* For #1063 - Adds feature flag and pref for new tab tray * For #1063 - Swaps add tab to tab tray button when newTabTray is enabled * For #1063 - Creates hidden preference to use new tab tray * For #1063 - Hides tabs on home screen when setting is enabled * For #1063 - Navigate to new tab tray from browser with setting enabled * For #1063 - Fixes regression where we dont show the new tab message with no tabs and no collections * For #1063 - Fixes crash when toggling to private mode on the home screen * For #1063 - combines both settings. Cleans up lint errorsmaster
parent
f7dcb9f7b3
commit
a8a90bd4d6
|
@ -43,4 +43,9 @@ object FeatureFlags {
|
|||
* Enables tip feature
|
||||
*/
|
||||
val tips = Config.channel.isDebug
|
||||
|
||||
/**
|
||||
* Enables new tab tray pref
|
||||
*/
|
||||
val tabTray = Config.channel.isDebug
|
||||
}
|
||||
|
|
|
@ -313,6 +313,12 @@ class DefaultBrowserToolbarController(
|
|||
}
|
||||
|
||||
private fun animateTabAndNavigateHome() {
|
||||
if (activity.settings().useNewTabTray) {
|
||||
val directions = BrowserFragmentDirections.actionBrowserFragmentToTabsTrayFragment()
|
||||
navController.navigate(directions)
|
||||
return
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
browserAnimator.beginAnimateOut()
|
||||
// Delay for a short amount of time so the browser has time to start animating out
|
||||
|
|
|
@ -26,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
|
|||
import androidx.constraintlayout.widget.ConstraintSet.TOP
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
|
@ -64,6 +65,7 @@ import mozilla.components.concept.sync.OAuthAccount
|
|||
import mozilla.components.feature.media.ext.pauseIfPlaying
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import mozilla.components.lib.state.ext.flowScoped
|
||||
import mozilla.components.support.ktx.android.util.dpToPx
|
||||
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged
|
||||
|
@ -98,6 +100,7 @@ import org.mozilla.fenix.settings.SupportUtils
|
|||
import org.mozilla.fenix.settings.deletebrowsingdata.deleteAndQuit
|
||||
import org.mozilla.fenix.theme.ThemeManager
|
||||
import org.mozilla.fenix.utils.FragmentPreDrawManager
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
import org.mozilla.fenix.utils.allowUndo
|
||||
import org.mozilla.fenix.whatsnew.WhatsNew
|
||||
import java.lang.ref.WeakReference
|
||||
|
@ -232,14 +235,20 @@ class HomeFragment : Fragment() {
|
|||
updateLayout(view)
|
||||
setOffset(view)
|
||||
sessionControlView = SessionControlView(
|
||||
homeFragmentStore,
|
||||
view.sessionControlRecyclerView,
|
||||
sessionControlInteractor,
|
||||
viewLifecycleOwner,
|
||||
homeViewModel
|
||||
)
|
||||
activity.themeManager.applyStatusBarTheme(activity)
|
||||
|
||||
view.consumeFrom(homeFragmentStore, viewLifecycleOwner) {
|
||||
sessionControlView?.update(it)
|
||||
|
||||
if (context?.settings()?.useNewTabTray == true) {
|
||||
view.tab_button.setCountWithAnimation(it.tabs.size)
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
|
@ -344,6 +353,12 @@ class HomeFragment : Fragment() {
|
|||
navigateToSearch()
|
||||
}
|
||||
|
||||
view.tab_button.setOnClickListener {
|
||||
invokePendingDeleteJobs()
|
||||
hideOnboardingIfNeeded()
|
||||
findNavController().navigate(HomeFragmentDirections.actionGlobalTabTrayFragment())
|
||||
}
|
||||
|
||||
PrivateBrowsingButtonView(
|
||||
privateBrowsingButton,
|
||||
browsingModeManager
|
||||
|
@ -538,6 +553,11 @@ class HomeFragment : Fragment() {
|
|||
scrollToSelectedTab()
|
||||
sharedViewModel.shouldScrollToSelectedTab = false
|
||||
}
|
||||
|
||||
requireContext().settings().useNewTabTray.also {
|
||||
view?.add_tab_button?.isVisible = !it
|
||||
view?.tab_button?.isVisible = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
package org.mozilla.fenix.home.sessioncontrol
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -14,15 +14,14 @@ import kotlinx.android.extensions.LayoutContainer
|
|||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.feature.tab.collections.TabCollection
|
||||
import mozilla.components.feature.top.sites.TopSite
|
||||
import mozilla.components.lib.state.ext.consumeFrom
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.home.HomeFragmentState
|
||||
import org.mozilla.fenix.home.HomeFragmentStore
|
||||
import org.mozilla.fenix.home.HomeScreenViewModel
|
||||
import org.mozilla.fenix.home.Mode
|
||||
import org.mozilla.fenix.home.OnboardingState
|
||||
import org.mozilla.fenix.home.Tab
|
||||
import org.mozilla.fenix.components.tips.Tip
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
val noTabMessage = AdapterItem.NoContentMessageWithAction(
|
||||
R.string.no_open_tabs_header_2,
|
||||
|
@ -36,7 +35,11 @@ val noCollectionMessage = AdapterItem.NoContentMessage(
|
|||
R.string.collections_description
|
||||
)
|
||||
|
||||
// This method got a little complex with the addition of the tab tray feature flag
|
||||
// When we remove the tabs from the home screen this will get much simpler again.
|
||||
@SuppressWarnings("LongParameterList", "ComplexMethod")
|
||||
private fun normalModeAdapterItems(
|
||||
context: Context,
|
||||
tabs: List<Tab>,
|
||||
topSites: List<TopSite>,
|
||||
collections: List<TabCollection>,
|
||||
|
@ -52,26 +55,30 @@ private fun normalModeAdapterItems(
|
|||
items.add(AdapterItem.TopSiteList(topSites))
|
||||
}
|
||||
|
||||
items.add(AdapterItem.TabHeader(false, tabs.isNotEmpty()))
|
||||
val useNewTabTray = context.settings().useNewTabTray
|
||||
|
||||
if (!useNewTabTray) {
|
||||
items.add(AdapterItem.TabHeader(false, tabs.isNotEmpty()))
|
||||
}
|
||||
|
||||
when {
|
||||
tabs.isNotEmpty() && collections.isNotEmpty() -> {
|
||||
showTabs(items, tabs)
|
||||
if (!useNewTabTray) { showTabs(items, tabs) }
|
||||
showCollections(collections, expandedCollections, tabs, items)
|
||||
}
|
||||
|
||||
tabs.isNotEmpty() && collections.isEmpty() -> {
|
||||
showTabs(items, tabs)
|
||||
if (!useNewTabTray) { showTabs(items, tabs) }
|
||||
items.add(AdapterItem.CollectionHeader)
|
||||
items.add(noCollectionMessage)
|
||||
}
|
||||
|
||||
tabs.isEmpty() && collections.isNotEmpty() -> {
|
||||
items.add(noTabMessage)
|
||||
if (!useNewTabTray) { items.add(noTabMessage) }
|
||||
showCollections(collections, expandedCollections, tabs, items)
|
||||
}
|
||||
|
||||
tabs.isEmpty() && collections.isEmpty() -> {
|
||||
tabs.isEmpty() && collections.isEmpty() && !useNewTabTray -> {
|
||||
items.add(noTabMessage)
|
||||
}
|
||||
}
|
||||
|
@ -105,14 +112,21 @@ private fun showCollections(
|
|||
}
|
||||
}
|
||||
|
||||
private fun privateModeAdapterItems(tabs: List<Tab>): List<AdapterItem> {
|
||||
private fun privateModeAdapterItems(context: Context, tabs: List<Tab>): List<AdapterItem> {
|
||||
val items = mutableListOf<AdapterItem>()
|
||||
items.add(AdapterItem.TabHeader(true, tabs.isNotEmpty()))
|
||||
|
||||
if (tabs.isNotEmpty()) {
|
||||
items.addAll(tabs.reversed().map(AdapterItem::TabItem))
|
||||
} else {
|
||||
val useNewTabTray = context.settings().useNewTabTray
|
||||
|
||||
if (useNewTabTray) {
|
||||
items.add(AdapterItem.PrivateBrowsingDescription)
|
||||
} else {
|
||||
items.add(AdapterItem.TabHeader(true, tabs.isNotEmpty()))
|
||||
|
||||
if (tabs.isNotEmpty()) {
|
||||
items.addAll(tabs.reversed().map(AdapterItem::TabItem))
|
||||
} else {
|
||||
items.add(AdapterItem.PrivateBrowsingDescription)
|
||||
}
|
||||
}
|
||||
|
||||
return items
|
||||
|
@ -153,9 +167,9 @@ private fun onboardingAdapterItems(onboardingState: OnboardingState): List<Adapt
|
|||
return items
|
||||
}
|
||||
|
||||
private fun HomeFragmentState.toAdapterList(): List<AdapterItem> = when (mode) {
|
||||
is Mode.Normal -> normalModeAdapterItems(tabs, topSites, collections, expandedCollections, tip)
|
||||
is Mode.Private -> privateModeAdapterItems(tabs)
|
||||
private fun HomeFragmentState.toAdapterList(context: Context): List<AdapterItem> = when (mode) {
|
||||
is Mode.Normal -> normalModeAdapterItems(context, tabs, topSites, collections, expandedCollections, tip)
|
||||
is Mode.Private -> privateModeAdapterItems(context, tabs)
|
||||
is Mode.Onboarding -> onboardingAdapterItems(mode.state)
|
||||
}
|
||||
|
||||
|
@ -165,10 +179,8 @@ private fun collectionTabItems(collection: TabCollection) = collection.tabs.mapI
|
|||
|
||||
@ExperimentalCoroutinesApi
|
||||
class SessionControlView(
|
||||
private val homeFragmentStore: HomeFragmentStore,
|
||||
override val containerView: View?,
|
||||
interactor: SessionControlInteractor,
|
||||
private val viewLifecycleOwner: LifecycleOwner,
|
||||
private var homeScreenViewModel: HomeScreenViewModel
|
||||
) : LayoutContainer {
|
||||
|
||||
|
@ -187,10 +199,6 @@ class SessionControlView(
|
|||
)
|
||||
)
|
||||
itemTouchHelper.attachToRecyclerView(this)
|
||||
|
||||
view.consumeFrom(homeFragmentStore, viewLifecycleOwner) {
|
||||
update(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +208,7 @@ class SessionControlView(
|
|||
sessionControlAdapter.submitList(null)
|
||||
}
|
||||
|
||||
val stateAdapterList = state.toAdapterList()
|
||||
val stateAdapterList = state.toAdapterList(view.context)
|
||||
|
||||
if (homeScreenViewModel.shouldScrollToTopSites) {
|
||||
sessionControlAdapter.submitList(stateAdapterList) {
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* 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.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.showToolbar
|
||||
|
||||
/**
|
||||
* Lets the user customize Private browsing options.
|
||||
*/
|
||||
class SecretSettingsPreference : PreferenceFragmentCompat() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
showToolbar(getString(R.string.preferences_debug_settings))
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.secret_settings_preferences, rootKey)
|
||||
updatePreferences()
|
||||
}
|
||||
|
||||
private fun updatePreferences() {
|
||||
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_enable_new_tab_tray))?.apply {
|
||||
onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||
isChecked = context.settings().useNewTabTray
|
||||
}
|
||||
}
|
||||
}
|
|
@ -277,6 +277,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
startActivity(intent)
|
||||
null
|
||||
}
|
||||
resources.getString(R.string.pref_key_debug_settings) -> {
|
||||
SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment()
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
directions?.let { navigateFromSettings(directions) }
|
||||
|
@ -327,6 +330,9 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
preferenceFxAOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater
|
||||
preferenceSyncOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater
|
||||
findPreference<Preference>(
|
||||
getPreferenceKey(R.string.pref_key_debug_settings)
|
||||
)?.isVisible = requireContext().settings().showSecretDebugMenuThisSession
|
||||
}
|
||||
|
||||
private fun navigateFromSettings(directions: NavDirections) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import mozilla.components.support.ktx.android.content.longPreference
|
|||
import mozilla.components.support.ktx.android.content.stringPreference
|
||||
import org.mozilla.fenix.BuildConfig
|
||||
import org.mozilla.fenix.Config
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.components.metrics.MozillaProductDetector
|
||||
|
@ -635,4 +636,15 @@ class Settings private constructor(
|
|||
appContext.getPreferenceKey(R.string.pref_key_top_sites_size),
|
||||
default = 0
|
||||
)
|
||||
|
||||
var useNewTabTray: Boolean
|
||||
get() = preferences.let {
|
||||
val prefKey = appContext.getPreferenceKey(R.string.pref_key_enable_new_tab_tray)
|
||||
val useNewTabTray = it.getBoolean(prefKey, false)
|
||||
FeatureFlags.tabTray && useNewTabTray }
|
||||
set(value) {
|
||||
preferences.edit()
|
||||
.putBoolean(appContext.getPreferenceKey(R.string.pref_key_enable_new_tab_tray), value)
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
android:contentDescription="@string/search_hint"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="@id/bottom_bar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/add_tab_button"
|
||||
app:layout_constraintEnd_toStartOf="@+id/accessory_button_barrier"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/bottom_bar">
|
||||
|
||||
|
@ -135,6 +135,13 @@
|
|||
android:textSize="15sp" />
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/accessory_button_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="start"
|
||||
app:constraint_referenced_ids="tab_button,add_tab_button" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/add_tab_button"
|
||||
android:layout_width="48dp"
|
||||
|
@ -147,6 +154,17 @@
|
|||
app:layout_constraintEnd_toStartOf="@+id/menuButton"
|
||||
app:layout_constraintStart_toEndOf="@id/toolbar_wrapper"/>
|
||||
|
||||
|
||||
<org.mozilla.fenix.components.toolbar.TabCounter
|
||||
android:id="@+id/tab_button"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="@id/bottom_bar"
|
||||
app:layout_constraintBottom_toBottomOf="@id/bottom_bar"
|
||||
app:layout_constraintEnd_toStartOf="@+id/menuButton"
|
||||
app:layout_constraintStart_toEndOf="@id/toolbar_wrapper"/>
|
||||
|
||||
<mozilla.components.browser.menu.view.MenuButton
|
||||
android:id="@+id/menuButton"
|
||||
android:layout_width="36dp"
|
||||
|
|
|
@ -365,6 +365,13 @@
|
|||
app:popEnterAnim="@anim/slide_in_left"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:destination="@id/aboutFragment" />
|
||||
<action
|
||||
android:id="@+id/action_settingsFragment_to_secretSettingsFragment"
|
||||
app:enterAnim="@anim/slide_in_right"
|
||||
app:exitAnim="@anim/slide_out_left"
|
||||
app:popEnterAnim="@anim/slide_in_left"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:destination="@id/secretSettingsPreference" />
|
||||
<action
|
||||
android:id="@+id/action_settingsFragment_to_customizationFragment"
|
||||
app:enterAnim="@anim/slide_in_right"
|
||||
|
@ -500,6 +507,10 @@
|
|||
<fragment
|
||||
android:id="@+id/aboutFragment"
|
||||
android:name="org.mozilla.fenix.settings.about.AboutFragment"/>
|
||||
<fragment
|
||||
android:id="@+id/secretSettingsPreference"
|
||||
android:name="org.mozilla.fenix.settings.SecretSettingsPreference"
|
||||
android:label="@string/preferences_debug_settings" />
|
||||
<fragment
|
||||
android:id="@+id/crashReporterFragment"
|
||||
android:name="org.mozilla.fenix.crashes.CrashReporterFragment">
|
||||
|
|
|
@ -165,4 +165,7 @@
|
|||
<string name="pref_key_migrating_from_firefox_nightly_tip" translatable="false">pref_key_migrating_from_firefox_nightly_tip</string>
|
||||
<string name="pref_key_migrating_from_fenix_tip" translatable="false">pref_key_migrating_from_fenix_tip</string>
|
||||
|
||||
<string name="pref_key_enable_new_tab_tray" translatable="false">pref_key_new_tab_tray</string>
|
||||
|
||||
<string name="pref_key_debug_settings" translatable="false">pref_key_debug_settings</string>
|
||||
</resources>
|
||||
|
|
|
@ -43,4 +43,8 @@
|
|||
<string name="tab_tray_menu_home" translatable="false">Go home</string>
|
||||
<!-- Shortcut action to toggle private mode -->
|
||||
<string name="tab_tray_menu_toggle" translatable="false">Toggle tab mode</string>
|
||||
|
||||
<!-- Label for the secret settings preference -->
|
||||
<string name="preferences_debug_settings">Secret Settings</string>
|
||||
<string name="preferences_debug_settings_enable_tab_tray">Use New Tab Tray</string>
|
||||
</resources>
|
||||
|
|
|
@ -159,5 +159,11 @@
|
|||
android:icon="@drawable/ic_info"
|
||||
android:key="@string/pref_key_about"
|
||||
android:title="@string/preferences_about" />
|
||||
|
||||
<androidx.preference.Preference
|
||||
android:icon="@drawable/ic_info"
|
||||
android:key="@string/pref_key_debug_settings"
|
||||
android:title="@string/preferences_debug_settings"
|
||||
app:isPreferenceVisible="false" />
|
||||
</androidx.preference.PreferenceCategory>
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="@string/pref_key_enable_new_tab_tray"
|
||||
android:title="@string/preferences_debug_settings_enable_tab_tray"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
Loading…
Reference in New Issue