From 192dd21cf499a52a607bd6320dc7001a849c7dba Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Tue, 13 Jul 2021 13:53:41 -0400 Subject: [PATCH] Issue #10611 - Add a new SelectOrAddUseCase for reopening existing tab with matching HistoryMetadataKey --- .../components/feature/tabs/TabsUseCases.kt | 32 ++++++++++++- .../feature/tabs/TabsUseCasesTest.kt | 47 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt b/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt index a520abc644b..e04de512627 100644 --- a/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt +++ b/components/feature/tabs/src/main/java/mozilla/components/feature/tabs/TabsUseCases.kt @@ -22,6 +22,7 @@ import mozilla.components.browser.state.state.recover.toTabSessionStates import mozilla.components.browser.state.store.BrowserStore import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.LoadUrlFlags +import mozilla.components.concept.storage.HistoryMetadataKey import mozilla.components.feature.session.SessionUseCases.LoadUrlUseCase /** @@ -369,18 +370,44 @@ class TabsUseCases( class SelectOrAddUseCase( private val store: BrowserStore ) { + /** + * Selects an already existing tab with the matching [HistoryMetadataKey] or otherwise + * creates a new tab with the given [url]. + */ + operator fun invoke( + url: String, + historyMetadata: HistoryMetadataKey, + ): String { + val tab = store.state.tabs.find { it.historyMetadata == historyMetadata } + + return if (tab != null) { + store.dispatch(TabListAction.SelectTabAction(tab.id)) + tab.id + } else { + this.invoke(url) + } + } + /** * Selects an already existing tab displaying [url] or otherwise creates a new tab. + * + * @param url The URL to be loaded in the new tab. + * @param private Whether or not this session should use private mode. + * @param source The origin of a session to describe how and why it was created. + * @param flags The [LoadUrlFlags] to use when loading the provided URL. + * @return The ID fo the selected or created tab. */ operator fun invoke( url: String, private: Boolean = false, source: Source = Source.NEW_TAB, flags: LoadUrlFlags = LoadUrlFlags.none() - ) { + ): String { val existingTab = store.state.findTabByUrl(url) - if (existingTab != null) { + + return if (existingTab != null) { store.dispatch(TabListAction.SelectTabAction(existingTab.id)) + existingTab.id } else { val tab = createTab( url = url, @@ -394,6 +421,7 @@ class TabsUseCases( url, flags )) + tab.id } } } diff --git a/components/feature/tabs/src/test/java/mozilla/components/feature/tabs/TabsUseCasesTest.kt b/components/feature/tabs/src/test/java/mozilla/components/feature/tabs/TabsUseCasesTest.kt index 57e301b73a0..fc2fe47441c 100644 --- a/components/feature/tabs/src/test/java/mozilla/components/feature/tabs/TabsUseCasesTest.kt +++ b/components/feature/tabs/src/test/java/mozilla/components/feature/tabs/TabsUseCasesTest.kt @@ -21,6 +21,7 @@ import mozilla.components.concept.engine.Engine import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.LoadUrlFlags import mozilla.components.concept.engine.EngineSessionState +import mozilla.components.concept.storage.HistoryMetadataKey import mozilla.components.support.test.any import mozilla.components.support.test.argumentCaptor import mozilla.components.support.test.ext.joinBlocking @@ -362,6 +363,31 @@ class TabsUseCasesTest { assertEquals(tab, store.state.selectedTab) } + @Test + fun `selectOrAddTab selects already existing tab with matching historyMetadata`() { + val historyMetadata = HistoryMetadataKey( + url = "https://mozilla.org", + referrerUrl = "https://firefox.com" + ) + + val tab = createTab("https://mozilla.org", historyMetadata = historyMetadata) + val otherTab = createTab("https://firefox.com") + + store.dispatch(TabListAction.AddTabAction(otherTab)).joinBlocking() + store.dispatch(TabListAction.AddTabAction(tab)).joinBlocking() + + assertEquals(otherTab.id, store.state.selectedTabId) + assertEquals(otherTab, store.state.selectedTab) + assertEquals(2, store.state.tabs.size) + + tabsUseCases.selectOrAddTab(tab.content.url, historyMetadata = historyMetadata) + store.waitUntilIdle() + + assertEquals(2, store.state.tabs.size) + assertEquals(tab.id, store.state.selectedTabId) + assertEquals(tab, store.state.selectedTab) + } + @Test fun `selectOrAddTab adds new tab if no matching existing tab could be found`() { val tab = createTab("https://mozilla.org") @@ -376,6 +402,27 @@ class TabsUseCasesTest { assertNotNull(store.state.findTabByUrl("https://firefox.com")) } + @Test + fun `selectOrAddTab adds new tab if no matching existing history metadata could be found`() { + val tab = createTab("https://mozilla.org") + val historyMetadata = HistoryMetadataKey( + url = "https://mozilla.org", + referrerUrl = "https://firefox.com" + ) + + store.dispatch(TabListAction.AddTabAction(tab)).joinBlocking() + + assertEquals(tab.id, store.state.selectedTabId) + assertEquals(tab, store.state.selectedTab) + assertEquals(1, store.state.tabs.size) + + tabsUseCases.selectOrAddTab("https://firefox.com", historyMetadata = historyMetadata) + store.waitUntilIdle() + + assertEquals(2, store.state.tabs.size) + assertNotNull(store.state.findTabByUrl("https://firefox.com")) + } + @Test fun `duplicateTab creates a duplicate of the given tab`() { store.dispatch(TabListAction.AddTabAction(