IJPL-232707 fix search result duplication, and updates not showing up in the marketplace tab when search is used

it turns out updatePanel adds a new search group result...
get rid of myPostFillGroupCallback, add updates info asynchronously instead

GitOrigin-RevId: 4327a2306825e5a244dd83f6d561a47597c665f2
This commit is contained in:
Vadim Salavatov
2026-02-14 21:15:14 +00:00
committed by intellij-monorepo-bot
parent 326de65c20
commit ad6fcb2006
4 changed files with 22 additions and 38 deletions
@@ -192,13 +192,11 @@ internal class InstalledPluginsTabSearchResultPanel(
coroutineScope.launch {
PluginModelAsyncOperationsExecutor.loadUpdates().let { updates ->
if (!ContainerUtil.isEmpty(updates)) {
myPostFillGroupCallback = Runnable {
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
PluginManagerConfigurablePanel.applyUpdates(myPanel, updates)
mySelectionListener.accept(myInstalledPanelSupplier.get())
mySelectionListener.accept(panel)
}
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
updatePanel()
fullRepaint()
}
}
}
@@ -23,7 +23,9 @@ import com.intellij.ide.plugins.newui.getPluginsViewCustomizer
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.asContextElement
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.project.Project
@@ -35,6 +37,9 @@ import com.intellij.ui.scale.JBUIScale.scale
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.ui.StatusText
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jetbrains.annotations.ApiStatus
import java.awt.Component
import java.awt.Graphics
@@ -174,15 +179,23 @@ internal class MarketplacePluginsTabSearchResultPanel(
}
else {
PluginModelAsyncOperationsExecutor
.performMarketplaceSearch(
parser.urlQuery,
!result.getModels().isEmpty()
).let { (searchResult, updates) ->
.performMarketplaceSearch(parser.urlQuery).let { searchResult ->
applySearchResult(
result, searchResult, updates, customRepositoriesMap,
result, searchResult, customRepositoriesMap,
parser, searchIndex
)
updatePanel()
coroutineScope.launch(Dispatchers.IO) {
val updates = PluginModelAsyncOperationsExecutor.loadUpdates()
if (updates.isNotEmpty()) {
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
PluginManagerConfigurablePanel.applyUpdates(myPanel, updates)
mySelectionListener.accept(myMarketplacePanelSupplier.get())
mySelectionListener.accept(panel)
fullRepaint()
}
}
}
}
}
}
@@ -198,7 +211,6 @@ internal class MarketplacePluginsTabSearchResultPanel(
private fun applySearchResult(
result: PluginsGroup,
searchResult: PluginSearchResult,
updates: List<PluginUiModel?>,
customRepositoriesMap: Map<String, List<PluginUiModel>>,
parser: SearchQueryParser.Marketplace,
searchIndex: Int,
@@ -259,14 +271,6 @@ internal class MarketplacePluginsTabSearchResultPanel(
myMarketplaceSortByAction.setText(title)
result.addSecondaryAction(myMarketplaceSortByAction)
if (!ContainerUtil.isEmpty<PluginUiModel?>(updates)) {
myPostFillGroupCallback = Runnable {
PluginManagerConfigurablePanel.applyUpdates(myPanel, updates)
mySelectionListener.accept(myMarketplacePanelSupplier.get())
mySelectionListener.accept(panel)
}
}
}
val ids = result.getModels().mapTo(LinkedHashSet()) { it.pluginId }
result.getPreloadedModel().setInstalledPlugins(getInstance().findInstalledPluginsSync(ids))
@@ -45,16 +45,10 @@ internal object PluginModelAsyncOperationsExecutor {
suspend fun performMarketplaceSearch(
query: String,
loadUpdates: Boolean,
): Pair<PluginSearchResult, List<PluginUiModel>> {
): PluginSearchResult {
return withContext(Dispatchers.IO) {
val pluginManager = UiPluginManager.getInstance()
val result = pluginManager.executeMarketplaceQuery(query, 10000, true)
val updates = mutableListOf<PluginUiModel>()
if (loadUpdates) {
updates.addAll(pluginManager.getUpdateModels())
}
result to updates
pluginManager.executeMarketplaceQuery(query, 10000, true)
}
}
@@ -5,7 +5,6 @@ import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.PluginsGroupType
import com.intellij.ide.plugins.newui.PluginLogo.endBatchMode
import com.intellij.ide.plugins.newui.PluginLogo.startBatchMode
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.asContextElement
@@ -24,7 +23,6 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jetbrains.annotations.ApiStatus
import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.JComponent
import javax.swing.JScrollBar
import javax.swing.ScrollPaneConstants
@@ -45,8 +43,6 @@ abstract class SearchResultPanel(
private var isLoading = false
private var myAnnounceSearchResultsAlarm: SingleAlarm? = null
@JvmField protected var myPostFillGroupCallback: Runnable? = null
init {
myPanel.getAccessibleContext().setAccessibleName(IdeBundle.message("title.search.results"))
group = PluginsGroup(
@@ -138,20 +134,12 @@ abstract class SearchResultPanel(
announceSearchResultsWithDelay()
myPanel.initialSelection(false)
runPostFillGroupCallback()
fullRepaint()
}
}
protected abstract suspend fun handleQuery(query: String, result: PluginsGroup)
private fun runPostFillGroupCallback() {
if (myPostFillGroupCallback != null) {
myPostFillGroupCallback!!.run()
myPostFillGroupCallback = null
}
}
private fun loading(start: Boolean) {
val panel = myPanel
if (start) {