From ccfb275b037481a658bcd75b71945b49c25e62a0 Mon Sep 17 00:00:00 2001 From: Mihai Adrian Carare <48995920+mcarare@users.noreply.github.com> Date: Tue, 30 Mar 2021 23:12:46 +0300 Subject: [PATCH] For #17800 - Request desktop site from home screen. (#18653) --- .../java/org/mozilla/fenix/HomeActivity.kt | 28 ++++++++++++++++--- .../org/mozilla/fenix/home/HomeFragment.kt | 4 +++ .../java/org/mozilla/fenix/home/HomeMenu.kt | 13 +++++++++ .../SessionControlController.kt | 6 ++++ .../fenix/search/SearchDialogController.kt | 17 +++++++---- .../fenix/search/SearchDialogFragment.kt | 8 ++++-- .../fenix/search/SearchDialogInteractor.kt | 4 +-- .../fenix/search/toolbar/ToolbarView.kt | 9 ++++-- .../java/org/mozilla/fenix/utils/Settings.kt | 9 ++++++ app/src/main/res/values/preference_keys.xml | 2 ++ .../DefaultSessionControlControllerTest.kt | 2 ++ .../fenix/search/toolbar/ToolbarViewTest.kt | 3 +- 12 files changed, 86 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 17c276de8..45fd06439 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import mozilla.appservices.places.BookmarkRoot +import mozilla.components.browser.state.action.ContentAction import mozilla.components.browser.state.search.SearchEngine import mozilla.components.browser.state.selector.getNormalOrPrivateTabs import mozilla.components.browser.state.state.SessionState @@ -122,7 +123,7 @@ import java.lang.ref.WeakReference * - browser screen */ @OptIn(ExperimentalCoroutinesApi::class) -@SuppressWarnings("TooManyFunctions", "LargeClass") +@SuppressWarnings("TooManyFunctions", "LargeClass", "LongParameterList") open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { // DO NOT MOVE ANYTHING ABOVE THIS, GETTING INIT TIME IS CRITICAL // we need to store startup timestamp for warm startup. we cant directly store @@ -747,10 +748,11 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { customTabSessionId: String? = null, engine: SearchEngine? = null, forceSearch: Boolean = false, - flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none() + flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), + requestDesktopMode: Boolean = false ) { openToBrowser(from, customTabSessionId) - load(searchTermOrURL, newTab, engine, forceSearch, flags) + load(searchTermOrURL, newTab, engine, forceSearch, flags, requestDesktopMode) } fun openToBrowser(from: BrowserDirection, customTabSessionId: String? = null) { @@ -816,7 +818,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { newTab: Boolean, engine: SearchEngine?, forceSearch: Boolean, - flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none() + flags: EngineSession.LoadUrlFlags = EngineSession.LoadUrlFlags.none(), + requestDesktopMode: Boolean = false ) { val startTime = components.core.engine.profiler?.getProfilerTime() val mode = browsingModeManager.mode @@ -833,6 +836,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { // and let it try to load whatever was entered. if ((!forceSearch && searchTermOrURL.isUrl()) || engine == null) { loadUrlUseCase.invoke(searchTermOrURL.toNormalizedUrl(), flags) + + if (requestDesktopMode) { + handleRequestDesktopMode() + } } else { if (newTab) { components.useCases.searchUseCases.newTabSearch @@ -859,6 +866,19 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } } + internal fun handleRequestDesktopMode() { + val requestDesktopSiteUseCase = + components.useCases.sessionUseCases.requestDesktopSite + requestDesktopSiteUseCase.invoke(true) + components.core.store.dispatch( + ContentAction.UpdateDesktopModeAction( + components.core.store.state.selectedTabId.toString(), true + ) + ) + // Reset preference value after opening the tab in desktop mode + settings().openNextTabInDesktopMode = false + } + open fun navigateToBrowserOnColdStart() { // Normal tabs + cold start -> Should go back to browser if we had any tabs open when we left last // except for PBM + Cold Start there won't be any tabs since they're evicted so we never will navigate diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 8d0127545..535b2e2ca 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -252,6 +252,7 @@ class HomeFragment : Fragment() { restoreUseCase = components.useCases.tabsUseCases.restore, reloadUrlUseCase = components.useCases.sessionUseCases.reload, selectTabUseCase = components.useCases.tabsUseCases.selectTab, + requestDesktopSiteUseCase = components.useCases.sessionUseCases.requestDesktopSite, fragmentStore = homeFragmentStore, navController = findNavController(), viewLifecycleScope = viewLifecycleOwner.lifecycleScope, @@ -854,6 +855,9 @@ class HomeFragment : Fragment() { HomeFragmentDirections.actionGlobalAddonsManagementFragment() ) } + is HomeMenu.Item.DesktopMode -> { + context.settings().openNextTabInDesktopMode = it.checked + } } }, onHighlightPresent = { menuButtonView.get()?.setHighlight(it) }, diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt index 6c1a32760..8bdabcf31 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeMenu.kt @@ -16,6 +16,7 @@ import mozilla.components.browser.menu.BrowserMenuHighlight import mozilla.components.browser.menu.ext.getHighlight import mozilla.components.browser.menu.item.BrowserMenuDivider import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem +import mozilla.components.browser.menu.item.BrowserMenuImageSwitch import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AuthType @@ -48,6 +49,7 @@ class HomeMenu( object Downloads : Item() object Quit : Item() object Sync : Item() + data class DesktopMode(val checked: Boolean) : Item() } private val primaryTextColor = @@ -176,6 +178,14 @@ class HomeMenu( onItemTapped.invoke(Item.Downloads) } + val desktopItem = BrowserMenuImageSwitch( + imageResource = R.drawable.ic_desktop, + label = context.getString(R.string.browser_menu_desktop_site), + initialState = { context.settings().openNextTabInDesktopMode } + ) { checked -> + onItemTapped.invoke(Item.DesktopMode(checked)) + } + // Only query account manager if it has been initialized. // We don't want to cause its initialization just for this check. val accountAuthItem = if (context.components.backgroundServices.accountManagerAvailableQueue.isReady()) { @@ -193,6 +203,9 @@ class HomeMenu( syncedTabsItem, bookmarksItem, historyItem, + BrowserMenuDivider(), + desktopItem, + BrowserMenuDivider(), downloadsItem, BrowserMenuDivider(), addons, diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt index 8339d8c87..e64efd86d 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlController.kt @@ -39,6 +39,7 @@ import org.mozilla.fenix.components.tips.Tip import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.home.HomeFragment import org.mozilla.fenix.home.HomeFragmentAction import org.mozilla.fenix.home.HomeFragmentDirections @@ -181,6 +182,7 @@ class DefaultSessionControlController( private val restoreUseCase: TabsUseCases.RestoreUseCase, private val reloadUrlUseCase: SessionUseCases.ReloadUrlUseCase, private val selectTabUseCase: TabsUseCases.SelectTabUseCase, + private val requestDesktopSiteUseCase: SessionUseCases.RequestDesktopSiteUseCase, private val fragmentStore: HomeFragmentStore, private val navController: NavController, private val viewLifecycleScope: CoroutineScope, @@ -403,6 +405,10 @@ class DefaultSessionControlController( selectTab = true, startLoading = true ) + + if (settings.openNextTabInDesktopMode) { + activity.handleRequestDesktopMode() + } activity.openToBrowser(BrowserDirection.FromHome) } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt index 4a4fe9c4f..a3484f633 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -24,6 +24,7 @@ import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricsUtils import org.mozilla.fenix.crashes.CrashListActivity import org.mozilla.fenix.ext.navigateSafe +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.utils.Settings @@ -32,7 +33,7 @@ import org.mozilla.fenix.utils.Settings */ @Suppress("TooManyFunctions") interface SearchController { - fun handleUrlCommitted(url: String) + fun handleUrlCommitted(url: String, fromHomeScreen: Boolean = false) fun handleEditingCancelled() fun handleTextChanged(text: String) fun handleUrlTapped(url: String) @@ -60,7 +61,7 @@ class SearchDialogController( private val clearToolbar: () -> Unit ) : SearchController { - override fun handleUrlCommitted(url: String) { + override fun handleUrlCommitted(url: String, fromHomeScreen: Boolean) { when (url) { "about:crashes" -> { // The list of past crashes can be accessed via "settings > about", but desktop and @@ -73,16 +74,19 @@ class SearchDialogController( SearchDialogFragmentDirections.actionGlobalAddonsManagementFragment() navController.navigateSafe(R.id.searchDialogFragment, directions) } - "moz://a" -> openSearchOrUrl(SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.MANIFESTO)) + "moz://a" -> openSearchOrUrl( + SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.MANIFESTO), + fromHomeScreen + ) else -> if (url.isNotBlank()) { - openSearchOrUrl(url) + openSearchOrUrl(url, fromHomeScreen) } } dismissDialog() } - private fun openSearchOrUrl(url: String) { + private fun openSearchOrUrl(url: String, fromHomeScreen: Boolean) { clearToolbarFocus() val searchEngine = fragmentStore.state.searchEngineSource.searchEngine @@ -91,7 +95,8 @@ class SearchDialogController( searchTermOrURL = url, newTab = fragmentStore.state.tabId == null, from = BrowserDirection.FromSearchDialog, - engine = searchEngine + engine = searchEngine, + requestDesktopMode = fromHomeScreen && activity.settings().openNextTabInDesktopMode ) val event = if (url.isUrl() || searchEngine == null) { diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index 780724462..53076bd29 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -168,20 +168,22 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { ) ) + val fromHomeFragment = + findNavController().previousBackStackEntry?.destination?.id == R.id.homeFragment + toolbarView = ToolbarView( requireContext(), interactor, historyStorageProvider(), isPrivate, view.toolbar, - requireComponents.core.engine + requireComponents.core.engine, + fromHomeFragment ) val awesomeBar = view.awesome_bar awesomeBar.customizeForBottomToolbar = requireContext().settings().shouldUseBottomToolbar - val fromHomeFragment = - findNavController().previousBackStackEntry?.destination?.id == R.id.homeFragment awesomeBarView = AwesomeBarView( activity, interactor, diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt index 93d1068ba..23ab51129 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogInteractor.kt @@ -17,8 +17,8 @@ class SearchDialogInteractor( private val searchController: SearchDialogController ) : AwesomeBarInteractor, ToolbarInteractor { - override fun onUrlCommitted(url: String) { - searchController.handleUrlCommitted(url) + override fun onUrlCommitted(url: String, fromHomeScreen: Boolean) { + searchController.handleUrlCommitted(url, fromHomeScreen) } override fun onEditingCanceled() { diff --git a/app/src/main/java/org/mozilla/fenix/search/toolbar/ToolbarView.kt b/app/src/main/java/org/mozilla/fenix/search/toolbar/ToolbarView.kt index dea282f36..1462be820 100644 --- a/app/src/main/java/org/mozilla/fenix/search/toolbar/ToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/search/toolbar/ToolbarView.kt @@ -31,8 +31,9 @@ interface ToolbarInteractor { /** * Called when a user hits the return key while [ToolbarView] has focus. * @param url the text inside the [ToolbarView] when committed + * @param fromHomeScreen true if the toolbar has been opened from home screen */ - fun onUrlCommitted(url: String) + fun onUrlCommitted(url: String, fromHomeScreen: Boolean = false) /** * Called when a user removes focus from the [ToolbarView] @@ -49,13 +50,15 @@ interface ToolbarInteractor { /** * View that contains and configures the BrowserToolbar to only be used in its editing mode. */ +@Suppress("LongParameterList") class ToolbarView( private val context: Context, private val interactor: ToolbarInteractor, private val historyStorage: HistoryStorage?, private val isPrivate: Boolean, val view: BrowserToolbar, - engine: Engine + engine: Engine, + fromHomeFragment: Boolean ) { @VisibleForTesting @@ -70,7 +73,7 @@ class ToolbarView( // from resizing in case the BrowserFragment is being displayed before the // keyboard is gone: https://github.com/mozilla-mobile/fenix/issues/8399 hideKeyboard() - interactor.onUrlCommitted(it) + interactor.onUrlCommitted(it, fromHomeFragment) false } diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 24478b24a..b7a12696d 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -1020,4 +1020,13 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = false, featureFlag = FeatureFlags.addressesFeature ) + + /** + * Storing desktop item checkbox value in the home screen menu. + * If set to true, next opened tab from home screen will be opened in desktop mode. + */ + var openNextTabInDesktopMode by booleanPreference( + appContext.getPreferenceKey(R.string.pref_key_open_next_tab_desktop_mode), + default = false + ) } diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 3092b356f..942ec3f8b 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -257,6 +257,8 @@ pref_key_return_to_browser + pref_key_open_next_tab_desktop_mode + pref_key_secret_debug_info pref_key_leanplum_user_id diff --git a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt index 99fbaaf96..8e7c456c3 100644 --- a/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/home/DefaultSessionControlControllerTest.kt @@ -140,6 +140,7 @@ class DefaultSessionControlControllerTest { every { analytics.metrics } returns metrics val restoreUseCase: TabsUseCases.RestoreUseCase = mockk(relaxed = true) + val requestDesktopSiteUseCase: SessionUseCases.RequestDesktopSiteUseCase = mockk(relaxed = true) controller = spyk(DefaultSessionControlController( activity = activity, @@ -152,6 +153,7 @@ class DefaultSessionControlControllerTest { reloadUrlUseCase = reloadUrlUseCase.reload, selectTabUseCase = selectTabUseCase.selectTab, restoreUseCase = restoreUseCase, + requestDesktopSiteUseCase = requestDesktopSiteUseCase, fragmentStore = fragmentStore, navController = navController, viewLifecycleScope = scope, diff --git a/app/src/test/java/org/mozilla/fenix/search/toolbar/ToolbarViewTest.kt b/app/src/test/java/org/mozilla/fenix/search/toolbar/ToolbarViewTest.kt index 0cb32ce9c..1ea3e3788 100644 --- a/app/src/test/java/org/mozilla/fenix/search/toolbar/ToolbarViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/toolbar/ToolbarViewTest.kt @@ -179,6 +179,7 @@ class ToolbarViewTest { historyStorage = null, isPrivate = isPrivate, view = toolbar, - engine = engine + engine = engine, + fromHomeFragment = false ) }