diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt new file mode 100644 index 0000000000..e5f5a28a15 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.tabstray + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import org.mozilla.fenix.compose.annotation.LightDarkPreview +import org.mozilla.fenix.theme.FirefoxTheme + +/** + * Top-level UI for displaying the Tabs Tray feature. + */ +@Composable +fun TabsTray() { + Box( + modifier = Modifier.fillMaxSize() + .background(FirefoxTheme.colors.layer1), + ) { + Text( + text = "Tabs Tray to Compose", + color = FirefoxTheme.colors.textPrimary, + style = FirefoxTheme.typography.body1, + ) + } +} + +@LightDarkPreview +@Composable +private fun TabsTrayPreview() { + FirefoxTheme { + TabsTray() + } +} diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt index 8ebc69aacb..d4fb0ab363 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayFragment.kt @@ -14,6 +14,7 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.VisibleForTesting import androidx.appcompat.app.AppCompatDialogFragment +import androidx.compose.ui.platform.ComposeView import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.setFragmentResultListener @@ -59,6 +60,7 @@ import org.mozilla.fenix.tabstray.ext.collectionMessage import org.mozilla.fenix.tabstray.ext.make import org.mozilla.fenix.tabstray.ext.showWithTheme import org.mozilla.fenix.tabstray.syncedtabs.SyncedTabsIntegration +import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.utils.allowUndo import kotlin.math.max @@ -115,27 +117,12 @@ class TabsTrayFragment : AppCompatDialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?) = TabsTrayDialog(requireContext(), theme) { tabsTrayInteractor } + @Suppress("LongMethod") override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View { - _tabsTrayDialogBinding = FragmentTabTrayDialogBinding.inflate( - inflater, - container, - false, - ) - _tabsTrayBinding = ComponentTabstray2Binding.inflate( - inflater, - tabsTrayDialogBinding.root, - true, - ) - _fabButtonBinding = ComponentTabstrayFabBinding.inflate( - LayoutInflater.from(tabsTrayDialogBinding.root.context), - tabsTrayDialogBinding.root, - true, - ) - val args by navArgs() args.accessPoint.takeIf { it != TabsTrayAccessPoint.None }?.let { TabsTray.accessPoint[it.name.lowercase()].add() @@ -146,6 +133,7 @@ class TabsTrayFragment : AppCompatDialogFragment() { TabsTrayState.Mode.Normal } val initialPage = args.page + val activity = activity as HomeActivity tabsTrayStore = StoreProvider.get(this) { TabsTrayStore( @@ -159,34 +147,6 @@ class TabsTrayFragment : AppCompatDialogFragment() { ) } - return tabsTrayDialogBinding.root - } - - override fun onStart() { - super.onStart() - findPreviousDialogFragment()?.let { dialog -> - dialog.onAcceptClicked = ::onCancelDownloadWarningAccepted - } - } - - override fun onDestroyView() { - super.onDestroyView() - _tabsTrayBinding = null - _tabsTrayDialogBinding = null - _fabButtonBinding = null - } - - @Suppress("LongMethod") - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - val activity = activity as HomeActivity - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - fabButtonBinding.newTabButton.accessibilityTraversalAfter = - tabsTrayBinding.tabLayout.id - } - TabsTray.opened.record(NoExtras()) - navigationInteractor = DefaultNavigationInteractor( context = requireContext(), @@ -226,34 +186,189 @@ class TabsTrayFragment : AppCompatDialogFragment() { controller = tabsTrayController, ) - setupMenu(navigationInteractor) - setupPager( - context = view.context, - lifecycleOwner = viewLifecycleOwner, - store = tabsTrayStore, - trayInteractor = tabsTrayInteractor, - ) + return if (requireContext().settings().enableTabsTrayToCompose) { + ComposeView(requireContext()).apply { + setContent { + FirefoxTheme { + TabsTray() + } + } + } + } else { + _tabsTrayDialogBinding = FragmentTabTrayDialogBinding.inflate( + inflater, + container, + false, + ) + _tabsTrayBinding = ComponentTabstray2Binding.inflate( + inflater, + tabsTrayDialogBinding.root, + true, + ) + _fabButtonBinding = ComponentTabstrayFabBinding.inflate( + LayoutInflater.from(tabsTrayDialogBinding.root.context), + tabsTrayDialogBinding.root, + true, + ) - setupBackgroundDismissalListener { - TabsTray.closed.record(NoExtras()) - dismissAllowingStateLoss() + tabsTrayDialogBinding.root } + } - trayBehaviorManager = TabSheetBehaviorManager( - behavior = BottomSheetBehavior.from(tabsTrayBinding.tabWrapper), - orientation = resources.configuration.orientation, - maxNumberOfTabs = max( - requireContext().components.core.store.state.normalTabs.size, - requireContext().components.core.store.state.privateTabs.size, - ), - numberForExpandingTray = if (requireContext().settings().gridTabView) { - EXPAND_AT_GRID_SIZE - } else { - EXPAND_AT_LIST_SIZE - }, - navigationInteractor = navigationInteractor, - displayMetrics = requireContext().resources.displayMetrics, - ) + override fun onStart() { + super.onStart() + findPreviousDialogFragment()?.let { dialog -> + dialog.onAcceptClicked = ::onCancelDownloadWarningAccepted + } + } + + override fun onDestroyView() { + super.onDestroyView() + _tabsTrayBinding = null + _tabsTrayDialogBinding = null + _fabButtonBinding = null + } + + @Suppress("LongMethod") + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + TabsTray.opened.record(NoExtras()) + + if (!requireContext().settings().enableTabsTrayToCompose) { + val activity = activity as HomeActivity + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + fabButtonBinding.newTabButton.accessibilityTraversalAfter = + tabsTrayBinding.tabLayout.id + } + + setupMenu(navigationInteractor) + setupPager( + context = view.context, + lifecycleOwner = viewLifecycleOwner, + store = tabsTrayStore, + trayInteractor = tabsTrayInteractor, + ) + + setupBackgroundDismissalListener { + TabsTray.closed.record(NoExtras()) + dismissAllowingStateLoss() + } + + trayBehaviorManager = TabSheetBehaviorManager( + behavior = BottomSheetBehavior.from(tabsTrayBinding.tabWrapper), + orientation = resources.configuration.orientation, + maxNumberOfTabs = max( + requireContext().components.core.store.state.normalTabs.size, + requireContext().components.core.store.state.privateTabs.size, + ), + numberForExpandingTray = if (requireContext().settings().gridTabView) { + EXPAND_AT_GRID_SIZE + } else { + EXPAND_AT_LIST_SIZE + }, + navigationInteractor = navigationInteractor, + displayMetrics = requireContext().resources.displayMetrics, + ) + + tabsTrayCtaBinding.set( + feature = TabsTrayInfoBannerBinding( + context = view.context, + store = requireComponents.core.store, + infoBannerView = tabsTrayBinding.infoBanner, + settings = requireComponents.settings, + navigationInteractor = navigationInteractor, + ), + owner = this, + view = view, + ) + + tabLayoutMediator.set( + feature = TabLayoutMediator( + tabLayout = tabsTrayBinding.tabLayout, + tabPager = tabsTrayBinding.tabsTray, + interactor = tabsTrayInteractor, + browsingModeManager = activity.browsingModeManager, + tabsTrayStore = tabsTrayStore, + ), + owner = this, + view = view, + ) + + val tabsTrayTabCounter2Binding = TabsTrayTabCounter2Binding.bind( + tabsTrayBinding.tabLayout, + ) + + tabCounterBinding.set( + feature = TabCounterBinding( + store = requireComponents.core.store, + counter = tabsTrayTabCounter2Binding.tabCounter, + ), + owner = this, + view = view, + ) + + floatingActionButtonBinding.set( + feature = FloatingActionButtonBinding( + store = tabsTrayStore, + actionButton = fabButtonBinding.newTabButton, + interactor = tabsTrayInteractor, + ), + owner = this, + view = view, + ) + + val tabsTrayMultiselectItemsBinding = TabstrayMultiselectItemsBinding.bind( + tabsTrayBinding.root, + ) + + selectionBannerBinding.set( + feature = SelectionBannerBinding( + context = requireContext(), + binding = tabsTrayBinding, + store = tabsTrayStore, + navInteractor = navigationInteractor, + tabsTrayInteractor = tabsTrayInteractor, + backgroundView = tabsTrayBinding.topBar, + showOnSelectViews = VisibilityModifier( + tabsTrayMultiselectItemsBinding.collectMultiSelect, + tabsTrayMultiselectItemsBinding.shareMultiSelect, + tabsTrayMultiselectItemsBinding.menuMultiSelect, + tabsTrayBinding.multiselectTitle, + tabsTrayBinding.exitMultiSelect, + ), + showOnNormalViews = VisibilityModifier( + tabsTrayBinding.tabLayout, + tabsTrayBinding.tabTrayOverflow, + fabButtonBinding.newTabButton, + ), + ), + owner = this, + view = view, + ) + + selectionHandleBinding.set( + feature = SelectionHandleBinding( + store = tabsTrayStore, + handle = tabsTrayBinding.handle, + containerLayout = tabsTrayBinding.tabWrapper, + ), + owner = this, + view = view, + ) + + tabsTrayInactiveTabsOnboardingBinding.set( + feature = TabsTrayInactiveTabsOnboardingBinding( + context = requireContext(), + store = requireComponents.core.store, + tabsTrayBinding = tabsTrayBinding, + settings = requireComponents.settings, + navigationInteractor = navigationInteractor, + ), + owner = this, + view = view, + ) + } tabsFeature.set( feature = TabsFeature( @@ -267,92 +382,6 @@ class TabsTrayFragment : AppCompatDialogFragment() { view = view, ) - tabsTrayCtaBinding.set( - feature = TabsTrayInfoBannerBinding( - context = view.context, - store = requireComponents.core.store, - infoBannerView = tabsTrayBinding.infoBanner, - settings = requireComponents.settings, - navigationInteractor = navigationInteractor, - ), - owner = this, - view = view, - ) - - tabLayoutMediator.set( - feature = TabLayoutMediator( - tabLayout = tabsTrayBinding.tabLayout, - tabPager = tabsTrayBinding.tabsTray, - interactor = tabsTrayInteractor, - browsingModeManager = activity.browsingModeManager, - tabsTrayStore = tabsTrayStore, - ), - owner = this, - view = view, - ) - - val tabsTrayTabCounter2Binding = TabsTrayTabCounter2Binding.bind( - tabsTrayBinding.tabLayout, - ) - - tabCounterBinding.set( - feature = TabCounterBinding( - store = requireComponents.core.store, - counter = tabsTrayTabCounter2Binding.tabCounter, - ), - owner = this, - view = view, - ) - - floatingActionButtonBinding.set( - feature = FloatingActionButtonBinding( - store = tabsTrayStore, - actionButton = fabButtonBinding.newTabButton, - interactor = tabsTrayInteractor, - ), - owner = this, - view = view, - ) - - val tabsTrayMultiselectItemsBinding = TabstrayMultiselectItemsBinding.bind( - tabsTrayBinding.root, - ) - - selectionBannerBinding.set( - feature = SelectionBannerBinding( - context = requireContext(), - binding = tabsTrayBinding, - store = tabsTrayStore, - navInteractor = navigationInteractor, - tabsTrayInteractor = tabsTrayInteractor, - backgroundView = tabsTrayBinding.topBar, - showOnSelectViews = VisibilityModifier( - tabsTrayMultiselectItemsBinding.collectMultiSelect, - tabsTrayMultiselectItemsBinding.shareMultiSelect, - tabsTrayMultiselectItemsBinding.menuMultiSelect, - tabsTrayBinding.multiselectTitle, - tabsTrayBinding.exitMultiSelect, - ), - showOnNormalViews = VisibilityModifier( - tabsTrayBinding.tabLayout, - tabsTrayBinding.tabTrayOverflow, - fabButtonBinding.newTabButton, - ), - ), - owner = this, - view = view, - ) - - selectionHandleBinding.set( - feature = SelectionHandleBinding( - store = tabsTrayStore, - handle = tabsTrayBinding.handle, - containerLayout = tabsTrayBinding.tabWrapper, - ), - owner = this, - view = view, - ) - secureTabsTrayBinding.set( feature = SecureTabsTrayBinding( store = tabsTrayStore, @@ -364,18 +393,6 @@ class TabsTrayFragment : AppCompatDialogFragment() { view = view, ) - tabsTrayInactiveTabsOnboardingBinding.set( - feature = TabsTrayInactiveTabsOnboardingBinding( - context = requireContext(), - store = requireComponents.core.store, - tabsTrayBinding = tabsTrayBinding, - settings = requireComponents.settings, - navigationInteractor = navigationInteractor, - ), - owner = this, - view = view, - ) - syncedTabsIntegration.set( feature = SyncedTabsIntegration( store = tabsTrayStore, @@ -397,10 +414,12 @@ class TabsTrayFragment : AppCompatDialogFragment() { override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - trayBehaviorManager.updateDependingOnOrientation(newConfig.orientation) + if (!requireContext().settings().enableTabsTrayToCompose) { + trayBehaviorManager.updateDependingOnOrientation(newConfig.orientation) - if (requireContext().settings().gridTabView) { - tabsTrayBinding.tabsTray.adapter?.notifyDataSetChanged() + if (requireContext().settings().gridTabView) { + tabsTrayBinding.tabsTray.adapter?.notifyDataSetChanged() + } } }