From 5c8cafe44ac3e8605ecdd43751f29357ca3e57d3 Mon Sep 17 00:00:00 2001 From: Vadim Salavatov Date: Thu, 12 Feb 2026 16:25:51 +0100 Subject: [PATCH] IJPL-232707 refactor: extract MarketplacePluginsTabSearchResultPanel GitOrigin-RevId: 9896f9e89a5f9084f218ae2c70b0f601727a04b2 --- .../ide/plugins/MarketplacePluginsTab.java | 268 +--------------- ...arketplacePluginsTabSearchResultPanel.java | 299 ++++++++++++++++++ 2 files changed, 305 insertions(+), 262 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTabSearchResultPanel.java diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTab.java b/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTab.java index d590ba05956f..a35125139bdb 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTab.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTab.java @@ -3,13 +3,10 @@ package com.intellij.ide.plugins; import com.intellij.execution.process.ProcessIOExecutorService; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.icons.AllIcons; import com.intellij.ide.IdeBundle; import com.intellij.ide.impl.ProjectUtil; import com.intellij.ide.plugins.marketplace.PluginSearchResult; -import com.intellij.ide.plugins.marketplace.ranking.MarketplaceLocalRanker; import com.intellij.ide.plugins.marketplace.statistics.PluginManagerUsageCollector; -import com.intellij.ide.plugins.newui.LinkComponent; import com.intellij.ide.plugins.newui.ListPluginComponent; import com.intellij.ide.plugins.newui.MultiSelectionEventHandler; import com.intellij.ide.plugins.newui.NoOpPluginsViewCustomizer; @@ -17,7 +14,6 @@ import com.intellij.ide.plugins.newui.PluginDetailsPageComponent; import com.intellij.ide.plugins.newui.PluginInstallationState; import com.intellij.ide.plugins.newui.PluginLogo; import com.intellij.ide.plugins.newui.PluginManagerCustomizer; -import com.intellij.ide.plugins.newui.PluginModelAsyncOperationsExecutor; import com.intellij.ide.plugins.newui.PluginModelFacade; import com.intellij.ide.plugins.newui.PluginUiModel; import com.intellij.ide.plugins.newui.PluginUiModelAdapter; @@ -46,15 +42,12 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.FUSEventSource; -import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiserStartupActivityKt; import com.intellij.openapi.util.text.HtmlChunk; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.components.labels.LinkListener; -import com.intellij.ui.scale.JBUIScale; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.StatusText; @@ -64,21 +57,11 @@ import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jspecify.annotations.NonNull; -import javax.accessibility.AccessibleContext; -import javax.accessibility.AccessibleRole; -import javax.swing.Icon; import javax.swing.JComponent; -import javax.swing.SwingConstants; -import java.awt.Component; -import java.awt.Graphics; -import java.awt.Point; -import java.awt.event.KeyEvent; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; @@ -86,17 +69,13 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.applyUpdates; import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.clearUpdates; import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.createScrollPane; import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.registerCopyProvider; -import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.showRightBottomPopup; @ApiStatus.Internal class MarketplacePluginsTab extends PluginsTab { @@ -422,8 +401,8 @@ class MarketplacePluginsTab extends PluginsTab { Project project = ProjectUtil.getActiveProject(); - myMarketplaceSearchPanel = new MarketplaceSearchResultPanel(myCoroutineScope, marketplaceController, panel, project, selectionListener, - myMarketplaceSortByGroup, () -> myMarketplacePanel); + myMarketplaceSearchPanel = new MarketplacePluginsTabSearchResultPanel(myCoroutineScope, marketplaceController, panel, project, selectionListener, + myMarketplaceSortByGroup, () -> myMarketplacePanel); return myMarketplaceSearchPanel; } @@ -653,9 +632,10 @@ class MarketplacePluginsTab extends PluginsTab { } } - private final class MarketplaceSortByAction extends ToggleAction implements DumbAware { - private final MarketplaceTabSearchSortByOptions myOption; - private boolean myState; + @ApiStatus.Internal + final class MarketplaceSortByAction extends ToggleAction implements DumbAware { + final MarketplaceTabSearchSortByOptions myOption; + boolean myState; private boolean myVisible; private MarketplaceSortByAction(@NotNull MarketplaceTabSearchSortByOptions option) { @@ -702,240 +682,4 @@ class MarketplacePluginsTab extends PluginsTab { return SearchWords.SORT_BY.getValue() + myOption.getQuery(); } } - - private class MarketplaceSearchResultPanel extends SearchResultPanel { - private final Project myProject; - private final @NotNull Consumer mySelectionListener; - private final @NotNull DefaultActionGroup myMarketplaceSortByGroup; - private final @NotNull LinkComponent myMarketplaceSortByAction; - private final @NotNull Supplier myMarketplacePanelSupplier; - - MarketplaceSearchResultPanel(CoroutineScope coroutineScope, - SearchUpDownPopupController marketplaceController, - PluginsGroupComponentWithProgress panel, - Project project, - @NotNull Consumer selectionListener, - @NotNull DefaultActionGroup marketplaceSortByGroup, - @NotNull Supplier marketplacePanelSupplier) { - super(coroutineScope, marketplaceController, panel, true); - myProject = project; - mySelectionListener = selectionListener; - myMarketplaceSortByGroup = marketplaceSortByGroup; - myMarketplacePanelSupplier = marketplacePanelSupplier; - myMarketplaceSortByAction = createSortByAction(); - } - - private @NotNull LinkComponent createSortByAction() { - LinkComponent sortByAction = new LinkComponent() { - @Override - protected boolean isInClickableArea(Point pt) { - return true; - } - - @Override - public AccessibleContext getAccessibleContext() { - if (accessibleContext == null) { - accessibleContext = new AccessibleLinkComponent(); - } - return accessibleContext; - } - - protected class AccessibleLinkComponent extends AccessibleLinkLabel { - @Override - public AccessibleRole getAccessibleRole() { - return AccessibleRole.COMBO_BOX; - } - } - }; - - sortByAction.setIcon(new Icon() { - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - getIcon().paintIcon(c, g, x, y + 1); - } - - @Override - public int getIconWidth() { - return getIcon().getIconWidth(); - } - - @Override - public int getIconHeight() { - return getIcon().getIconHeight(); - } - - private static @NotNull Icon getIcon() { - return AllIcons.General.ButtonDropTriangle; - } - }); // TODO: icon - sortByAction.setPaintUnderline(false); - sortByAction.setIconTextGap(JBUIScale.scale(4)); - sortByAction.setHorizontalTextPosition(SwingConstants.LEFT); - sortByAction.setForeground(PluginsGroupComponent.SECTION_HEADER_FOREGROUND); - - //noinspection unchecked - sortByAction.setListener( - (component, __) -> showRightBottomPopup(component.getParent().getParent(), IdeBundle.message("plugins.configurable.sort.by"), - myMarketplaceSortByGroup), null); - - DumbAwareAction.create(event -> sortByAction.doClick()) - .registerCustomShortcutSet(KeyEvent.VK_DOWN, 0, sortByAction); - return sortByAction; - } - - @Override - @SuppressWarnings("unchecked") - protected void handleQuery(@NotNull String query, @NotNull PluginsGroup result, @NotNull AtomicBoolean runQuery) { - int searchIndex = PluginManagerUsageCollector.updateAndGetSearchIndex(); - - SearchQueryParser.Marketplace parser = new SearchQueryParser.Marketplace(query); - - Map pluginToScore = null; - - if (parser.internal) { - try { - PluginsViewCustomizer.PluginsGroupDescriptor groupDescriptor = - PluginsViewCustomizerKt.getPluginsViewCustomizer().getInternalPluginsGroupDescriptor(); - if (groupDescriptor != null) { - if (parser.searchQuery == null) { - result.addDescriptors(groupDescriptor.getPlugins()); - } - else { - for (IdeaPluginDescriptor pluginDescriptor : groupDescriptor.getPlugins()) { - if (StringUtil.containsIgnoreCase(pluginDescriptor.getName(), parser.searchQuery)) { - result.addDescriptor(pluginDescriptor); - } - } - } - result.removeDuplicates(); - result.sortByName(); - return; - } - } - catch (Exception e) { - LOG.error("Error while loading internal plugins group", e); - } - } - - PluginModelAsyncOperationsExecutor.INSTANCE.getCustomRepositoriesPluginMap(getCoroutineScope(), map -> { - Map> customRepositoriesMap = (Map>)map; - if (parser.suggested && myProject != null) { - List<@NotNull PluginUiModel> plugins = - PluginsAdvertiserStartupActivityKt.findSuggestedPlugins(myProject, customRepositoriesMap); - result.addModels(plugins); - updateSearchPanel(result, runQuery, plugins); - } - else if (!parser.repositories.isEmpty()) { - for (String repository : parser.repositories) { - List descriptors = customRepositoriesMap.get(repository); - if (descriptors == null) { - continue; - } - if (parser.searchQuery == null) { - result.addModels(descriptors); - } - else { - for (PluginUiModel descriptor : descriptors) { - if (StringUtil.containsIgnoreCase(descriptor.getName(), parser.searchQuery)) { - result.addModel(descriptor); - } - } - } - } - result.removeDuplicates(); - result.sortByName(); - updateSearchPanel(result, runQuery, result.getModels()); - } - else { - PluginModelAsyncOperationsExecutor.INSTANCE - .performMarketplaceSearch(getCoroutineScope(), - parser.getUrlQuery(), - !result.getModels().isEmpty(), - (searchResult, updates) -> { - applySearchResult(result, searchResult, (List)updates, customRepositoriesMap, - parser, pluginToScore, searchIndex); - updatePanel(runQuery); - return null; - }); - } - return null; - }); - } - - private void updateSearchPanel(@NonNull PluginsGroup result, AtomicBoolean runQuery, List<@NotNull PluginUiModel> plugins) { - Set ids = plugins.stream().map(it -> it.getPluginId()).collect(Collectors.toSet()); - result.getPreloadedModel().setInstalledPlugins(UiPluginManager.getInstance().findInstalledPluginsSync(ids)); - result.getPreloadedModel().setPluginInstallationStates(UiPluginManager.getInstance().getInstallationStatesSync()); - updatePanel(runQuery); - } - - private void applySearchResult(@NotNull PluginsGroup result, - PluginSearchResult searchResult, - List updates, - Map> customRepositoriesMap, - SearchQueryParser.Marketplace parser, - Map pluginToScore, - int searchIndex) { - if (searchResult.getError() != null) { - ApplicationManager.getApplication().invokeLater( - () -> myPanel.getEmptyText() - .setText(IdeBundle.message("plugins.configurable.search.result.not.loaded")) - .appendSecondaryText( - IdeBundle.message("plugins.configurable.check.internet"), - StatusText.DEFAULT_ATTRIBUTES, null), ModalityState.any() - ); - } - // compare plugin versions between marketplace & custom repositories - List customPlugins = ContainerUtil.flatten(customRepositoriesMap.values()); - Collection plugins = - RepositoryHelper.mergePluginModelsFromRepositories(searchResult.getPlugins(), - customPlugins, - false); - result.addModels(0, new ArrayList<>(plugins)); - - if (parser.searchQuery != null) { - List descriptors = ContainerUtil.filter(customPlugins, - descriptor -> StringUtil.containsIgnoreCase( - descriptor.getName(), - parser.searchQuery)); - result.addModels(0, descriptors); - } - - result.removeDuplicates(); - - final var localRanker = MarketplaceLocalRanker.getInstanceIfEnabled(); - if (localRanker != null) { - pluginToScore = localRanker.rankPlugins(parser, result.getModels()); - } - - if (!result.getModels().isEmpty()) { - String title = IdeBundle.message("plugin.manager.action.label.sort.by.1"); - - for (AnAction action : myMarketplaceSortByGroup.getChildren(ActionManager.getInstance())) { - MarketplaceSortByAction sortByAction = (MarketplaceSortByAction)action; - sortByAction.setState(parser); - if (sortByAction.myState) { - title = IdeBundle.message("plugin.manager.action.label.sort.by", - sortByAction.myOption.getPresentableNameSupplier().get()); - } - } - - myMarketplaceSortByAction.setText(title); - result.addSecondaryAction(myMarketplaceSortByAction); - - if (!ContainerUtil.isEmpty(updates)) { - myPostFillGroupCallback = () -> { - applyUpdates(myPanel, updates); - mySelectionListener.accept(myMarketplacePanelSupplier.get()); - mySelectionListener.accept(getPanel()); - }; - } - } - Set ids = result.getModels().stream().map(it -> it.getPluginId()).collect(Collectors.toSet()); - result.getPreloadedModel().setInstalledPlugins(UiPluginManager.getInstance().findInstalledPluginsSync(ids)); - result.getPreloadedModel().setPluginInstallationStates(UiPluginManager.getInstance().getInstallationStatesSync()); - PluginManagerUsageCollector.INSTANCE.performMarketplaceSearch(ProjectUtil.getActiveProject(), parser, result.getModels(), - searchIndex, pluginToScore); - } - } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTabSearchResultPanel.java b/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTabSearchResultPanel.java new file mode 100644 index 000000000000..2c8e5a90e33f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/plugins/MarketplacePluginsTabSearchResultPanel.java @@ -0,0 +1,299 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.plugins; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.IdeBundle; +import com.intellij.ide.impl.ProjectUtil; +import com.intellij.ide.plugins.marketplace.PluginSearchResult; +import com.intellij.ide.plugins.marketplace.ranking.MarketplaceLocalRanker; +import com.intellij.ide.plugins.marketplace.statistics.PluginManagerUsageCollector; +import com.intellij.ide.plugins.newui.LinkComponent; +import com.intellij.ide.plugins.newui.PluginModelAsyncOperationsExecutor; +import com.intellij.ide.plugins.newui.PluginUiModel; +import com.intellij.ide.plugins.newui.PluginsGroup; +import com.intellij.ide.plugins.newui.PluginsGroupComponent; +import com.intellij.ide.plugins.newui.PluginsGroupComponentWithProgress; +import com.intellij.ide.plugins.newui.PluginsViewCustomizer; +import com.intellij.ide.plugins.newui.PluginsViewCustomizerKt; +import com.intellij.ide.plugins.newui.SearchQueryParser; +import com.intellij.ide.plugins.newui.SearchResultPanel; +import com.intellij.ide.plugins.newui.SearchUpDownPopupController; +import com.intellij.ide.plugins.newui.UiPluginManager; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiserStartupActivityKt; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.scale.JBUIScale; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.StatusText; +import kotlinx.coroutines.CoroutineScope; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; + +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleRole; +import javax.swing.Icon; +import javax.swing.SwingConstants; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.applyUpdates; +import static com.intellij.ide.plugins.PluginManagerConfigurablePanel.showRightBottomPopup; + +@ApiStatus.Internal +class MarketplacePluginsTabSearchResultPanel extends SearchResultPanel { + private static final Logger LOG = Logger.getInstance(MarketplacePluginsTabSearchResultPanel.class); + + private final Project myProject; + private final @NotNull Consumer mySelectionListener; + private final @NotNull DefaultActionGroup myMarketplaceSortByGroup; + private final @NotNull LinkComponent myMarketplaceSortByAction; + private final @NotNull Supplier myMarketplacePanelSupplier; + + MarketplacePluginsTabSearchResultPanel(CoroutineScope coroutineScope, + SearchUpDownPopupController marketplaceController, + PluginsGroupComponentWithProgress panel, + Project project, + @NotNull Consumer selectionListener, + @NotNull DefaultActionGroup marketplaceSortByGroup, + @NotNull Supplier marketplacePanelSupplier) { + super(coroutineScope, marketplaceController, panel, true); + myProject = project; + mySelectionListener = selectionListener; + myMarketplaceSortByGroup = marketplaceSortByGroup; + myMarketplacePanelSupplier = marketplacePanelSupplier; + myMarketplaceSortByAction = createSortByAction(); + } + + private @NotNull LinkComponent createSortByAction() { + LinkComponent sortByAction = new LinkComponent() { + @Override + protected boolean isInClickableArea(Point pt) { + return true; + } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleLinkComponent(); + } + return accessibleContext; + } + + protected class AccessibleLinkComponent extends AccessibleLinkLabel { + @Override + public AccessibleRole getAccessibleRole() { + return AccessibleRole.COMBO_BOX; + } + } + }; + + sortByAction.setIcon(new Icon() { + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + getIcon().paintIcon(c, g, x, y + 1); + } + + @Override + public int getIconWidth() { + return getIcon().getIconWidth(); + } + + @Override + public int getIconHeight() { + return getIcon().getIconHeight(); + } + + private static @NotNull Icon getIcon() { + return AllIcons.General.ButtonDropTriangle; + } + }); // TODO: icon + sortByAction.setPaintUnderline(false); + sortByAction.setIconTextGap(JBUIScale.scale(4)); + sortByAction.setHorizontalTextPosition(SwingConstants.LEFT); + sortByAction.setForeground(PluginsGroupComponent.SECTION_HEADER_FOREGROUND); + + //noinspection unchecked + sortByAction.setListener( + (component, __) -> showRightBottomPopup(component.getParent().getParent(), IdeBundle.message("plugins.configurable.sort.by"), + myMarketplaceSortByGroup), null); + + DumbAwareAction.create(event -> sortByAction.doClick()) + .registerCustomShortcutSet(KeyEvent.VK_DOWN, 0, sortByAction); + return sortByAction; + } + + @Override + @SuppressWarnings("unchecked") + protected void handleQuery(@NotNull String query, @NotNull PluginsGroup result, @NotNull AtomicBoolean runQuery) { + int searchIndex = PluginManagerUsageCollector.updateAndGetSearchIndex(); + + SearchQueryParser.Marketplace parser = new SearchQueryParser.Marketplace(query); + + Map pluginToScore = null; + + if (parser.internal) { + try { + PluginsViewCustomizer.PluginsGroupDescriptor groupDescriptor = + PluginsViewCustomizerKt.getPluginsViewCustomizer().getInternalPluginsGroupDescriptor(); + if (groupDescriptor != null) { + if (parser.searchQuery == null) { + result.addDescriptors(groupDescriptor.getPlugins()); + } + else { + for (IdeaPluginDescriptor pluginDescriptor : groupDescriptor.getPlugins()) { + if (StringUtil.containsIgnoreCase(pluginDescriptor.getName(), parser.searchQuery)) { + result.addDescriptor(pluginDescriptor); + } + } + } + result.removeDuplicates(); + result.sortByName(); + return; + } + } + catch (Exception e) { + LOG.error("Error while loading internal plugins group", e); + } + } + + PluginModelAsyncOperationsExecutor.INSTANCE.getCustomRepositoriesPluginMap(getCoroutineScope(), map -> { + Map> customRepositoriesMap = (Map>)map; + if (parser.suggested && myProject != null) { + List<@NotNull PluginUiModel> plugins = + PluginsAdvertiserStartupActivityKt.findSuggestedPlugins(myProject, customRepositoriesMap); + result.addModels(plugins); + updateSearchPanel(result, runQuery, plugins); + } + else if (!parser.repositories.isEmpty()) { + for (String repository : parser.repositories) { + List descriptors = customRepositoriesMap.get(repository); + if (descriptors == null) { + continue; + } + if (parser.searchQuery == null) { + result.addModels(descriptors); + } + else { + for (PluginUiModel descriptor : descriptors) { + if (StringUtil.containsIgnoreCase(descriptor.getName(), parser.searchQuery)) { + result.addModel(descriptor); + } + } + } + } + result.removeDuplicates(); + result.sortByName(); + updateSearchPanel(result, runQuery, result.getModels()); + } + else { + PluginModelAsyncOperationsExecutor.INSTANCE + .performMarketplaceSearch(getCoroutineScope(), + parser.getUrlQuery(), + !result.getModels().isEmpty(), + (searchResult, updates) -> { + applySearchResult(result, searchResult, (List)updates, customRepositoriesMap, + parser, pluginToScore, searchIndex); + updatePanel(runQuery); + return null; + }); + } + return null; + }); + } + + private void updateSearchPanel(@NonNull PluginsGroup result, AtomicBoolean runQuery, List<@NotNull PluginUiModel> plugins) { + Set ids = plugins.stream().map(it -> it.getPluginId()).collect(Collectors.toSet()); + result.getPreloadedModel().setInstalledPlugins(UiPluginManager.getInstance().findInstalledPluginsSync(ids)); + result.getPreloadedModel().setPluginInstallationStates(UiPluginManager.getInstance().getInstallationStatesSync()); + updatePanel(runQuery); + } + + private void applySearchResult(@NotNull PluginsGroup result, + PluginSearchResult searchResult, + List updates, + Map> customRepositoriesMap, + SearchQueryParser.Marketplace parser, + Map pluginToScore, + int searchIndex) { + if (searchResult.getError() != null) { + ApplicationManager.getApplication().invokeLater( + () -> myPanel.getEmptyText() + .setText(IdeBundle.message("plugins.configurable.search.result.not.loaded")) + .appendSecondaryText( + IdeBundle.message("plugins.configurable.check.internet"), + StatusText.DEFAULT_ATTRIBUTES, null), ModalityState.any() + ); + } + // compare plugin versions between marketplace & custom repositories + List customPlugins = ContainerUtil.flatten(customRepositoriesMap.values()); + Collection plugins = + RepositoryHelper.mergePluginModelsFromRepositories(searchResult.getPlugins(), + customPlugins, + false); + result.addModels(0, new ArrayList<>(plugins)); + + if (parser.searchQuery != null) { + List descriptors = ContainerUtil.filter(customPlugins, + descriptor -> StringUtil.containsIgnoreCase( + descriptor.getName(), + parser.searchQuery)); + result.addModels(0, descriptors); + } + + result.removeDuplicates(); + + final var localRanker = MarketplaceLocalRanker.getInstanceIfEnabled(); + if (localRanker != null) { + pluginToScore = localRanker.rankPlugins(parser, result.getModels()); + } + + if (!result.getModels().isEmpty()) { + String title = IdeBundle.message("plugin.manager.action.label.sort.by.1"); + + for (AnAction action : myMarketplaceSortByGroup.getChildren(ActionManager.getInstance())) { + MarketplacePluginsTab.MarketplaceSortByAction sortByAction = (MarketplacePluginsTab.MarketplaceSortByAction)action; + sortByAction.setState(parser); + if (sortByAction.myState) { + title = IdeBundle.message("plugin.manager.action.label.sort.by", + sortByAction.myOption.getPresentableNameSupplier().get()); + } + } + + myMarketplaceSortByAction.setText(title); + result.addSecondaryAction(myMarketplaceSortByAction); + + if (!ContainerUtil.isEmpty(updates)) { + myPostFillGroupCallback = () -> { + applyUpdates(myPanel, updates); + mySelectionListener.accept(myMarketplacePanelSupplier.get()); + mySelectionListener.accept(getPanel()); + }; + } + } + Set ids = result.getModels().stream().map(it -> it.getPluginId()).collect(Collectors.toSet()); + result.getPreloadedModel().setInstalledPlugins(UiPluginManager.getInstance().findInstalledPluginsSync(ids)); + result.getPreloadedModel().setPluginInstallationStates(UiPluginManager.getInstance().getInstallationStatesSync()); + PluginManagerUsageCollector.INSTANCE.performMarketplaceSearch(ProjectUtil.getActiveProject(), parser, result.getModels(), + searchIndex, pluginToScore); + } +} \ No newline at end of file