parent
54cb8f0194
commit
248237290e
|
@ -22,6 +22,7 @@ import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.fragment_browser.*
|
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||||
import kotlinx.android.synthetic.main.fragment_browser.view.*
|
import kotlinx.android.synthetic.main.fragment_browser.view.*
|
||||||
|
import kotlinx.android.synthetic.main.tab_header.view.*
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
@ -71,6 +72,7 @@ import org.mozilla.fenix.NavGraphDirections
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||||
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
||||||
|
import org.mozilla.fenix.collections.SaveCollectionStep
|
||||||
import org.mozilla.fenix.components.FenixSnackbar
|
import org.mozilla.fenix.components.FenixSnackbar
|
||||||
import org.mozilla.fenix.components.FindInPageIntegration
|
import org.mozilla.fenix.components.FindInPageIntegration
|
||||||
import org.mozilla.fenix.components.StoreProvider
|
import org.mozilla.fenix.components.StoreProvider
|
||||||
|
@ -96,6 +98,7 @@ import org.mozilla.fenix.ext.settings
|
||||||
import org.mozilla.fenix.home.SharedViewModel
|
import org.mozilla.fenix.home.SharedViewModel
|
||||||
import org.mozilla.fenix.tabtray.TabTrayDialogFragment
|
import org.mozilla.fenix.tabtray.TabTrayDialogFragment
|
||||||
import org.mozilla.fenix.theme.ThemeManager
|
import org.mozilla.fenix.theme.ThemeManager
|
||||||
|
import org.mozilla.fenix.utils.allowUndo
|
||||||
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
|
import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
@ -117,6 +120,9 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
||||||
protected val browserToolbarView: BrowserToolbarView
|
protected val browserToolbarView: BrowserToolbarView
|
||||||
get() = _browserToolbarView!!
|
get() = _browserToolbarView!!
|
||||||
|
|
||||||
|
private val sessionManager: SessionManager
|
||||||
|
get() = requireComponents.core.sessionManager
|
||||||
|
|
||||||
protected val readerViewFeature = ViewBoundFeatureWrapper<ReaderViewFeature>()
|
protected val readerViewFeature = ViewBoundFeatureWrapper<ReaderViewFeature>()
|
||||||
|
|
||||||
private val sessionFeature = ViewBoundFeatureWrapper<SessionFeature>()
|
private val sessionFeature = ViewBoundFeatureWrapper<SessionFeature>()
|
||||||
|
@ -225,6 +231,75 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
||||||
tabTrayDialog.dismiss()
|
tabTrayDialog.dismiss()
|
||||||
findNavController().navigate(BrowserFragmentDirections.actionGlobalHome())
|
findNavController().navigate(BrowserFragmentDirections.actionGlobalHome())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onShareTabsClicked(private: Boolean) {
|
||||||
|
share(getListOfSessions(private))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCloseAllTabsClicked(private: Boolean) {
|
||||||
|
val tabs = getListOfSessions(private)
|
||||||
|
|
||||||
|
val selectedIndex = sessionManager
|
||||||
|
.selectedSession?.let { sessionManager.sessions.indexOf(it) } ?: 0
|
||||||
|
|
||||||
|
val snapshot = tabs
|
||||||
|
.map(sessionManager::createSessionSnapshot)
|
||||||
|
.map {
|
||||||
|
it.copy(engineSession = null, engineSessionState = it.engineSession?.saveState())
|
||||||
|
}
|
||||||
|
.let { SessionManager.Snapshot(it, selectedIndex) }
|
||||||
|
|
||||||
|
tabs.forEach {
|
||||||
|
sessionManager.remove(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate
|
||||||
|
val snackbarMessage = if (isPrivate) {
|
||||||
|
getString(R.string.snackbar_private_tabs_closed)
|
||||||
|
} else {
|
||||||
|
getString(R.string.snackbar_tabs_closed)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.allowUndo(
|
||||||
|
requireView(),
|
||||||
|
snackbarMessage,
|
||||||
|
getString(R.string.snackbar_deleted_undo),
|
||||||
|
{
|
||||||
|
sessionManager.restore(snapshot)
|
||||||
|
},
|
||||||
|
operation = { },
|
||||||
|
anchorView = view.tabs_header
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveToCollectionClicked() {
|
||||||
|
val tabs = getListOfSessions(false)
|
||||||
|
val tabIds = tabs.map { it.id }.toList().toTypedArray()
|
||||||
|
val tabCollectionStorage = (activity as HomeActivity).components.core.tabCollectionStorage
|
||||||
|
val navController = findNavController()
|
||||||
|
|
||||||
|
val step = when {
|
||||||
|
// Show the SelectTabs fragment if there are multiple opened tabs to select which tabs
|
||||||
|
// you want to save to a collection.
|
||||||
|
tabs.size > 1 -> SaveCollectionStep.SelectTabs
|
||||||
|
// If there is an existing tab collection, show the SelectCollection fragment to save
|
||||||
|
// the selected tab to a collection of your choice.
|
||||||
|
tabCollectionStorage.cachedTabCollections.isNotEmpty() ->
|
||||||
|
SaveCollectionStep.SelectCollection
|
||||||
|
// Show the NameCollection fragment to create a new collection for the selected tab.
|
||||||
|
else -> SaveCollectionStep.NameCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
if (navController.currentDestination?.id == R.id.collectionCreationFragment) return
|
||||||
|
|
||||||
|
val directions = BrowserFragmentDirections.actionBrowserFragmentToCreateCollectionFragment(
|
||||||
|
tabIds = tabIds,
|
||||||
|
previousFragmentId = R.id.tabTrayFragment,
|
||||||
|
saveCollectionStep = step,
|
||||||
|
selectedTabIds = tabIds
|
||||||
|
)
|
||||||
|
navController.nav(R.id.browserFragment, directions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -965,6 +1040,23 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun share(tabs: List<Session>) {
|
||||||
|
val data = tabs.map {
|
||||||
|
ShareData(url = it.url, title = it.title)
|
||||||
|
}
|
||||||
|
val directions = BrowserFragmentDirections.actionGlobalShareFragment(
|
||||||
|
data = data.toTypedArray()
|
||||||
|
)
|
||||||
|
nav(R.id.browserFragment, directions)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getListOfSessions(
|
||||||
|
private: Boolean = (activity as HomeActivity).browsingModeManager.mode.isPrivate
|
||||||
|
): List<Session> {
|
||||||
|
return requireComponents.core.sessionManager.sessionsOfType(private = private)
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dereference these views when the fragment view is destroyed to prevent memory leaks
|
* Dereference these views when the fragment view is destroyed to prevent memory leaks
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,7 @@ import com.google.android.material.appbar.AppBarLayout
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.fragment_home.*
|
import kotlinx.android.synthetic.main.fragment_home.*
|
||||||
import kotlinx.android.synthetic.main.fragment_home.view.*
|
import kotlinx.android.synthetic.main.fragment_home.view.*
|
||||||
|
import kotlinx.android.synthetic.main.tab_header.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
@ -59,6 +60,7 @@ import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.browser.session.SessionManager
|
import mozilla.components.browser.session.SessionManager
|
||||||
import mozilla.components.browser.state.state.MediaState.State.PLAYING
|
import mozilla.components.browser.state.state.MediaState.State.PLAYING
|
||||||
import mozilla.components.browser.state.store.BrowserStore
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
|
import mozilla.components.concept.engine.prompt.ShareData
|
||||||
import mozilla.components.concept.sync.AccountObserver
|
import mozilla.components.concept.sync.AccountObserver
|
||||||
import mozilla.components.concept.sync.AuthType
|
import mozilla.components.concept.sync.AuthType
|
||||||
import mozilla.components.concept.sync.OAuthAccount
|
import mozilla.components.concept.sync.OAuthAccount
|
||||||
|
@ -75,6 +77,7 @@ import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.addons.runIfFragmentIsAttached
|
import org.mozilla.fenix.addons.runIfFragmentIsAttached
|
||||||
import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions
|
import org.mozilla.fenix.browser.BrowserAnimator.Companion.getToolbarNavOptions
|
||||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||||
|
import org.mozilla.fenix.collections.SaveCollectionStep
|
||||||
import org.mozilla.fenix.components.FenixSnackbar
|
import org.mozilla.fenix.components.FenixSnackbar
|
||||||
import org.mozilla.fenix.components.PrivateShortcutCreateManager
|
import org.mozilla.fenix.components.PrivateShortcutCreateManager
|
||||||
import org.mozilla.fenix.components.StoreProvider
|
import org.mozilla.fenix.components.StoreProvider
|
||||||
|
@ -371,6 +374,72 @@ class HomeFragment : Fragment() {
|
||||||
(activity as HomeActivity).browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
(activity as HomeActivity).browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
||||||
tabTrayDialog.dismiss()
|
tabTrayDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onShareTabsClicked(private: Boolean) {
|
||||||
|
share(getListOfSessions(private))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCloseAllTabsClicked(private: Boolean) {
|
||||||
|
val tabs = getListOfSessions(private)
|
||||||
|
|
||||||
|
val selectedIndex = sessionManager
|
||||||
|
.selectedSession?.let { sessionManager.sessions.indexOf(it) } ?: 0
|
||||||
|
|
||||||
|
val snapshot = tabs
|
||||||
|
.map(sessionManager::createSessionSnapshot)
|
||||||
|
.map { it.copy(engineSession = null, engineSessionState = it.engineSession?.saveState()) }
|
||||||
|
.let { SessionManager.Snapshot(it, selectedIndex) }
|
||||||
|
|
||||||
|
tabs.forEach {
|
||||||
|
sessionManager.remove(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val isPrivate = (activity as HomeActivity).browsingModeManager.mode.isPrivate
|
||||||
|
val snackbarMessage = if (isPrivate) {
|
||||||
|
getString(R.string.snackbar_private_tabs_closed)
|
||||||
|
} else {
|
||||||
|
getString(R.string.snackbar_tabs_closed)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.allowUndo(
|
||||||
|
requireView(),
|
||||||
|
snackbarMessage,
|
||||||
|
getString(R.string.snackbar_deleted_undo),
|
||||||
|
{
|
||||||
|
sessionManager.restore(snapshot)
|
||||||
|
},
|
||||||
|
operation = { },
|
||||||
|
anchorView = view.tabs_header
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveToCollectionClicked() {
|
||||||
|
val tabs = getListOfSessions(false)
|
||||||
|
val tabIds = tabs.map { it.id }.toList().toTypedArray()
|
||||||
|
val tabCollectionStorage = (activity as HomeActivity).components.core.tabCollectionStorage
|
||||||
|
val navController = findNavController()
|
||||||
|
|
||||||
|
val step = when {
|
||||||
|
// Show the SelectTabs fragment if there are multiple opened tabs to select which tabs
|
||||||
|
// you want to save to a collection.
|
||||||
|
tabs.size > 1 -> SaveCollectionStep.SelectTabs
|
||||||
|
// If there is an existing tab collection, show the SelectCollection fragment to save
|
||||||
|
// the selected tab to a collection of your choice.
|
||||||
|
tabCollectionStorage.cachedTabCollections.isNotEmpty() -> SaveCollectionStep.SelectCollection
|
||||||
|
// Show the NameCollection fragment to create a new collection for the selected tab.
|
||||||
|
else -> SaveCollectionStep.NameCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
if (navController.currentDestination?.id == R.id.collectionCreationFragment) return
|
||||||
|
|
||||||
|
val directions = HomeFragmentDirections.actionHomeFragmentToCreateCollectionFragment(
|
||||||
|
tabIds = tabIds,
|
||||||
|
previousFragmentId = R.id.tabTrayFragment,
|
||||||
|
saveCollectionStep = step,
|
||||||
|
selectedTabIds = tabIds
|
||||||
|
)
|
||||||
|
navController.nav(R.id.homeFragment, directions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,8 +915,8 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getListOfSessions(): List<Session> {
|
private fun getListOfSessions(private: Boolean = browsingModeManager.mode.isPrivate): List<Session> {
|
||||||
return sessionManager.sessionsOfType(private = browsingModeManager.mode.isPrivate)
|
return sessionManager.sessionsOfType(private = private)
|
||||||
.filter { session: Session -> session.id != pendingSessionDeletion?.sessionId }
|
.filter { session: Session -> session.id != pendingSessionDeletion?.sessionId }
|
||||||
.toList()
|
.toList()
|
||||||
}
|
}
|
||||||
|
@ -1022,6 +1091,16 @@ class HomeFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun share(tabs: List<Session>) {
|
||||||
|
val data = tabs.map {
|
||||||
|
ShareData(url = it.url, title = it.title)
|
||||||
|
}
|
||||||
|
val directions = HomeFragmentDirections.actionGlobalShareFragment(
|
||||||
|
data = data.toTypedArray()
|
||||||
|
)
|
||||||
|
nav(R.id.homeFragment, directions)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ANIMATION_DELAY = 100L
|
private const val ANIMATION_DELAY = 100L
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import kotlinx.android.synthetic.main.component_tabstray.view.*
|
||||||
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.*
|
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.*
|
||||||
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.*
|
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.*
|
||||||
import mozilla.components.concept.tabstray.Tab
|
import mozilla.components.concept.tabstray.Tab
|
||||||
|
import mozilla.components.lib.state.ext.consumeFrom
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
@ -25,6 +26,9 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), TabTrayInteractor {
|
||||||
interface Interactor {
|
interface Interactor {
|
||||||
fun onTabSelected(tab: Tab)
|
fun onTabSelected(tab: Tab)
|
||||||
fun onNewTabTapped(private: Boolean)
|
fun onNewTabTapped(private: Boolean)
|
||||||
|
fun onShareTabsClicked(private: Boolean)
|
||||||
|
fun onSaveToCollectionClicked()
|
||||||
|
fun onCloseAllTabsClicked(private: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var tabTrayView: TabTrayView
|
private lateinit var tabTrayView: TabTrayView
|
||||||
|
@ -49,7 +53,9 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), TabTrayInteractor {
|
||||||
(activity as HomeActivity).browsingModeManager.mode.isPrivate
|
(activity as HomeActivity).browsingModeManager.mode.isPrivate
|
||||||
)
|
)
|
||||||
|
|
||||||
tabLayout.setOnClickListener { dismissAllowingStateLoss() }
|
tabLayout.setOnClickListener {
|
||||||
|
dismissAllowingStateLoss()
|
||||||
|
}
|
||||||
|
|
||||||
view.tabLayout.setOnApplyWindowInsetsListener { v, insets ->
|
view.tabLayout.setOnApplyWindowInsetsListener { v, insets ->
|
||||||
v.updatePadding(
|
v.updatePadding(
|
||||||
|
@ -64,6 +70,8 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), TabTrayInteractor {
|
||||||
|
|
||||||
insets
|
insets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consumeFrom(requireComponents.core.store) { tabTrayView.updateState(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabClosed(tab: Tab) {
|
override fun onTabClosed(tab: Tab) {
|
||||||
|
@ -108,6 +116,18 @@ class TabTrayDialogFragment : AppCompatDialogFragment(), TabTrayInteractor {
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onShareTabsClicked(private: Boolean) {
|
||||||
|
interactor?.onShareTabsClicked(private)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveToCollectionClicked() {
|
||||||
|
interactor?.onSaveToCollectionClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCloseAllTabsClicked(private: Boolean) {
|
||||||
|
interactor?.onCloseAllTabsClicked(private)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ELEVATION = 80f
|
private const val ELEVATION = 80f
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,22 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.tabtray
|
package org.mozilla.fenix.tabtray
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.tabs.TabLayout
|
import com.google.android.material.tabs.TabLayout
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.component_tabstray.*
|
import kotlinx.android.synthetic.main.component_tabstray.*
|
||||||
import kotlinx.android.synthetic.main.component_tabstray.view.*
|
import kotlinx.android.synthetic.main.component_tabstray.view.*
|
||||||
import kotlinx.android.synthetic.main.component_tabstray_fab.view.*
|
import kotlinx.android.synthetic.main.component_tabstray_fab.view.*
|
||||||
|
import mozilla.components.browser.menu.BrowserMenuBuilder
|
||||||
|
import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
|
||||||
|
import mozilla.components.browser.state.selector.normalTabs
|
||||||
|
import mozilla.components.browser.state.selector.privateTabs
|
||||||
|
import mozilla.components.browser.state.state.BrowserState
|
||||||
import mozilla.components.browser.state.state.TabSessionState
|
import mozilla.components.browser.state.state.TabSessionState
|
||||||
import mozilla.components.browser.tabstray.BrowserTabsTray
|
import mozilla.components.browser.tabstray.BrowserTabsTray
|
||||||
import mozilla.components.concept.tabstray.Tab
|
import mozilla.components.concept.tabstray.Tab
|
||||||
|
@ -26,6 +33,9 @@ interface TabTrayInteractor {
|
||||||
fun onTabSelected(tab: Tab)
|
fun onTabSelected(tab: Tab)
|
||||||
fun onNewTabTapped(private: Boolean)
|
fun onNewTabTapped(private: Boolean)
|
||||||
fun onTabTrayDismissed()
|
fun onTabTrayDismissed()
|
||||||
|
fun onShareTabsClicked(private: Boolean)
|
||||||
|
fun onSaveToCollectionClicked()
|
||||||
|
fun onCloseAllTabsClicked(private: Boolean)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* View that contains and configures the BrowserAwesomeBar
|
* View that contains and configures the BrowserAwesomeBar
|
||||||
|
@ -41,8 +51,11 @@ class TabTrayView(
|
||||||
val view = LayoutInflater.from(container.context)
|
val view = LayoutInflater.from(container.context)
|
||||||
.inflate(R.layout.component_tabstray, container, true)
|
.inflate(R.layout.component_tabstray, container, true)
|
||||||
|
|
||||||
|
val isPrivateModeSelected: Boolean get() = view.tab_layout.selectedTabPosition == PRIVATE_TAB_ID
|
||||||
|
|
||||||
private val behavior = BottomSheetBehavior.from(view.tab_wrapper)
|
private val behavior = BottomSheetBehavior.from(view.tab_wrapper)
|
||||||
private var tabsFeature: TabsFeature
|
private var tabsFeature: TabsFeature
|
||||||
|
private var tabTrayItemMenu: TabTrayItemMenu
|
||||||
|
|
||||||
override val containerView: View?
|
override val containerView: View?
|
||||||
get() = container
|
get() = container
|
||||||
|
@ -89,8 +102,26 @@ class TabTrayView(
|
||||||
TabsTouchHelper(tray.tabsAdapter).attachToRecyclerView(tray)
|
TabsTouchHelper(tray.tabsAdapter).attachToRecyclerView(tray)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tabTrayItemMenu = TabTrayItemMenu(view.context, { view.tab_layout.selectedTabPosition == 0 }) {
|
||||||
|
when (it) {
|
||||||
|
is TabTrayItemMenu.Item.ShareAllTabs -> interactor.onShareTabsClicked(
|
||||||
|
isPrivateModeSelected
|
||||||
|
)
|
||||||
|
is TabTrayItemMenu.Item.SaveToCollection -> interactor.onSaveToCollectionClicked()
|
||||||
|
is TabTrayItemMenu.Item.CloseAllTabs -> interactor.onCloseAllTabsClicked(
|
||||||
|
isPrivateModeSelected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view.tab_tray_overflow.setOnClickListener {
|
||||||
|
tabTrayItemMenu.menuBuilder
|
||||||
|
.build(view.context)
|
||||||
|
.show(anchor = it)
|
||||||
|
}
|
||||||
|
|
||||||
fabView.new_tab_button.setOnClickListener {
|
fabView.new_tab_button.setOnClickListener {
|
||||||
interactor.onNewTabTapped(view.tab_layout.selectedTabPosition == 1)
|
interactor.onNewTabTapped(isPrivateModeSelected)
|
||||||
}
|
}
|
||||||
|
|
||||||
tabsTray.register(this)
|
tabsTray.register(this)
|
||||||
|
@ -109,6 +140,17 @@ class TabTrayView(
|
||||||
}
|
}
|
||||||
|
|
||||||
tabsFeature.filterTabs(filter)
|
tabsFeature.filterTabs(filter)
|
||||||
|
|
||||||
|
updateState(view.context.components.core.store.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateState(state: BrowserState) {
|
||||||
|
val shouldHide = if (isPrivateModeSelected) {
|
||||||
|
state.privateTabs.isEmpty()
|
||||||
|
} else {
|
||||||
|
state.normalTabs.isEmpty()
|
||||||
|
}
|
||||||
|
view?.tab_tray_overflow?.isVisible = !shouldHide
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabClosed(tab: Tab) {
|
override fun onTabClosed(tab: Tab) {
|
||||||
|
@ -124,3 +166,43 @@ class TabTrayView(
|
||||||
private const val ELEVATION = 90f
|
private const val ELEVATION = 90f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TabTrayItemMenu(
|
||||||
|
private val context: Context,
|
||||||
|
private val shouldShowSaveToCollection: () -> Boolean,
|
||||||
|
private val onItemTapped: (Item) -> Unit = {}
|
||||||
|
) {
|
||||||
|
|
||||||
|
sealed class Item {
|
||||||
|
object ShareAllTabs : Item()
|
||||||
|
object SaveToCollection : Item()
|
||||||
|
object CloseAllTabs : Item()
|
||||||
|
}
|
||||||
|
|
||||||
|
val menuBuilder by lazy { BrowserMenuBuilder(menuItems) }
|
||||||
|
|
||||||
|
private val menuItems by lazy {
|
||||||
|
listOf(
|
||||||
|
SimpleBrowserMenuItem(
|
||||||
|
context.getString(R.string.tab_tray_menu_item_save),
|
||||||
|
textColorResource = R.color.primary_text_normal_theme
|
||||||
|
) {
|
||||||
|
onItemTapped.invoke(Item.SaveToCollection)
|
||||||
|
}.apply { visible = shouldShowSaveToCollection },
|
||||||
|
|
||||||
|
SimpleBrowserMenuItem(
|
||||||
|
context.getString(R.string.tab_tray_menu_item_share),
|
||||||
|
textColorResource = R.color.primary_text_normal_theme
|
||||||
|
) {
|
||||||
|
onItemTapped.invoke(Item.ShareAllTabs)
|
||||||
|
},
|
||||||
|
|
||||||
|
SimpleBrowserMenuItem(
|
||||||
|
context.getString(R.string.tab_tray_menu_item_close),
|
||||||
|
textColorResource = R.color.primary_text_normal_theme
|
||||||
|
) {
|
||||||
|
onItemTapped.invoke(Item.CloseAllTabs)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -58,11 +58,11 @@
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:contentDescription="@string/open_tabs_menu"
|
android:contentDescription="@string/open_tabs_menu"
|
||||||
app:srcCompat="@drawable/ic_menu"
|
app:srcCompat="@drawable/ic_menu"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="0dp"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/tab_layout"
|
app:layout_constraintTop_toTopOf="@id/tab_layout"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/tab_layout"/>
|
app:layout_constraintBottom_toBottomOf="@id/tab_layout" />
|
||||||
<mozilla.components.concept.tabstray.TabsTray
|
<mozilla.components.concept.tabstray.TabsTray
|
||||||
android:id="@+id/tabsTray"
|
android:id="@+id/tabsTray"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
|
|
@ -164,6 +164,9 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_browserFragment_to_tabsTrayFragment"
|
android:id="@+id/action_browserFragment_to_tabsTrayFragment"
|
||||||
app:destination="@+id/tabTrayFragment" />
|
app:destination="@+id/tabTrayFragment" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_browserFragment_to_createCollectionFragment"
|
||||||
|
app:destination="@id/collectionCreationFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
|
|
Loading…
Reference in New Issue