For #13934 - Make TabHistory work on PWA/Custom Tabs

pull/149/head
ekager 4 years ago
parent 407c31fdb3
commit 9a2103a9a7

@ -254,7 +254,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
) )
}, },
onCloseTab = { closedSession -> onCloseTab = { closedSession ->
val tab = store.state.findTab(closedSession.id) ?: return@DefaultBrowserToolbarController val tab = store.state.findTab(closedSession.id)
?: return@DefaultBrowserToolbarController
val isSelected = tab.id == context.components.core.store.state.selectedTabId val isSelected = tab.id == context.components.core.store.state.selectedTabId
val snackbarMessage = if (tab.content.private) { val snackbarMessage = if (tab.content.private) {
@ -875,7 +876,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
} }
override fun onBackLongPressed(): Boolean { override fun onBackLongPressed(): Boolean {
findNavController().navigate(R.id.action_global_tabHistoryDialogFragment) findNavController().navigate(
NavGraphDirections.actionGlobalTabHistoryDialogFragment(
activeSessionId = customTabSessionId
)
)
return true return true
} }
@ -1118,7 +1123,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
private fun didFirstContentfulHappen() = private fun didFirstContentfulHappen() =
if (components.settings.waitToShowPageUntilFirstPaint) { if (components.settings.waitToShowPageUntilFirstPaint) {
val tab = components.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId) val tab =
components.core.store.state.findTabOrCustomTabOrSelectedTab(customTabSessionId)
tab?.content?.firstContentfulPaint ?: false tab?.content?.firstContentfulPaint ?: false
} else { } else {
true true

@ -87,7 +87,9 @@ class DefaultBrowserToolbarMenuController(
is ToolbarMenu.Item.Back -> { is ToolbarMenu.Item.Back -> {
if (item.viewHistory) { if (item.viewHistory) {
navController.navigate( navController.navigate(
BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment() BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(
activeSessionId = customTabSession?.id
)
) )
} else { } else {
sessionUseCases.goBack.invoke(currentSession) sessionUseCases.goBack.invoke(currentSession)
@ -96,7 +98,9 @@ class DefaultBrowserToolbarMenuController(
is ToolbarMenu.Item.Forward -> { is ToolbarMenu.Item.Forward -> {
if (item.viewHistory) { if (item.viewHistory) {
navController.navigate( navController.navigate(
BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment() BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(
activeSessionId = customTabSession?.id
)
) )
} else { } else {
sessionUseCases.goForward.invoke(currentSession) sessionUseCases.goForward.invoke(currentSession)

@ -5,8 +5,8 @@
package org.mozilla.fenix.tabhistory package org.mozilla.fenix.tabhistory
import androidx.navigation.NavController import androidx.navigation.NavController
import mozilla.components.browser.session.SessionManager
import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SessionUseCases
import org.mozilla.fenix.R
interface TabHistoryController { interface TabHistoryController {
fun handleGoToHistoryItem(item: TabHistoryItem) fun handleGoToHistoryItem(item: TabHistoryItem)
@ -14,11 +14,16 @@ interface TabHistoryController {
class DefaultTabHistoryController( class DefaultTabHistoryController(
private val navController: NavController, private val navController: NavController,
private val goToHistoryIndexUseCase: SessionUseCases.GoToHistoryIndexUseCase private val goToHistoryIndexUseCase: SessionUseCases.GoToHistoryIndexUseCase,
private val customTabId: String? = null,
private val sessionManager: SessionManager
) : TabHistoryController { ) : TabHistoryController {
override fun handleGoToHistoryItem(item: TabHistoryItem) { override fun handleGoToHistoryItem(item: TabHistoryItem) {
navController.popBackStack(R.id.browserFragment, false) navController.navigateUp()
goToHistoryIndexUseCase.invoke(item.index) goToHistoryIndexUseCase.invoke(
item.index,
session = customTabId?.let { sessionManager.findSessionById(customTabId) }
?: sessionManager.selectedSession)
} }
} }

@ -12,10 +12,16 @@ import androidx.navigation.fragment.findNavController
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.fragment_tab_history_dialog.* import kotlinx.android.synthetic.main.fragment_tab_history_dialog.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.lib.state.ext.consumeFrom import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.mapNotNull
import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab
import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
class TabHistoryDialogFragment : BottomSheetDialogFragment() { class TabHistoryDialogFragment : BottomSheetDialogFragment() {
@ -25,6 +31,8 @@ class TabHistoryDialogFragment : BottomSheetDialogFragment() {
setStyle(STYLE_NO_TITLE, R.style.BottomSheet) setStyle(STYLE_NO_TITLE, R.style.BottomSheet)
} }
var customTabSessionId: String? = null
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
@ -35,9 +43,13 @@ class TabHistoryDialogFragment : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
customTabSessionId = requireArguments().getString(EXTRA_SESSION_ID)
val controller = DefaultTabHistoryController( val controller = DefaultTabHistoryController(
navController = findNavController(), navController = findNavController(),
goToHistoryIndexUseCase = requireComponents.useCases.sessionUseCases.goToHistoryIndex goToHistoryIndexUseCase = requireComponents.useCases.sessionUseCases.goToHistoryIndex,
customTabId = customTabSessionId,
sessionManager = container.requireContext().components.core.sessionManager
) )
val tabHistoryView = TabHistoryView( val tabHistoryView = TabHistoryView(
container = tabHistoryLayout, container = tabHistoryLayout,
@ -45,12 +57,20 @@ class TabHistoryDialogFragment : BottomSheetDialogFragment() {
interactor = TabHistoryInteractor(controller) interactor = TabHistoryInteractor(controller)
) )
consumeFrom(requireComponents.core.store) { requireComponents.core.store.flowScoped(viewLifecycleOwner) { flow ->
tabHistoryView.updateState(it) flow.mapNotNull { state -> state.findCustomTabOrSelectedTab(customTabSessionId)?.content?.history }
.ifChanged()
.collect { historyState ->
tabHistoryView.updateState(historyState)
}
} }
} }
private fun expand() { private fun expand() {
(dialog as BottomSheetDialog).behavior.state = BottomSheetBehavior.STATE_EXPANDED (dialog as BottomSheetDialog).behavior.state = BottomSheetBehavior.STATE_EXPANDED
} }
companion object {
const val EXTRA_SESSION_ID = "activeSessionId"
}
} }

@ -11,8 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.main.component_tabhistory.* import kotlinx.android.synthetic.main.component_tabhistory.*
import mozilla.components.browser.state.selector.selectedTab import mozilla.components.browser.state.state.content.HistoryState
import mozilla.components.browser.state.state.BrowserState
import org.mozilla.fenix.R import org.mozilla.fenix.R
interface TabHistoryViewInteractor { interface TabHistoryViewInteractor {
@ -66,18 +65,16 @@ class TabHistoryView(
tabHistoryRecyclerView.layoutManager = layoutManager tabHistoryRecyclerView.layoutManager = layoutManager
} }
fun updateState(state: BrowserState) { fun updateState(historyState: HistoryState) {
state.selectedTab?.content?.history?.let { historyState -> currentIndex = historyState.currentIndex
currentIndex = historyState.currentIndex val items = historyState.items.mapIndexed { index, historyItem ->
val items = historyState.items.mapIndexed { index, historyItem -> TabHistoryItem(
TabHistoryItem( title = historyItem.title,
title = historyItem.title, url = historyItem.uri,
url = historyItem.uri, index = index,
index = index, isSelected = index == currentIndex
isSelected = index == historyState.currentIndex )
)
}
adapter.submitList(items)
} }
adapter.submitList(items)
} }
} }

@ -836,7 +836,12 @@
<dialog <dialog
android:id="@+id/tabHistoryDialogFragment" android:id="@+id/tabHistoryDialogFragment"
android:name="org.mozilla.fenix.tabhistory.TabHistoryDialogFragment" android:name="org.mozilla.fenix.tabhistory.TabHistoryDialogFragment"
tools:layout="@layout/fragment_tab_history_dialog" /> tools:layout="@layout/fragment_tab_history_dialog">
<argument
android:name="activeSessionId"
app:argType="string"
app:nullable="true" />
</dialog>
<navigation <navigation
android:id="@+id/site_permissions_exceptions_graph" android:id="@+id/site_permissions_exceptions_graph"

@ -137,7 +137,7 @@ class DefaultBrowserToolbarMenuControllerTest {
val controller = createController(scope = this) val controller = createController(scope = this)
controller.handleToolbarItemInteraction(item) controller.handleToolbarItemInteraction(item)
val directions = BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment() val directions = BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(null)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BACK)) } verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BACK)) }
verify { navController.navigate(directions) } verify { navController.navigate(directions) }
@ -161,7 +161,7 @@ class DefaultBrowserToolbarMenuControllerTest {
val controller = createController(scope = this) val controller = createController(scope = this)
controller.handleToolbarItemInteraction(item) controller.handleToolbarItemInteraction(item)
val directions = BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment() val directions = BrowserFragmentDirections.actionGlobalTabHistoryDialogFragment(null)
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.FORWARD)) } verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.FORWARD)) }
verify { navController.navigate(directions) } verify { navController.navigate(directions) }

@ -5,13 +5,14 @@
package org.mozilla.fenix.tabhistory package org.mozilla.fenix.tabhistory
import androidx.navigation.NavController import androidx.navigation.NavController
import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import io.mockk.verify import io.mockk.verify
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.store.BrowserStore import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SessionUseCases
import org.junit.Test import org.junit.Test
import org.mozilla.fenix.R
class TabHistoryControllerTest { class TabHistoryControllerTest {
@ -19,10 +20,12 @@ class TabHistoryControllerTest {
private val sessionManager: SessionManager = mockk(relaxed = true) private val sessionManager: SessionManager = mockk(relaxed = true)
private val navController: NavController = mockk(relaxed = true) private val navController: NavController = mockk(relaxed = true)
private val sessionUseCases = SessionUseCases(store, sessionManager) private val sessionUseCases = SessionUseCases(store, sessionManager)
private val goToHistoryIndexUseCase = sessionUseCases.goToHistoryIndex private val goToHistoryIndexUseCase = sessionUseCases.goToHistoryIndex
private val controller = DefaultTabHistoryController( private val controller = DefaultTabHistoryController(
navController = navController, navController = navController,
goToHistoryIndexUseCase = goToHistoryIndexUseCase goToHistoryIndexUseCase = goToHistoryIndexUseCase,
sessionManager = sessionManager
) )
private val currentItem = TabHistoryItem( private val currentItem = TabHistoryItem(
@ -33,10 +36,31 @@ class TabHistoryControllerTest {
) )
@Test @Test
fun handleGoToHistoryIndex() { fun handleGoToHistoryIndexNormalBrowsing() {
val session: Session = mockk(relaxed = true)
every { sessionManager.selectedSession } returns session
controller.handleGoToHistoryItem(currentItem) controller.handleGoToHistoryItem(currentItem)
verify { navController.popBackStack(R.id.browserFragment, false) } verify { navController.navigateUp() }
verify { goToHistoryIndexUseCase.invoke(currentItem.index) } verify { goToHistoryIndexUseCase.invoke(currentItem.index, session) }
}
@Test
fun handleGoToHistoryIndexCustomTab() {
val customTabController = DefaultTabHistoryController(
navController = navController,
goToHistoryIndexUseCase = goToHistoryIndexUseCase,
customTabId = "custom-id",
sessionManager = sessionManager
)
val customTabSession: Session = mockk(relaxed = true)
every { sessionManager.findSessionById(any()) } returns customTabSession
customTabController.handleGoToHistoryItem(currentItem)
verify { navController.navigateUp() }
verify { goToHistoryIndexUseCase.invoke(currentItem.index, customTabSession) }
} }
} }

Loading…
Cancel
Save