diff --git a/app/src/main/java/org/mozilla/fenix/GlobalDirections.kt b/app/src/main/java/org/mozilla/fenix/GlobalDirections.kt new file mode 100644 index 000000000..76cdd6971 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/GlobalDirections.kt @@ -0,0 +1,37 @@ +/* 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 + +import androidx.navigation.NavDirections + +/** + * Used with [HomeActivity] global navigation to indicate which fragment is being opened. + * + * @property navDirections NavDirections to navigate to destination + * @property destinationId fragment ID of the fragment being navigated to + */ +enum class GlobalDirections(val navDirections: NavDirections, val destinationId: Int) { + Home(NavGraphDirections.actionGlobalHomeFragment(), R.id.homeFragment), + Settings( + NavGraphDirections.actionGlobalSettingsFragment(), + R.id.settingsFragment + ), + Sync( + NavGraphDirections.actionGlobalTurnOnSync(), + R.id.turnOnSyncFragment + ), + SearchEngine( + NavGraphDirections.actionGlobalSearchEngineFragment(), + R.id.searchEngineFragment + ), + Accessibility( + NavGraphDirections.actionGlobalAccessibilityFragment(), + R.id.accessibilityFragment + ), + DeleteData( + NavGraphDirections.actionGlobalDeleteBrowsingDataFragment(), + R.id.deleteBrowsingDataFragment + ) +} diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 4f6d774da..3c788ff67 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -38,14 +38,21 @@ import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.isSentryEnabled import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.SentryBreadcrumbsRecorder +import org.mozilla.fenix.exceptions.ExceptionsFragmentDirections +import org.mozilla.fenix.ext.alreadyOnDestination import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getRootView import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.intent.CrashReporterIntentProcessor import org.mozilla.fenix.home.intent.DeepLinkIntentProcessor import org.mozilla.fenix.home.intent.OpenBrowserIntentProcessor import org.mozilla.fenix.home.intent.SpeechProcessingIntentProcessor import org.mozilla.fenix.home.intent.StartSearchIntentProcessor +import org.mozilla.fenix.library.bookmarks.BookmarkFragmentDirections +import org.mozilla.fenix.library.history.HistoryFragmentDirections +import org.mozilla.fenix.search.SearchFragmentDirections +import org.mozilla.fenix.settings.SettingsFragmentDirections import org.mozilla.fenix.share.ShareFragment import org.mozilla.fenix.theme.DefaultThemeManager import org.mozilla.fenix.theme.ThemeManager @@ -193,16 +200,48 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback load(searchTermOrURL, newTab, engine, forceSearch) } + @Suppress("ComplexMethod") fun openToBrowser(from: BrowserDirection, customTabSessionId: String? = null) { if (sessionObserver == null) sessionObserver = subscribeToSessions() - with(navHost.navController) { - if (currentDestination?.id == R.id.browserFragment || popBackStack(R.id.browserFragment, false)) return + if (navHost.navController.alreadyOnDestination(R.id.browserFragment)) return + @IdRes val fragmentId = if (from.fragmentId != 0) from.fragmentId else null + val directions = when (from) { + BrowserDirection.FromGlobal -> { + NavGraphDirections.actionGlobalBrowser(customTabSessionId) + } + BrowserDirection.FromHome -> { + HomeFragmentDirections.actionHomeFragmentToBrowserFragment(customTabSessionId) + } + BrowserDirection.FromSearch -> { + SearchFragmentDirections.actionSearchFragmentToBrowserFragment( + customTabSessionId + ) + } + BrowserDirection.FromSettings -> { + SettingsFragmentDirections.actionSettingsFragmentToBrowserFragment( + customTabSessionId + ) + } + BrowserDirection.FromBookmarks -> { + BookmarkFragmentDirections.actionBookmarkFragmentToBrowserFragment( + customTabSessionId + ) + } + BrowserDirection.FromHistory -> { + HistoryFragmentDirections.actionHistoryFragmentToBrowserFragment( + customTabSessionId + ) + } + BrowserDirection.FromExceptions -> { + ExceptionsFragmentDirections.actionExceptionsFragmentToBrowserFragment( + customTabSessionId + ) + } } - @IdRes val fragmentId = if (from.fragmentId != 0) from.fragmentId else null - navHost.navController.nav(fragmentId, NavGraphDirections.actionGlobalBrowser(customTabSessionId)) + navHost.navController.nav(fragmentId, directions) } private fun load( diff --git a/app/src/main/java/org/mozilla/fenix/ext/NavController.kt b/app/src/main/java/org/mozilla/fenix/ext/NavController.kt index 065914404..58a6232cd 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/NavController.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/NavController.kt @@ -51,6 +51,10 @@ fun NavController.nav( } } +fun NavController.alreadyOnDestination(@IdRes destId: Int?): Boolean { + return destId?.let { currentDestination?.id == it || popBackStack(it, false) } ?: false +} + fun recordIdException(actual: Int?, expected: Int?) { if (!BuildConfig.SENTRY_TOKEN.isNullOrEmpty()) { Sentry.capture("Fragment id $actual did not match expected $expected") diff --git a/app/src/main/java/org/mozilla/fenix/home/intent/DeepLinkIntentProcessor.kt b/app/src/main/java/org/mozilla/fenix/home/intent/DeepLinkIntentProcessor.kt index ba3e5aaa5..3e71695c3 100644 --- a/app/src/main/java/org/mozilla/fenix/home/intent/DeepLinkIntentProcessor.kt +++ b/app/src/main/java/org/mozilla/fenix/home/intent/DeepLinkIntentProcessor.kt @@ -11,9 +11,10 @@ import android.os.Build.VERSION.SDK_INT import android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS import androidx.navigation.NavController import org.mozilla.fenix.BrowserDirection +import org.mozilla.fenix.GlobalDirections import org.mozilla.fenix.HomeActivity -import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.browser.browsingmode.BrowsingMode +import org.mozilla.fenix.ext.alreadyOnDestination /** * Deep links in the form of `fenix://host` open different parts of the app. @@ -34,17 +35,19 @@ class DeepLinkIntentProcessor( private fun handleDeepLink(deepLink: Uri, navController: NavController) { handleDeepLinkSideEffects(deepLink) - val directions = when (deepLink.host) { - "home", "enable_private_browsing" -> NavGraphDirections.actionGlobalHomeFragment() - "settings" -> NavGraphDirections.actionGlobalSettingsFragment() - "turn_on_sync" -> NavGraphDirections.actionGlobalTurnOnSync() - "settings_search_engine" -> NavGraphDirections.actionGlobalSearchEngineFragment() - "settings_accessibility" -> NavGraphDirections.actionGlobalAccessibilityFragment() - "settings_delete_browsing_data" -> NavGraphDirections.actionGlobalDeleteBrowsingDataFragment() + val globalDirections = when (deepLink.host) { + "home", "enable_private_browsing" -> GlobalDirections.Home + "settings" -> GlobalDirections.Settings + "turn_on_sync" -> GlobalDirections.Sync + "settings_search_engine" -> GlobalDirections.SearchEngine + "settings_accessibility" -> GlobalDirections.Accessibility + "settings_delete_browsing_data" -> GlobalDirections.DeleteData else -> return } - navController.navigate(directions) + if (!navController.alreadyOnDestination(globalDirections.destinationId)) { + navController.navigate(globalDirections.navDirections) + } } /** 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 c3497729c..77127e38a 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 @@ -93,6 +93,7 @@ class ToolbarView( setOnEditListener(object : mozilla.components.concept.toolbar.Toolbar.OnEditListener { override fun onCancelEditing(): Boolean { interactor.onEditingCanceled() + // We need to return false to not show display mode return false } override fun onTextChanged(text: String) {