Skip to content

Commit

Permalink
Issue mozilla-mobile#10611 - Add a new SelectOrAddUseCase for reopeni…
Browse files Browse the repository at this point in the history
…ng existing tab with matching HistoryMetadataKey
  • Loading branch information
gabrielluong committed Jul 15, 2021
1 parent cb822bb commit 04126e3
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -369,18 +370,48 @@ 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].
*
* @param url The URL to be selected or loaded in the new tab.
* @param historyMetadata The [HistoryMetadataKey] to match for existing tabs.
* @return The ID of the selected or created tab.
*/
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 of 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,
Expand All @@ -394,6 +425,7 @@ class TabsUseCases(
url,
flags
))
tab.id
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand All @@ -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(
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ permalink: /changelog/

* **feature-tabs**
* Adds `lastAccess` to the `Tab` data class that is used in `TabsTray`.
* Adds a new SelectOrAddUseCase for reopening existing tab with matching HistoryMetadataKey. [#10611](https://github.com/mozilla-mobile/android-components/issues/10611)

# 91.0.0
* [Commits](https://github.com/mozilla-mobile/android-components/compare/v91.0.0...master)
Expand Down

0 comments on commit 04126e3

Please sign in to comment.