diff --git a/platform/searchEverywhere/backend/src/impl/SeBackendService.kt b/platform/searchEverywhere/backend/src/impl/SeBackendService.kt index 752352da3824..1cf767215424 100644 --- a/platform/searchEverywhere/backend/src/impl/SeBackendService.kt +++ b/platform/searchEverywhere/backend/src/impl/SeBackendService.kt @@ -18,10 +18,8 @@ import com.intellij.platform.searchEverywhere.providers.SeProvidersHolder import com.intellij.platform.searchEverywhere.providers.target.SeTypeVisibilityStatePresentation import com.jetbrains.rhizomedb.EID import fleet.kernel.DurableRef -import fleet.kernel.change import fleet.kernel.onDispose import fleet.kernel.rete.Rete -import fleet.kernel.shared import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.ReceiveChannel @@ -183,22 +181,9 @@ class SeBackendService(val project: Project, private val coroutineScope: Corouti val providersHolder = getProvidersHolder(sessionRef, dataContextId) if (providersHolder == null) return false - coroutineScope.launch { - try { - SeFindToolWindowManager(project).openInFindToolWindow( - providerIds, params, isAllTab, providersHolder, projectId, - ) - } - finally { - withContext(NonCancellable) { - change { - shared { - sessionRef.derefOrNull()?.delete() - } - } - } - } - } + SeFindToolWindowManager(project).openInFindToolWindow( + providerIds, params, isAllTab, providersHolder, projectId, + ) return true } diff --git a/platform/searchEverywhere/backend/src/impl/SeFindToolWindowManager.kt b/platform/searchEverywhere/backend/src/impl/SeFindToolWindowManager.kt index f6b8613779aa..6f706bbfef2e 100644 --- a/platform/searchEverywhere/backend/src/impl/SeFindToolWindowManager.kt +++ b/platform/searchEverywhere/backend/src/impl/SeFindToolWindowManager.kt @@ -50,7 +50,7 @@ class SeFindToolWindowManager(private val project: Project) { projectId: ProjectId, ) { val contributorsString = providerIds.mapNotNull { providerId -> - providersHolder.get(providerId, false)?.displayName + providersHolder.get(providerId, isAllTab)?.displayName }.joinToString(separator = ", ") val presentation = UsageViewPresentation() val tabCaptionText = IdeBundle.message("searcheverywhere.found.matches.title", params.inputQuery, contributorsString) diff --git a/platform/searchEverywhere/frontend/src/SeFrontendService.kt b/platform/searchEverywhere/frontend/src/SeFrontendService.kt index 6aa4a2abf6ba..dcf983454e24 100644 --- a/platform/searchEverywhere/frontend/src/SeFrontendService.kt +++ b/platform/searchEverywhere/frontend/src/SeFrontendService.kt @@ -1 +1 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.searchEverywhere.frontend import com.intellij.ide.actions.SearchEverywhereManagerFactory import com.intellij.ide.actions.searcheverywhere.* import com.intellij.ide.actions.searcheverywhere.statistics.SearchEverywhereUsageTriggerCollector import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.EDT import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.ui.popup.JBPopup import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.util.Disposer import com.intellij.platform.searchEverywhere.SeSessionEntity import com.intellij.platform.searchEverywhere.frontend.tabs.actions.SeActionsTab import com.intellij.platform.searchEverywhere.frontend.tabs.all.SeAllTab import com.intellij.platform.searchEverywhere.frontend.tabs.classes.SeClassesTab import com.intellij.platform.searchEverywhere.frontend.tabs.files.SeFilesTab import com.intellij.platform.searchEverywhere.frontend.tabs.symbols.SeSymbolsTab import com.intellij.platform.searchEverywhere.frontend.tabs.text.SeTextTab import com.intellij.platform.searchEverywhere.frontend.ui.SePopupContentPane import com.intellij.platform.searchEverywhere.frontend.vm.SePopupVm import com.intellij.platform.searchEverywhere.providers.SeLog import com.intellij.platform.searchEverywhere.providers.SeLog.LIFE_CYCLE import com.intellij.platform.searchEverywhere.providers.SeProvidersHolder import com.intellij.platform.searchEverywhere.providers.computeCatchingOrNull import com.intellij.platform.searchEverywhere.utils.SuspendLazyProperty import com.intellij.platform.searchEverywhere.utils.initAsync import com.intellij.platform.util.coroutines.childScope import com.intellij.platform.util.coroutines.sync.OverflowSemaphore import com.intellij.util.ui.StartupUiUtil import fleet.kernel.DurableRef import fleet.kernel.change import fleet.kernel.shared import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import org.jetbrains.annotations.ApiStatus import java.awt.KeyboardFocusManager import java.util.concurrent.atomic.AtomicBoolean @ApiStatus.Internal @Service(Service.Level.PROJECT, Service.Level.APP) class SeFrontendService(val project: Project?, private val coroutineScope: CoroutineScope) : SearchEverywhereManager { @Suppress("unused") constructor(coroutineScope: CoroutineScope) : this(null, coroutineScope) private val popupSemaphore = OverflowSemaphore(1, overflow = BufferOverflow.DROP_LATEST) @Volatile private var popupInstance: SePopupInstance? = null @Volatile var localProvidersHolder: SeProvidersHolder? = null private set private val historyList = SearchHistoryList(true) val removeSessionRef: AtomicBoolean = AtomicBoolean(true) override fun show(tabId: String, searchText: String?, initEvent: AnActionEvent) { coroutineScope.launch { val popupScope = coroutineScope.childScope("SearchEverywhereFrontendService popup scope") val sessionRef = SeSessionEntity.createRef() try { popupSemaphore.withPermit { localProvidersHolder = SeProvidersHolder.initialize(initEvent, project, sessionRef, "Frontend") val completable = doShowPopup(tabId, searchText, initEvent, popupScope, sessionRef) completable.await() } } finally { popupInstance = null localProvidersHolder?.let { Disposer.dispose(it) } localProvidersHolder = null withContext(NonCancellable) { popupScope.cancel() if (removeSessionRef.get()) { change { shared { sessionRef.derefOrNull()?.delete() } } } } } } } private suspend fun doShowPopup( tabId: String, searchText: String?, initEvent: AnActionEvent, popupScope: CoroutineScope, sessionRef: DurableRef, ): CompletableDeferred { val startTime = System.currentTimeMillis() val tabInitializationTimoutMillis: Long = 50 val tabFactories = SeTabFactory.EP_NAME.extensionList val orderedTabFactoryIds = tabFactories.map { it.id } val tabsOrDeferredTabs = tabFactories.map { it.id to initAsync(popupScope) { computeCatchingOrNull({ e -> "Error while getting tab from ${it.id} tab factory: ${e.message}" }) { it.getTab(popupScope, project, sessionRef, initEvent) } } }.map { (loadingTabId, tabLoadingProperty) -> popupScope.async { withTimeoutOrNull(tabInitializationTimoutMillis) { tabLoadingProperty.getValue() } ?: run { if ((tabId + MAIN_TABS).contains(loadingTabId)) { SeLog.warn("Tab $tabId initialization took too long (> ${tabInitializationTimoutMillis}ms), waiting it's initialization anyway") // If we have to open this tab right after the popup is there, we wait until it gets initialized tabLoadingProperty.getValue() } else { SeLog.log(LIFE_CYCLE) { "Tab $tabId initialization took too long (> ${tabInitializationTimoutMillis}ms), will be initialized later" } tabLoadingProperty } } } }.awaitAll() val tabs = tabsOrDeferredTabs.filterIsInstance().sortedWith { tab1, tab2 -> val order1 = orderedTabFactoryIds.indexOf(tab1.id).let { if (it == -1) orderedTabFactoryIds.size + 1 else it } val order2 = orderedTabFactoryIds.indexOf(tab2.id).let { if (it == -1) orderedTabFactoryIds.size + 1 else it } order1 - order2 } val deferredTabs = tabsOrDeferredTabs.filterIsInstance>() var popup: JBPopup? = null val popupVm = SePopupVm(popupScope, project, sessionRef, tabs, deferredTabs, searchText, tabId, historyList) { popup?.cancel() popup = null } popupVm.showTab(tabId) val completable = CompletableDeferred() withContext(Dispatchers.EDT) { val contentPane = SePopupContentPane(project, popupVm) { popupScope.launch(NonCancellable) { removeSessionRef.set(false) popupVm.openInFindWindow(sessionRef, initEvent) } } popup = createPopup(contentPane, popupVm, project) { completable.complete(Unit) } if (project == null) popup?.showInCenterOf(KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow) else popup?.showCenteredInCurrentWindow(project) popupInstance = SePopupInstance(popupVm, contentPane) val endTime = System.currentTimeMillis() SeLog.log { "Search Everywhere popup opened in ${endTime - startTime} ms" } } return completable } private fun createPopup(panel: SePopupContentPane, popupVm: SePopupVm, project: Project?, onCancel: () -> Unit): JBPopup { val popup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, panel.preferableFocusedComponent) .setProject(project) .setModalContext(false) .setNormalWindowLevel(StartupUiUtil.isWaylandToolkit()) .setCancelOnClickOutside(true) .setRequestFocus(true) .setCancelKeyEnabled(false) .setResizable(true) .setMovable(true) .setDimensionServiceKey(project, POPUP_LOCATION_SETTINGS_KEY, true) .setLocateWithinScreenBounds(false) .setCancelCallback { popupVm.saveSearchText() onCancel() SearchEverywhereUsageTriggerCollector.DIALOG_CLOSED.log(project, true) true } .createPopup() Disposer.register(popup, panel) return popup } override fun isShown(): Boolean = popupInstance != null @Deprecated("Deprecated in the interface") override fun getCurrentlyShownUI(): SearchEverywhereUI { throw UnsupportedOperationException("The method is deprecated. Please use getCurrentlyShownPopupInstance() instead.") } override fun getCurrentlyShownPopupInstance(): SearchEverywherePopupInstance? = popupInstance override fun getSelectedTabID(): String = popupInstance?.getSelectedTabID() ?: "" override fun setSelectedTabID(tabID: String) { popupInstance?.setSelectedTabID(tabID) } override fun toggleEverywhereFilter() { popupInstance?.toggleEverywhereFilter() } override fun isEverywhere(): Boolean = popupInstance?.isEverywhere() ?: false @ApiStatus.Internal override fun isSplit(): Boolean = true companion object { @JvmStatic fun getInstance(project: Project?): SeFrontendService = project?.getService(SeFrontendService::class.java) ?: service() @JvmStatic val isEnabled: Boolean get() = SearchEverywhereFeature.isSplit private const val POPUP_LOCATION_SETTINGS_KEY: String = "search.everywhere.popup" private val MAIN_TABS = setOf(SeAllTab.ID, SeFilesTab.ID, SeClassesTab.ID, SeSymbolsTab.ID, SeActionsTab.ID, SeTextTab.ID) } } @ApiStatus.Internal class RemDevFriendlySearchEverywhereManager : SearchEverywhereManagerFactory { override fun isAvailable(): Boolean = SeFrontendService.isEnabled override fun getManager(project: Project?): SearchEverywhereManager = SeFrontendService.getInstance(project) } \ No newline at end of file +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.platform.searchEverywhere.frontend import com.intellij.ide.actions.SearchEverywhereManagerFactory import com.intellij.ide.actions.searcheverywhere.* import com.intellij.ide.actions.searcheverywhere.statistics.SearchEverywhereUsageTriggerCollector import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.EDT import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.project.Project import com.intellij.openapi.ui.popup.JBPopup import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.util.Disposer import com.intellij.platform.searchEverywhere.SeSessionEntity import com.intellij.platform.searchEverywhere.frontend.tabs.actions.SeActionsTab import com.intellij.platform.searchEverywhere.frontend.tabs.all.SeAllTab import com.intellij.platform.searchEverywhere.frontend.tabs.classes.SeClassesTab import com.intellij.platform.searchEverywhere.frontend.tabs.files.SeFilesTab import com.intellij.platform.searchEverywhere.frontend.tabs.symbols.SeSymbolsTab import com.intellij.platform.searchEverywhere.frontend.tabs.text.SeTextTab import com.intellij.platform.searchEverywhere.frontend.ui.SePopupContentPane import com.intellij.platform.searchEverywhere.frontend.vm.SePopupVm import com.intellij.platform.searchEverywhere.providers.SeLog import com.intellij.platform.searchEverywhere.providers.SeLog.LIFE_CYCLE import com.intellij.platform.searchEverywhere.providers.SeProvidersHolder import com.intellij.platform.searchEverywhere.providers.computeCatchingOrNull import com.intellij.platform.searchEverywhere.utils.SuspendLazyProperty import com.intellij.platform.searchEverywhere.utils.initAsync import com.intellij.platform.util.coroutines.childScope import com.intellij.platform.util.coroutines.sync.OverflowSemaphore import com.intellij.util.ui.StartupUiUtil import fleet.kernel.DurableRef import fleet.kernel.change import fleet.kernel.shared import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import org.jetbrains.annotations.ApiStatus import java.awt.KeyboardFocusManager import java.util.concurrent.atomic.AtomicBoolean @ApiStatus.Internal @Service(Service.Level.PROJECT, Service.Level.APP) class SeFrontendService(val project: Project?, private val coroutineScope: CoroutineScope) : SearchEverywhereManager { @Suppress("unused") constructor(coroutineScope: CoroutineScope) : this(null, coroutineScope) private val popupSemaphore = OverflowSemaphore(1, overflow = BufferOverflow.DROP_LATEST) @Volatile private var popupInstance: SePopupInstance? = null @Volatile var localProvidersHolder: SeProvidersHolder? = null private set private val historyList = SearchHistoryList(true) val removeSessionRef: AtomicBoolean = AtomicBoolean(true) override fun show(tabId: String, searchText: String?, initEvent: AnActionEvent) { coroutineScope.launch { val popupScope = coroutineScope.childScope("SearchEverywhereFrontendService popup scope") val sessionRef = SeSessionEntity.createRef() try { popupSemaphore.withPermit { localProvidersHolder = SeProvidersHolder.initialize(initEvent, project, sessionRef, "Frontend") val completable = doShowPopup(tabId, searchText, initEvent, popupScope, sessionRef) completable.await() } } finally { popupInstance = null localProvidersHolder?.let { Disposer.dispose(it) } localProvidersHolder = null withContext(NonCancellable) { popupScope.cancel() if (removeSessionRef.get()) { change { shared { sessionRef.derefOrNull()?.delete() } } } } } } } private suspend fun doShowPopup( tabId: String, searchText: String?, initEvent: AnActionEvent, popupScope: CoroutineScope, sessionRef: DurableRef, ): CompletableDeferred { val startTime = System.currentTimeMillis() val tabInitializationTimoutMillis: Long = 50 val tabFactories = SeTabFactory.EP_NAME.extensionList val orderedTabFactoryIds = tabFactories.map { it.id } val tabsOrDeferredTabs = tabFactories.map { it.id to initAsync(popupScope) { computeCatchingOrNull({ e -> "Error while getting tab from ${it.id} tab factory: ${e.message}" }) { it.getTab(popupScope, project, sessionRef, initEvent) } } }.map { (loadingTabId, tabLoadingProperty) -> popupScope.async { withTimeoutOrNull(tabInitializationTimoutMillis) { tabLoadingProperty.getValue() } ?: run { if ((tabId + MAIN_TABS).contains(loadingTabId)) { SeLog.warn("Tab $tabId initialization took too long (> ${tabInitializationTimoutMillis}ms), waiting it's initialization anyway") // If we have to open this tab right after the popup is there, we wait until it gets initialized tabLoadingProperty.getValue() } else { SeLog.log(LIFE_CYCLE) { "Tab $tabId initialization took too long (> ${tabInitializationTimoutMillis}ms), will be initialized later" } tabLoadingProperty } } } }.awaitAll() val tabs = tabsOrDeferredTabs.filterIsInstance().sortedWith { tab1, tab2 -> val order1 = orderedTabFactoryIds.indexOf(tab1.id).let { if (it == -1) orderedTabFactoryIds.size + 1 else it } val order2 = orderedTabFactoryIds.indexOf(tab2.id).let { if (it == -1) orderedTabFactoryIds.size + 1 else it } order1 - order2 } val deferredTabs = tabsOrDeferredTabs.filterIsInstance>() var popup: JBPopup? = null val popupVm = SePopupVm(popupScope, project, sessionRef, tabs, deferredTabs, searchText, tabId, historyList) { popup?.cancel() popup = null } popupVm.showTab(tabId) val completable = CompletableDeferred() withContext(Dispatchers.EDT) { val contentPane = SePopupContentPane(project, popupVm) { popupScope.launch(NonCancellable) { removeSessionRef.set(false) try { popupVm.openInFindWindow(sessionRef, initEvent) } finally { change { shared { sessionRef.derefOrNull()?.delete() } } } } popupScope.cancel() } popup = createPopup(contentPane, popupVm, project) { completable.complete(Unit) } if (project == null) popup?.showInCenterOf(KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow) else popup?.showCenteredInCurrentWindow(project) popupInstance = SePopupInstance(popupVm, contentPane) val endTime = System.currentTimeMillis() SeLog.log { "Search Everywhere popup opened in ${endTime - startTime} ms" } } return completable } private fun createPopup(panel: SePopupContentPane, popupVm: SePopupVm, project: Project?, onCancel: () -> Unit): JBPopup { val popup = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, panel.preferableFocusedComponent) .setProject(project) .setModalContext(false) .setNormalWindowLevel(StartupUiUtil.isWaylandToolkit()) .setCancelOnClickOutside(true) .setRequestFocus(true) .setCancelKeyEnabled(false) .setResizable(true) .setMovable(true) .setDimensionServiceKey(project, POPUP_LOCATION_SETTINGS_KEY, true) .setLocateWithinScreenBounds(false) .setCancelCallback { popupVm.saveSearchText() onCancel() SearchEverywhereUsageTriggerCollector.DIALOG_CLOSED.log(project, true) true } .createPopup() Disposer.register(popup, panel) return popup } override fun isShown(): Boolean = popupInstance != null @Deprecated("Deprecated in the interface") override fun getCurrentlyShownUI(): SearchEverywhereUI { throw UnsupportedOperationException("The method is deprecated. Please use getCurrentlyShownPopupInstance() instead.") } override fun getCurrentlyShownPopupInstance(): SearchEverywherePopupInstance? = popupInstance override fun getSelectedTabID(): String = popupInstance?.getSelectedTabID() ?: "" override fun setSelectedTabID(tabID: String) { popupInstance?.setSelectedTabID(tabID) } override fun toggleEverywhereFilter() { popupInstance?.toggleEverywhereFilter() } override fun isEverywhere(): Boolean = popupInstance?.isEverywhere() ?: false @ApiStatus.Internal override fun isSplit(): Boolean = true companion object { @JvmStatic fun getInstance(project: Project?): SeFrontendService = project?.getService(SeFrontendService::class.java) ?: service() @JvmStatic val isEnabled: Boolean get() = SearchEverywhereFeature.isSplit private const val POPUP_LOCATION_SETTINGS_KEY: String = "search.everywhere.popup" private val MAIN_TABS = setOf(SeAllTab.ID, SeFilesTab.ID, SeClassesTab.ID, SeSymbolsTab.ID, SeActionsTab.ID, SeTextTab.ID) } } @ApiStatus.Internal class RemDevFriendlySearchEverywhereManager : SearchEverywhereManagerFactory { override fun isAvailable(): Boolean = SeFrontendService.isEnabled override fun getManager(project: Project?): SearchEverywhereManager = SeFrontendService.getInstance(project) } \ No newline at end of file diff --git a/platform/searchEverywhere/frontend/src/tabs/text/SeTextFilterEditor.kt b/platform/searchEverywhere/frontend/src/tabs/text/SeTextFilterEditor.kt index e22d1eaf19c9..70f731b06cf5 100644 --- a/platform/searchEverywhere/frontend/src/tabs/text/SeTextFilterEditor.kt +++ b/platform/searchEverywhere/frontend/src/tabs/text/SeTextFilterEditor.kt @@ -7,16 +7,16 @@ import com.intellij.find.impl.JComboboxAction import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.project.Project import com.intellij.platform.searchEverywhere.SeSearchScopesInfo -import com.intellij.platform.searchEverywhere.frontend.SeFilterActionsPresentation -import com.intellij.platform.searchEverywhere.frontend.SeFilterPresentation import com.intellij.platform.searchEverywhere.frontend.tabs.target.SeScopeChooserActionProvider import com.intellij.platform.searchEverywhere.frontend.tabs.utils.SeFilterEditorBase import com.intellij.platform.searchEverywhere.providers.SeTextFilter import org.jetbrains.annotations.ApiStatus @ApiStatus.Internal -class SeTextFilterEditor(private val project: Project?, - private val scopesInfo: SeSearchScopesInfo?) : SeFilterEditorBase( +class SeTextFilterEditor( + private val project: Project?, + private val scopesInfo: SeSearchScopesInfo?, +) : SeFilterEditorBase( SeTextFilter(scopesInfo?.selectedScopeId, null) ) { private val scopeFilterAction: AnAction? = scopesInfo?.let { @@ -45,9 +45,5 @@ class SeTextFilterEditor(private val project: Project?, return typesFilterAction } - override fun getPresentation(): SeFilterPresentation { - return object : SeFilterActionsPresentation { - override fun getActions(): List = listOfNotNull(getScopeFilterAction(), getTypeFilterAction()) - } - } + override fun getActions(): List = listOfNotNull(getScopeFilterAction(), getTypeFilterAction()) } \ No newline at end of file diff --git a/platform/searchEverywhere/frontend/src/tabs/text/SeTextTabEmptyResultInfoProvider.kt b/platform/searchEverywhere/frontend/src/tabs/text/SeTextTabEmptyResultInfoProvider.kt index 71b74ddf1d86..5882641bb39f 100644 --- a/platform/searchEverywhere/frontend/src/tabs/text/SeTextTabEmptyResultInfoProvider.kt +++ b/platform/searchEverywhere/frontend/src/tabs/text/SeTextTabEmptyResultInfoProvider.kt @@ -9,7 +9,6 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.text.StringUtil import com.intellij.platform.searchEverywhere.frontend.SeEmptyResultInfo import com.intellij.platform.searchEverywhere.frontend.SeEmptyResultInfoChunk -import com.intellij.platform.searchEverywhere.frontend.SeFilterActionsPresentation import com.intellij.psi.search.EverythingGlobalScope import com.intellij.ui.SimpleTextAttributes import org.jetbrains.annotations.ApiStatus @@ -46,7 +45,7 @@ class SeTextTabEmptyResultInfoProvider( } private val toggleScopeAction: SearchEverywhereToggleAction? - get() = (filterEditor?.getPresentation() as? SeFilterActionsPresentation)?.getActions()?.firstOrNull { + get() = filterEditor?.getActions()?.firstOrNull { it is SearchEverywhereToggleAction } as? SearchEverywhereToggleAction diff --git a/platform/searchEverywhere/frontend/src/vm/SePopupVm.kt b/platform/searchEverywhere/frontend/src/vm/SePopupVm.kt index c9ddbc45545b..569792682f61 100644 --- a/platform/searchEverywhere/frontend/src/vm/SePopupVm.kt +++ b/platform/searchEverywhere/frontend/src/vm/SePopupVm.kt @@ -45,6 +45,9 @@ class SePopupVm( val currentTab: SeTabVm get() = tabVms[currentTabIndex.value.coerceIn(tabVms.indices)] val currentTabFlow: Flow + private val canBeShownInFindResultsFlow = MutableStateFlow(false) + val canBeShownInFindResults: Boolean get() = canBeShownInFindResultsFlow.value + private var historyIterator: HistoryIterator = historyList.getIterator(currentTab.tabId) get() { val selectedContributorID = currentTab.tabId @@ -82,6 +85,12 @@ class SePopupVm( } } + coroutineScope.launch { + currentTabFlow.collect { tabVm -> + canBeShownInFindResultsFlow.update { tabVm.canBeShownInFindResults() } + } + } + deferredTabs.forEach { coroutineScope.launch { it.getValue()?.let { tab -> @@ -155,11 +164,10 @@ class SePopupVm( override fun update(e: AnActionEvent) { if (project == null) { + e.presentation.isEnabled = false return } - coroutineScope.launch { - e.presentation.isEnabled = canBeShownInFindResults() - } + e.presentation.isEnabled = canBeShownInFindResults e.presentation.icon = getInstance(project).getShowInFindToolWindowIcon() }