mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-19 09:25:34 +00:00
[fenix] For https://github.com/mozilla-mobile/fenix/issues/13934 - Make TabHistory work on PWA/Custom Tabs
This commit is contained in:
parent
f4406b2265
commit
9763d05ef2
@ -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…
Reference in New Issue
Block a user