diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt index 21d6fdb6a..4f9a0885e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/DeepLinkTest.kt @@ -29,6 +29,8 @@ import org.mozilla.fenix.ui.robots.DeepLinkRobot * - fenix://urls_bookmarks — take the user to the bookmarks list * - fenix://settings_logins — take the user to the settings page to do with logins (not the saved logins). **/ + +@Ignore("All tests perma-failing, see: https://github.com/mozilla-mobile/fenix/issues/13491") class DeepLinkTest { private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) private lateinit var mockWebServer: MockWebServer diff --git a/app/src/geckoRelease/java/org/mozilla/fenix/engine/GeckoProvider.kt b/app/src/geckoRelease/java/org/mozilla/fenix/engine/GeckoProvider.kt index f2f715078..ef75ce688 100644 --- a/app/src/geckoRelease/java/org/mozilla/fenix/engine/GeckoProvider.kt +++ b/app/src/geckoRelease/java/org/mozilla/fenix/engine/GeckoProvider.kt @@ -5,6 +5,7 @@ import android.content.Context import android.os.Bundle import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper +import mozilla.components.browser.engine.gecko.ext.toContentBlockingSetting import mozilla.components.browser.engine.gecko.glean.GeckoAdapter import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy import mozilla.components.concept.storage.LoginsStorage @@ -50,8 +51,7 @@ object GeckoProvider { val runtimeSettings = builder .crashHandler(CrashHandlerService::class.java) .telemetryDelegate(GeckoAdapter()) - // TODO: Fix me! - // .contentBlocking(policy.toContentBlockingSetting()) + .contentBlocking(policy.toContentBlockingSetting()) .aboutConfigEnabled(Config.channel.isBeta) .debugLogging(Config.channel.isDebug) .build() diff --git a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt index 312460f1d..915320890 100644 --- a/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt +++ b/app/src/main/java/org/mozilla/fenix/AppRequestInterceptor.kt @@ -28,7 +28,14 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor { ): RequestInterceptor.InterceptionResponse? { return context.components.services.appLinksInterceptor .onLoadRequest( - engineSession, uri, lastUri, hasUserGesture, isSameDomain, isRedirect, isDirectNavigation, isSubframeRequest + engineSession, + uri, + lastUri, + hasUserGesture, + isSameDomain, + isRedirect, + isDirectNavigation, + isSubframeRequest ) } diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index c98f1b555..da2c235cf 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -48,4 +48,9 @@ object FeatureFlags { * Enables wait til first contentful paint */ val waitUntilPaintToDraw = Config.channel.isNightlyOrDebug + + /** + * Enables downloads with external download managers. + */ + val externalDownloadManager = Config.channel.isNightlyOrDebug } diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 479e168c9..f30d021a6 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -252,10 +252,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { lifecycleScope.launch(IO) { if ( settings().isDefaultBrowser() && - settings().wasDefaultBrowserOnLastPause != settings().isDefaultBrowser() + settings().wasDefaultBrowserOnLastResume != settings().isDefaultBrowser() ) { metrics.track(Event.ChangedToDefaultBrowser) } + + settings().wasDefaultBrowserOnLastResume = settings().isDefaultBrowser() } } @@ -264,11 +266,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) } - if (settings().wasDefaultBrowserOnLastPause != settings().isDefaultBrowser() - ) { - settings().wasDefaultBrowserOnLastPause = settings().isDefaultBrowser() - } - super.onPause() // Every time the application goes into the background, it is possible that the user diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index c7c350808..c48c7f73d 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -21,6 +21,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import androidx.preference.PreferenceManager import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.android.synthetic.main.fragment_browser.view.* @@ -41,7 +42,6 @@ import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab import mozilla.components.browser.state.state.SessionState import mozilla.components.browser.state.state.content.DownloadState import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.browser.thumbnails.BrowserThumbnails import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.feature.accounts.FxaCapability import mozilla.components.feature.accounts.FxaWebChannelFeature @@ -99,6 +99,7 @@ import org.mozilla.fenix.downloads.DynamicDownloadDialog import org.mozilla.fenix.ext.accessibilityManager import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.enterToImmersiveMode +import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.hideToolbar import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.nav @@ -138,7 +139,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session private val appLinksFeature = ViewBoundFeatureWrapper() private val promptsFeature = ViewBoundFeatureWrapper() private val findInPageIntegration = ViewBoundFeatureWrapper() - private val thumbnailsFeature = ViewBoundFeatureWrapper() private val toolbarIntegration = ViewBoundFeatureWrapper() private val sitePermissionsFeature = ViewBoundFeatureWrapper() private val fullScreenFeature = ViewBoundFeatureWrapper() @@ -279,12 +279,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session lifecycleOwner = viewLifecycleOwner ) - thumbnailsFeature.set( - feature = BrowserThumbnails(context, view.engineView, store), - owner = this, - view = view - ) - toolbarIntegration.set( feature = browserToolbarView.toolbarIntegration, owner = this, @@ -346,6 +340,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session view = view ) + val shouldForwardToThirdParties = + PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + context.getPreferenceKey(R.string.pref_key_external_download_manager), false + ) + val downloadFeature = DownloadsFeature( context.applicationContext, store = store, @@ -357,6 +356,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session store, DownloadService::class ), + shouldForwardToThirdParties = { shouldForwardToThirdParties }, promptsStyling = DownloadsFeature.PromptsStyling( gravity = Gravity.BOTTOM, shouldWidthMatchParent = true, @@ -586,7 +586,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session .ifChanged { it.content.firstContentfulPaint } .collect { val showEngineView = - it.content.firstContentfulPaint || it.content.progress == 100 + it.content.firstContentfulPaint || it.content.progress == LOADING_PROGRESS_COMPLETE if (showEngineView) { engineView?.asView()?.isVisible = true @@ -804,11 +804,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session } override fun onBackLongPressed(): Boolean { - if (FeatureFlags.tabHistory) { - findNavController().navigate(R.id.action_global_tabHistoryDialogFragment) - return true - } - return false + findNavController().navigate(R.id.action_global_tabHistoryDialogFragment) + return true } /** @@ -1074,6 +1071,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session private const val REQUEST_CODE_DOWNLOAD_PERMISSIONS = 1 private const val REQUEST_CODE_PROMPT_PERMISSIONS = 2 private const val REQUEST_CODE_APP_PERMISSIONS = 3 + + private const val LOADING_PROGRESS_COMPLETE = 100 } override fun onAccessibilityStateChanged(enabled: Boolean) { diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt index 9a32bf1b6..559e594cf 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt @@ -42,7 +42,7 @@ class BrowserAnimator( if (unwrappedSwipeRefresh?.context?.settings()?.waitToShowPageUntilFirstPaint == true) { if (firstContentfulHappened()) { viewLifecycleScope.get()?.launch { - delay(100) + delay(ANIMATION_DELAY) unwrappedEngineView?.asView()?.visibility = View.VISIBLE unwrappedSwipeRefresh?.background = null unwrappedSwipeRefresh?.alpha = 1f @@ -91,6 +91,8 @@ class BrowserAnimator( } companion object { + private const val ANIMATION_DELAY = 100L + fun getToolbarNavOptions(context: Context): NavOptions { val navOptions = NavOptions.Builder() diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index 1fd155f63..9163d8ab5 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -21,6 +21,7 @@ import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.browser.session.Session import mozilla.components.browser.state.selector.findTab +import mozilla.components.browser.thumbnails.BrowserThumbnails import mozilla.components.browser.toolbar.BrowserToolbar import mozilla.components.feature.app.links.AppLinksUseCases import mozilla.components.feature.contextmenu.ContextMenuCandidate @@ -55,6 +56,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { private val windowFeature = ViewBoundFeatureWrapper() private val searchFeature = ViewBoundFeatureWrapper() + private val thumbnailsFeature = ViewBoundFeatureWrapper() private var readerModeAvailable = false @@ -107,6 +109,12 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { browserToolbarView.view.addPageAction(readerModeAction) + thumbnailsFeature.set( + feature = BrowserThumbnails(context, view.engineView, components.core.store), + owner = this, + view = view + ) + readerViewFeature.set( feature = StrictMode.allowThreadDiskReads().resetPoliciesAfter { ReaderViewFeature( diff --git a/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt b/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt index 747c5cb40..ccd2b3ce4 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/ToolbarGestureHandler.kt @@ -35,6 +35,7 @@ import kotlin.math.min * Handles intercepting touch events on the toolbar for swipe gestures and executes the * necessary animations. */ +@Suppress("LargeClass", "TooManyFunctions") class ToolbarGestureHandler( private val activity: Activity, private val contentLayout: View, @@ -76,6 +77,7 @@ class ToolbarGestureHandler( GestureDirection.LEFT_TO_RIGHT } + @Suppress("ComplexCondition") return if ( !activity.window.decorView.isKeyboardVisible() && start.isInToolbar() && diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt index 3fc636e4a..d6b4737f6 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/LeanplumMetricsService.kt @@ -95,6 +95,7 @@ class LeanplumMetricsService( deviceId } + @Suppress("ComplexMethod") override fun start() { if (!application.settings().isMarketingTelemetryEnabled) return @@ -255,7 +256,7 @@ class LeanplumMetricsService( "jpn" // Japanese ) - private val PREFERENCE_NAME = "LEANPLUM_PREFERENCES" - private val DEVICE_ID_KEY = "LP_DEVICE_ID" + private const val PREFERENCE_NAME = "LEANPLUM_PREFERENCES" + private const val DEVICE_ID_KEY = "LP_DEVICE_ID" } } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index 16b47a519..1694d89f0 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -140,6 +140,7 @@ internal class ReleaseMetricController( MetricServiceType.Marketing -> isMarketingDataTelemetryEnabled() } + @Suppress("LongMethod") private fun Fact.toEvent(): Event? = when (Pair(component, item)) { Component.FEATURE_PROMPTS to LoginDialogFacts.Items.DISPLAY -> Event.LoginDialogPromptDisplayed Component.FEATURE_PROMPTS to LoginDialogFacts.Items.CANCEL -> Event.LoginDialogPromptCancelled diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index 953473302..5fd5b8ec6 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -23,7 +23,6 @@ import mozilla.components.concept.engine.prompt.ShareData import mozilla.components.feature.session.SessionFeature import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.ktx.kotlin.isUrl -import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.NavGraphDirections import org.mozilla.fenix.R @@ -204,14 +203,18 @@ class DefaultBrowserToolbarController( trackToolbarItemInteraction(item) Do exhaustive when (item) { - ToolbarMenu.Item.Back -> sessionUseCases.goBack.invoke(currentSession) - is ToolbarMenu.Item.Forward -> { - if (FeatureFlags.tabHistory && item.viewHistory) { + is ToolbarMenu.Item.Back -> { + if (item.viewHistory) { navController.navigate(R.id.action_global_tabHistoryDialogFragment) - } else if (!item.viewHistory) { - sessionUseCases.goForward.invoke(currentSession) } else { - // Do nothing if tab history feature flag is off and item.viewHistory is true + sessionUseCases.goBack.invoke(currentSession) + } + } + is ToolbarMenu.Item.Forward -> { + if (item.viewHistory) { + navController.navigate(R.id.action_global_tabHistoryDialogFragment) + } else { + sessionUseCases.goForward.invoke(currentSession) } } is ToolbarMenu.Item.Reload -> { @@ -383,7 +386,7 @@ class DefaultBrowserToolbarController( @Suppress("ComplexMethod") private fun trackToolbarItemInteraction(item: ToolbarMenu.Item) { val eventItem = when (item) { - ToolbarMenu.Item.Back -> Event.BrowserMenuItemTapped.Item.BACK + is ToolbarMenu.Item.Back -> Event.BrowserMenuItemTapped.Item.BACK is ToolbarMenu.Item.Forward -> Event.BrowserMenuItemTapped.Item.FORWARD is ToolbarMenu.Item.Reload -> Event.BrowserMenuItemTapped.Item.RELOAD ToolbarMenu.Item.Stop -> Event.BrowserMenuItemTapped.Item.STOP diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt index 6b1bf2316..ecaeff835 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt @@ -250,8 +250,10 @@ class BrowserToolbarView( private const val TOOLBAR_ELEVATION = 16 } + @Suppress("ComplexCondition") private fun ToolbarMenu.Item.performHapticIfNeeded(view: View) { if (this is ToolbarMenu.Item.Reload && this.bypassCache || + this is ToolbarMenu.Item.Back && this.viewHistory || this is ToolbarMenu.Item.Forward && this.viewHistory ) { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt index db8ebb164..dc98afa23 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/DefaultToolbarMenu.kt @@ -74,6 +74,20 @@ class DefaultToolbarMenu( } override val menuToolbar by lazy { + val back = BrowserMenuItemToolbar.TwoStateButton( + primaryImageResource = mozilla.components.ui.icons.R.drawable.mozac_ic_back, + primaryContentDescription = context.getString(R.string.browser_menu_back), + primaryImageTintResource = primaryTextColor(), + isInPrimaryState = { + session?.canGoBack ?: true + }, + secondaryImageTintResource = ThemeManager.resolveAttribute(R.attr.disabled, context), + disableInSecondaryState = true, + longClickListener = { onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = true)) } + ) { + onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = false)) + } + val forward = BrowserMenuItemToolbar.TwoStateButton( primaryImageResource = mozilla.components.ui.icons.R.drawable.mozac_ic_forward, primaryContentDescription = context.getString(R.string.browser_menu_forward), @@ -135,7 +149,7 @@ class DefaultToolbarMenu( onItemTapped.invoke(ToolbarMenu.Item.Bookmark) } - BrowserMenuItemToolbar(listOf(bookmark, share, forward, refresh)) + BrowserMenuItemToolbar(listOf(back, forward, bookmark, share, refresh)) } // Predicates that need to be repeatedly called as the session changes diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt index 46c422bb9..5a8d88b13 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/ToolbarMenu.kt @@ -13,7 +13,7 @@ interface ToolbarMenu { data class RequestDesktop(val isChecked: Boolean) : Item() object FindInPage : Item() object Share : Item() - object Back : Item() + data class Back(val viewHistory: Boolean) : Item() data class Forward(val viewHistory: Boolean) : Item() data class Reload(val bypassCache: Boolean) : Item() object Stop : Item() diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt index 4c69f7877..fa3e8a94e 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt @@ -59,9 +59,10 @@ class CustomTabToolbarMenu( R.attr.disabled, context ), - disableInSecondaryState = true + disableInSecondaryState = true, + longClickListener = { onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = true)) } ) { - onItemTapped.invoke(ToolbarMenu.Item.Back) + onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = false)) } val forward = BrowserMenuItemToolbar.TwoStateButton( 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 c9df30ee2..a5b4b7de7 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 @@ -232,7 +232,10 @@ class DefaultSessionControlController( } override fun handleCollectionShareTabsClicked(collection: TabCollection) { - showShareFragment(collection.tabs.map { ShareData(url = it.url, title = it.title) }) + showShareFragment( + collection.title, + collection.tabs.map { ShareData(url = it.url, title = it.title) } + ) metrics.track(Event.CollectionShared) } @@ -366,8 +369,9 @@ class DefaultSessionControlController( showTabTrayCollectionCreation() } - private fun showShareFragment(data: List) { + private fun showShareFragment(shareSubject: String, data: List) { val directions = HomeFragmentDirections.actionGlobalShareFragment( + shareSubject = shareSubject, data = data.toTypedArray() ) navController.nav(R.id.homeFragment, directions) diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 469c5397d..ee9bc6fb6 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -29,6 +29,7 @@ import mozilla.components.support.ktx.android.content.hasCamera import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.Config import org.mozilla.fenix.HomeActivity +import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.application @@ -301,7 +302,7 @@ class SettingsFragment : PreferenceFragmentCompat() { private fun setupPreferences() { val leakKey = getPreferenceKey(R.string.pref_key_leakcanary) val debuggingKey = getPreferenceKey(R.string.pref_key_remote_debugging) - + val preferenceExternalDownloadManager = requirePreference(R.string.pref_key_make_default_browser) val preferenceLeakCanary = findPreference(leakKey) val preferenceRemoteDebugging = findPreference(debuggingKey) val preferenceMakeDefaultBrowser = requirePreference(R.string.pref_key_make_default_browser) @@ -314,6 +315,7 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + preferenceExternalDownloadManager.isVisible = FeatureFlags.externalDownloadManager preferenceRemoteDebugging?.setOnPreferenceChangeListener { preference, newValue -> preference.context.settings().preferences.edit() .putBoolean(preference.key, newValue).apply() diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareController.kt b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt index 0f768cd9e..2c1f44888 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareController.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt @@ -55,6 +55,7 @@ interface ShareController { * Default behavior of [ShareController]. Other implementations are possible. * * @param context [Context] used for various Android interactions. + * @param shareSubject desired message subject used when sharing through 3rd party apps, like email clients. * @param shareData the list of [ShareData]s that can be shared. * @param sendTabUseCases instance of [SendTabUseCases] which allows sending tabs to account devices. * @param snackbar - instance of [FenixSnackbar] for displaying styled snackbars @@ -64,6 +65,7 @@ interface ShareController { @Suppress("TooManyFunctions") class DefaultShareController( private val context: Context, + private val shareSubject: String?, private val shareData: List, private val sendTabUseCases: SendTabUseCases, private val snackbar: FenixSnackbar, @@ -90,7 +92,7 @@ class DefaultShareController( val intent = Intent(ACTION_SEND).apply { putExtra(EXTRA_TEXT, getShareText()) - putExtra(EXTRA_SUBJECT, shareData.map { it.title }.joinToString(", ")) + putExtra(EXTRA_SUBJECT, getShareSubject()) type = "text/plain" flags = FLAG_ACTIVITY_NEW_TASK setClassName(app.packageName, app.activityName) @@ -189,6 +191,9 @@ class DefaultShareController( } } + @VisibleForTesting + internal fun getShareSubject() = shareSubject ?: shareData.map { it.title }.joinToString(", ") + // Navigation between app fragments uses ShareTab as arguments. SendTabUseCases uses TabData. @VisibleForTesting internal fun List.toTabData() = map { data -> diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 005a8b8fe..cd190d564 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -67,6 +67,7 @@ class ShareFragment : AppCompatDialogFragment() { shareInteractor = ShareInteractor( DefaultShareController( context = requireContext(), + shareSubject = args.shareSubject, shareData = shareData, snackbar = FenixSnackbar.make( view = requireActivity().getRootView()!!, diff --git a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt index c7e2e3004..f74da7e4d 100644 --- a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt +++ b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryView.kt @@ -34,18 +34,25 @@ class TabHistoryView( private val adapter = TabHistoryAdapter(interactor) private val layoutManager = object : LinearLayoutManager(containerView.context) { + + private var shouldScrollToSelected = true + override fun onLayoutCompleted(state: RecyclerView.State?) { super.onLayoutCompleted(state) currentIndex?.let { index -> - // Force expansion of the dialog, otherwise scrolling to the current history item - // won't work when its position is near the bottom of the recyclerview. - expandDialog.invoke() - // Also, attempt to center the current history item. - val itemView = tabHistoryRecyclerView.findViewHolderForLayoutPosition( - findFirstCompletelyVisibleItemPosition() - )?.itemView - val offset = tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2 - scrollToPositionWithOffset(index, offset) + // Attempt to center the current history item after the first layout is completed, + // but not after subsequent layouts + if (shouldScrollToSelected) { + // Force expansion of the dialog, otherwise scrolling to the current history item + // won't work when its position is near the bottom of the recyclerview. + expandDialog.invoke() + val itemView = tabHistoryRecyclerView.findViewHolderForLayoutPosition( + findFirstCompletelyVisibleItemPosition() + )?.itemView + val offset = tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2 + scrollToPositionWithOffset(index, offset) + shouldScrollToSelected = false + } } } }.apply { diff --git a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryViewHolder.kt b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryViewHolder.kt index 6366dca52..0f001590b 100644 --- a/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/tabhistory/TabHistoryViewHolder.kt @@ -33,7 +33,9 @@ class TabHistoryViewHolder( history_layout.loadFavicon(item.url) if (item.isSelected) { - history_layout.setBackgroundColor(history_layout.context.getColorFromAttr(R.attr.tabHistoryItemSelectedBackground)) + history_layout.setBackgroundColor( + history_layout.context.getColorFromAttr(R.attr.tabHistoryItemSelectedBackground) + ) } else { history_layout.background = null } diff --git a/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt b/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt index 51c46e657..d0830bd73 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/FeatureFlagPreference.kt @@ -8,7 +8,11 @@ import mozilla.components.support.ktx.android.content.PreferencesHolder import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -fun featureFlagPreference(key: String, default: Boolean, featureFlag: Boolean): ReadWriteProperty = +fun featureFlagPreference( + key: String, + default: Boolean, + featureFlag: Boolean +): ReadWriteProperty = FeatureFlagPreferencePreference(key, default, featureFlag) private class FeatureFlagPreferencePreference( 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 8ab5be5ec..ba2390b3f 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -340,7 +340,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { * Caches the last known "is default browser" state when the app was paused. * For an up to do date state use `isDefaultBrowser` instead. */ - var wasDefaultBrowserOnLastPause by booleanPreference( + var wasDefaultBrowserOnLastResume by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_default_browser), default = isDefaultBrowser() ) diff --git a/app/src/main/res/layout/library_site_item.xml b/app/src/main/res/layout/library_site_item.xml index 2197e740d..4d8ea73fd 100644 --- a/app/src/main/res/layout/library_site_item.xml +++ b/app/src/main/res/layout/library_site_item.xml @@ -53,7 +53,8 @@ app:layout_constraintStart_toEndOf="@id/icon" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/url" - app:layout_constraintVertical_chainStyle="packed"/> + app:layout_constraintVertical_chainStyle="packed" + app:layout_goneMarginEnd="@dimen/library_item_icon_margin_horizontal" /> + app:layout_constraintBottom_toBottomOf="parent" + app:layout_goneMarginEnd="@dimen/library_item_icon_margin_horizontal" /> + - Privado %s + %s privado %s (Privado) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 929206f24..dfda518d5 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -27,6 +27,9 @@ %1$s pestañas abiertas. Tocar para cambiar de pestaña. + + %1$s seleccionado + %1$s es producido por Mozilla. diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 6eb679fae..2637b586e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -40,6 +40,8 @@ Tallenna valitut välilehdet kokoelmaan Valittu %1$s + + Kumottu valinta %1$s Poistuttiin monivalintatilasta diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index a001a6270..c5c88f206 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -37,9 +37,18 @@ मल्टीसेलेक्ट मोड से बाहर निकलें चुने गए टैब को संग्रह में सहेजें + + %1$s चयनित + + %1$s अचयनित मल्टीसेलेक्ट मोड से बाहर निकल चुके + + मल्टीसेलेक्ट मोड में दाखिल, संग्रह में सहेजने के लिए टैबों को चुनें + + चयनित + %1$s को Mozilla द्वारा निर्मित किया गया है। @@ -165,8 +174,8 @@ स्कैन करें - - खोज इंजन + + खोज इंजन खोज इंजन सेटिंग्स @@ -597,6 +606,8 @@ फ़ोल्डर चुनें क्या आप वाकई इस फ़ोल्डर को हटाना चाहते हैं? + + %s चयनित वस्तुओं को मिटा देगा। %1$s मिटाया गया @@ -655,6 +666,8 @@ बुकमार्क मिटा दिए गए + + चयनित फोल्डर मिटाए जा रहे हैं पूर्ववत करें @@ -860,6 +873,8 @@ क्या आप वाकई %1$s को हटाना चाहते हैं? इस टैब को हटाने से संपूर्ण संग्रह मिट जाएगा। आप किसी भी समय नए संग्रह बना सकते हैं। + + %1$s को मिटाएं? मिटाएं @@ -1269,6 +1284,8 @@ लॉगिन और पासवर्ड जो सहेजे नहीं गए हैं उन्हें यहां दिखाये जायेंगे। इन साइटों के लिए लॉगिन और पासवर्ड सहेजे नहीं जाएंगे। + + सभी अपवादों को मिटाएं लॉगिन खोजें @@ -1472,9 +1489,7 @@ एक लॉगिन इस उपयोगकर्ता नाम के साथ मौजूद है - - Firefox खाते से कनेक्ट करें। - + अन्य डिवाइस कनेक्ट करें कृपया पुनः प्रमाणित करें। @@ -1495,13 +1510,4 @@ ठीक है, समझ गए - - - शॉर्टकट - - के साथ खोजें - - इस बार, इसके साथ खोजें: - - खोज शॉर्टकट्स दिखाएं diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 8b120b9a3..62beca7de 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -734,7 +734,7 @@ Gyűjtemény menü - Gyűjtsd össze a számára fontos dolgokat + Gyűjtse össze az Önnek fontos dolgokat Csoportosítsa a hasonló kereséseket, webhelyeket és lapokat a későbbi gyors elérés érdekében. diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index f6df130c3..45bb40030 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -27,6 +27,29 @@ %1$s tab terbuka. Ketuk untuk beralih tab. + + %1$d terpilih + + Tambah koleksi baru + + Nama + + Pilih koleksi + + Keluar mode seleksi ganda + + Simpan tab terpilih ke koleksi + + %1$s dipilih + + %1$s tidak dipilih + + Keluar dari mode seleksi ganda + + Memasuki mode seleksi ganda, pilih tab untuk menyimpannya ke koleksi + + Terpilih + %1$s diproduksi oleh Mozilla. @@ -152,15 +175,13 @@ Pindai - - Pintasan + + Mesin pencari Setelan mesin pencari - - Cari dengan - Kali ini, cari lewat: + Saat ini, cari dengan: Isi tautan dari papan klip @@ -270,8 +291,8 @@ Perangkat pengembang Pengawakutuan jarak jauh melalui USB - - Tampilkan pintasan pencarian + + Tampilkan mesin pencari Tampilkan saran pencarian @@ -525,6 +546,9 @@ %1$s (Mode Privat) + + Simpan + Hapus riwayat @@ -592,6 +616,8 @@ Pilih folder Yakin akan menghapus folder ini? + + %s akan menghapus item terpilih. %1$s terhapus @@ -646,8 +672,10 @@ %1$s terhapus - + Markah dihapus + + Menghapus folder terpilih URUNGKAN @@ -743,6 +771,8 @@ %d tab dipilih Tab disimpan! + + Koleksi disimpan! Tab disimpan! @@ -849,6 +879,10 @@ TOLAK Yakin ingin menghapus %1$s? + + Menghapus tab ini akan menghapus keseluruhan koleksi. Kamu dapat membuat koleksi baru kapan saja. + + Hapus %1$s? Hapus @@ -1249,6 +1283,8 @@ Info masuk dan kata sandi yang tidak disimpan akan ditampilkan di sini. Info masuk dan kata sandi tidak akan disimpan untuk situs-situs ini. + + Hapus semua pengecualian Cari log masuk @@ -1287,6 +1323,8 @@ Salin nama pengguna Salin situs + + Buka situs di peramban Tampilkan sandi @@ -1437,9 +1475,7 @@ Sebuah info masuk dengan nama pengguna tersebut sudah ada - - Hubungkan dengan Firefox Account. - + Hubungkan perangkat lain Harap autentikasi ulang. diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index b8a165e61..b701f979f 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -1,9 +1,9 @@ - - သီးသန့် Firefox အကြိုမြင်ကွင်း - - Firefox Preview (သီးသန့်) + + သီးသန့် %s + + %s (သီးသန့်) ရွေးချယ်စရာများ @@ -14,23 +14,40 @@ သီးသန့်ရှာဖွေမှုကို ပိတ်ပါ လိပ်စာရှာဖွေ သို့ ရိုက်ထည့်ပါ - - ဖွင့်ထားသည့်တပ်ဗ်များ မရှိပါ သင့်ဖွင့်ထားသည့်တက်ဗ်များကို ဤနေရာတွင် ပြမည်။ + + သင်၏ သီးသန့် တက်ဗ်များ ဤနေရာမှာ ပြရန်။ + + ဖွင့်ထားသော တက်ဗ် 1 ခု။ တက်ဗ်များ ပြောင်းရန် ထိပါ။ + + ဖွင့်ထားသော တက်ဗ် %1$s ခု။ တက်ဗ်များ ပြောင်းရန် ထိပါ။ + + %1$d ခု ရွေးချယ်ထားပြီး + + စုဆောင်းမှု အသစ် သို့ ထည့်ရန် + + အမည် + + စုဆောင်းမှု ကို ရွေးချယ်ရန် + + + multiselect mode ကိုပိတ်ပါ + + စုဆောင်းမှု သို့ တက်ဗ်များ သိမ်းရန် + + + %1$s ကို Mozilla မှ ထုတ်လုပ်သည်။ + သင် ကိုယ်ပိုင်အပိုင်းထဲတွင် ရှိနေသည်။ - - % 1 $ s သည်သင်အက်ပ်မှထွက်သောအခါသို့မဟုတ်သီးသန့် tabs အားလုံးပိတ်သောအခါသင်၏ရှာဖွေခြင်းနှင့်ရှာဖွေခြင်းရာဇဝင်ကိုရှင်းလင်းသည်။ ၎င်းသည်သင့်အားဝက်ဘ်ဆိုက်များသို့မဟုတ်သင်၏အင်တာနက် ၀ န်ဆောင်မှုပေးသူများအတွက်အမည်မသိစေသော်လည်း၎င်းကိုပြုလုပ်သည် -        သင်အွန်လိုင်းလုပ်တာကိုဒီကိရိယာကိုအသုံးပြုတဲ့သူတိုင်းထံမှလျှို့ဝှက်ထားရန်ပိုလွယ်ကူသည်။ ပုဂ္ဂလိက browsing ဆိုင်ရာ အမြင်မှားများ အပိုင်း ကိုဖျက်ပါ - + သင့်မူလမြင်ကွင်းမှ သီးသန့်တဗ်များကိုဖွင့်ရန် ဖြတ်လမ်းလုပ်ပါ @@ -38,6 +55,9 @@ နေပါစေ + + ယခု မဟုတ် + တပ်ဗ် အသစ် @@ -45,6 +65,9 @@ တစ်ကိုယ်ရေသုံး တပ်ဗ်အသစ် + + ထိပ်တန်း ဆိုက်များ + တပ်ဗ်များကို ဖွင့်ပါ @@ -87,8 +110,6 @@ တပ်ဗ် အသစ် စုဆောင်းမှုသို့သိမ်းဆည်းပါ - - ဆိုဘ်ပြဿနာကိုတင်ပြပါ မျှဝေ @@ -102,7 +123,7 @@ %1$s က ထောက်ပံ့ပေးထားတယ် - + စာဖတ်သူမြင်ကွင်း အက်ပ်ထဲတွင်ဖွင့်ပါ @@ -123,14 +144,8 @@ စစ်ဆေးပါ - - လမ်းတိုများ အင်ဂျင်အပြင်အဆင် ရှာဖွေပါ - - ရှာပါ - - ဤတစ်ကြိမ်တွင်ရှာဖွေပါ - ကလစ်ဘုတ်မှ လင့်ခ်ကိုဖြည့်စွက်ပါ @@ -150,6 +165,9 @@ ဝဘ်တွင် ရှာဖွေပါ + + အသံဖြင့် ရှာရန် + အပြင်အဆင်များ @@ -227,10 +245,12 @@ USB မှတဆင့် Remote debugging - - ရှာဖွေမှုဖြတ်လမ်းများကိုပြပါ + + ရှာဖွေရေး အင်ဂျင်များပြရန် ရှာဖွေရေး အကြံပြုချက်များကို ဖေါ်ပြပါ + + အသံရှာ ဖွေမှု ပြရန် ကိုယ်ပိုင်သီးသန့်အပိုင်းများတွင်ပြပါ @@ -257,6 +277,8 @@ စာမှတ်များ ဝင်ရောက်မှုများ + + ပွင့်နေသော တက်ဗ်များ ထွက်ရန် @@ -278,7 +300,7 @@ - %s %s အပေါ် %s + %1$s သည် %2$s %3$s တွင် @@ -348,7 +370,7 @@ - firefox.com/pair သို့လည်ပတ်ပါ။]]> + firefox.com/pair တွင်ပြနေသော QR ကုဒ်ကို ဖတ်ပါ]]> ကင်မရာဖွင့်ပါ @@ -393,8 +415,6 @@ စာဖတ်စာရင်း ရှာပါ - - စာကြည့်တိုက် အပြင်အဆင်များ @@ -412,6 +432,24 @@ သီးသန့် တဗ် များ တက်ဗ် ထည့်ပါ + + သီးသန့် တက်ဗ် ထည့် + + သီးသန့် + + ပွင့်နေသည့် တက်ဗ်များ + + စုစည်းမှု ထဲသို့ သိမ်းရန် + + တက်ဗ်များ အားလုံး မျှဝေရန် + + တက်ဗ်များ အားလုံး ပိတ်ရန် + + တက်ဗ် အသစ် + + မူလ သို့ သွားရန် + + စုစည်းမှု ထဲမှ တက်ဗ် ကို ဖယ်ရှားရန် တပ်ဗ်ကို ပိတ်ရန် @@ -423,7 +461,7 @@ တပ်ဗ်များကို မျှဝေပါ - စုဆောင်းမှုသို့သိမ်းဆည်းပါ + စုဆောင်းမှု သို့ တက်ဗ်များ သိမ်းရန် တဗ်မန်နူး @@ -447,13 +485,24 @@ ဖယ်ရှားပါ + + သိမ်းရန် + မှတ်တမ်းကို ဖျက်ပါ သင့် မှတ်တမ်းကို ဖျက်ပစ်မှာ သေချာပြီလား? + + မှတ်တမ်း ကို ဖျက်ပြီး + + %1$s ခု ဖျက်ပြီး ရှင်းလင်းပါ + + ကူးရန် + + မျှဝေရန် ဖျက်ပါ %1$s ဖျက်ပြီး - - ရွေးချယ်ထားသည့်အမှတ်အသားများကိုဖျက်ပစ်သည် မလုပ်တော့ပါ @@ -618,16 +665,14 @@ ပိတ်ပါ - - သင့်အတွက်အရေးကြီးတဲ့အရာတွေကိုစုဆောင်းပါ။ စတင်ရန်စုဆောင်းမှုအသစ်တစ်ခုရရှိရန်ဖွင့်ထားသောတဗ်များကိုသိမ်းဆည်းပါ။ စုဆည်းမှုများ စုဆောင်းခြင်းမီနူး - စုစည်းမှု မရှိပါ - - သင်၏ စုစည်းမှုများကိုဤနေရာတွင်ပြလိမ့်မည်။ + သင် အတွက် အရေးပါသည်များ ကို စုစည်းပါ + + ရှာဖွေခြင်းများ၊ ဆိုက်များ နှင့် တက်ဗ်များ ကို အမျိုးအစားတူစုခြင်းဖြင့် နောင်တွင် မြန်မြန် ရယူနိုင်လိမ့်မည်။ တက်ပ်များကိုရွေးပါ @@ -651,6 +696,8 @@ % d tabs ကိုရွေးချယ်ထားပါသည် တဗ်များကိုသိမ်းထားပြီး + + စုစည်းမှု သိမ်းပြီး။ တဗ်ကိုသိမ်းထားပြီး @@ -658,6 +705,9 @@ သိမ်းပါ + + မြင်ကွင်း + စုဆည်းမှု %d @@ -752,6 +802,10 @@ Deny %1$s ကိုသင်ဖျက်လိုသလား။ + + ဤ တက်ဗ် ကို ဖျက်ခြင်း ကြောင့် ဤ စုစည်းမှုတစ်ခုလုံး ပျက်သွားလိမ့်မည်။ သင် သည် စုစည်းမှု အသစ် ကိုအချိန်မရွေး ပြုလုပ်နိုင်ပါသည်။ + + %1$s ကိုဖျက်မှာလား? ဖျက်ပါ @@ -768,16 +822,11 @@ စာလုံးအရွယ်အစား - - အလိုအလျောက်စာလုံးအရွယ်အစား - စာလုံးအရွယ်အစားသည်သင်၏ဖုန်းနှင့်ကိုက်ညီပါလိမ့်မည်။ဤနေရာတွင်ဖောင့်အရွယ်အစားကိုစီမံခန့်ခွဲရန်ကိုပိတ်ပါ။ ကြည့်ရှုမှုအချက်အလက်များ ဖျက်ပါ - - တပ်ဗ်များကို ဖွင့်ပါ %d တဗ်များ @@ -809,8 +858,6 @@ ပင်မမန်နူးမှ \"Quit\" ကိုသင်ရွေးလျှင် ရှာဖွေအချက်အလက်များကိုအလိုအလျောက်ဖျက်ပါမည်။ ပင်မမန်နူးမှ \"Quit\" ကိုသင်ရွေးလျှင် ရှာဖွေအချက်အလက်များကိုအလိုအလျောက်ဖျက်ပါမည်။ - - ရှာဖွေကြည့်ရှုမှု မှတ်တမ်း ထွက်ရန် @@ -862,20 +909,9 @@ ထပ်တူပြုခြင်းဖွင့်ထားသည် ဝင်ရောက်ရန်မအောင်မြင်ပါ - - သင့်ကိုယ်သင်ကာကွယ်ပါ - - သင့်ကိုအွန်လိုင်းပေါ်တွင် ခြေရာခံခြင်းမှ %s မှ ဆိုက်များကိုရပ်ဆိုင်းပြီးကူညီလိမ့်မည်။ - - စံ - - ခြေရာခံသူများကိုပိတ်သော်လည်း စာမျက်နှာများကိုပုံမှန်ဆွဲတင်ခွင့်ပြုပါ။ တင်းကြပ်စွာ (အကြံပြုသည်) - - ပိုမိုကောင်းမွန်သောကာကွယ်မှုနှင့်စွမ်းဆောင်ရည်အတွက်ခြေရာခံသူများကိုပိုမိုပိတ်ဆို့ထားသောကြောင့်အချို့သောဆိုဒ်များကိုအလုပ်မလုပ်နိုင်ပါ @@ -959,33 +995,15 @@ သင့်ရဲ့အချက်အလက်များကိုသင်ကိုယ်တိုင်သိမ်းထားပါ။ %s သည်အွန်လိုင်းတွင်လုပ်ဆောင်သောအသုံးပြုမှုများကို ခြေရာခံမှုများမှသင့်အားကာကွယ်ပေးသည်။ ပိုမိုလေ့လာရန် - - စံ - - စံ (အကြံပြုချက်) - - လုံခြုံရေးနှင့် စွမ်းဆောင်ရည်ကို ဟန်ချက်ညီစေရန် ပြုလုပ်ထားသည်။ - - စာမျက်နှာများသည်ပုံမှန်အားဖြင့်ဆွဲတင်လိမ့်မည်၊ သို့သော် ခြေရာခံတွေကိုပိတ်လိမ့်မည်။ စံချိန်မြင့်ခြေရာခံကာကွယ်ခြင်းက ဘာတွေကိုပိတ်ဆို့မလဲ တင်းကျပ်ပါ - - တင်းကျပ်ရန် (ပုံမှန်) - - ပိုမိုအားကောင်းသည့်ခြေရာခံကာကွယ်ခြင်းနှင့်ပိုမိုမြန်ဆန်သောစွမ်းဆောင်နိုင်မှုများရှိသော်လည်းအချို့သောဆိုဒ်များမှာအလုပ်မလုပ်နိုင်ပါ။ - - တင်းကြပ်စွာ (အကြံပြုသည်) - - ပိုမိုလုံခြုံသောကာကွယ်မှုဖြစ်သော်လည်းအချို့သောဆိုဒ်များသို့မဟုတ်ပါဝင်သည့်အရာများအားပျက်စီးစေနိုင်သည်။ ကန့်သတ်ခြေရာခံကာကွယ်ခြင်းက ဘာတွေကိုပိတ်ဆို့မလဲ စိတ်ကြိုက် - - ပိတ်ဆို့ရန် ခြေရာခံသူများနှင့် scriptsများကို ရွေးချယ်ပါ။ စိတ်ကြိုက်ခြေရာခံကာကွယ်ခြင်းက ဘာတွေကိုပိတ်ဆို့မလဲ @@ -1035,8 +1053,6 @@ နောက်ယောင်ခံသည့် အရာများ ခြေရာခံခြင်းကုဒ်ပါရှိခြင်းကြောင့်အပြင်ဘက်ကြော်ငြာများ၊ဗွီဒီယိုများနှင့်အခြားအကြောင်းအရာများကိုတားမြစ်သည်။ အချို့သော ဆိုက်၏လုပ်ဆောင်နိုင်စွမ်းကိုအကျိုးသက်ရောက်နိုင်သည်။ - - စိတ်မချရ၍ %s သည် ခြေရာခံသူများကိုဤဆိုက်ပေါ်တွင်ပိတ်ဆို့ထားသည်။ ဘာတွေကိုပိတ်ဆို့ထားလဲနှိပ်၍ကြည့်ပါ။ ဤဆိုက်အတွက် ကာကွယ်မှုဖွင့်ထားသည်။ @@ -1284,4 +1300,5 @@ ဤဝင်ရောက်မှုကိုဖျက်မှာသေချာပါသလား။ ဖျက်ပါ - + + diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index 4f0f63ee9..539783b21 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -33,12 +33,16 @@ Nom Seleccionar una colleccion + + Sortir del mòde seleccion multipla Enregistrar los onglets seleccionats dins la colleccion %1$s seleccionat %1$s deseleccionat + + Sortida del mòde seleccion multipla Seleccionat @@ -912,6 +916,8 @@ Aquò suprimirà totas las donadas de navegacion. + + %s suprimirà las donadas de navegacion seleccionadas. Anullar @@ -1123,6 +1129,10 @@ Qu’es nòu dins %s + + %s | Bibliotècas liuras + Assisténcia @@ -1192,6 +1202,10 @@ Per ne saber mai sus Sync. Excepcions + + Los identificants e senhals pas salvats seràn mostrats aquí. + + Los identificants e senhals seràn pas salvats per aquestes sites. Suprimir totas las excepcions @@ -1245,6 +1259,8 @@ O configurar ara Desverrolhatz lo periferic + + Zoom per totes los sites Nom (A-Z) @@ -1274,6 +1290,8 @@ Ne saber mai + + Detalhs del motor de recèrca personalizat Ligam per ne saber mai @@ -1360,6 +1378,9 @@ Parlatz ara + + Un identificant amb aqueste nom d’utilizaire existís ja + Connectatz un autre periferic. diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index bf1cd432d..32462293b 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -25,6 +25,8 @@ Odprtih zavihkov: %1$s. Tapnite za preklop zavihkov. + + %1$d izbranih Dodaj novo zbirko diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 700697231..317651afd 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -149,6 +149,7 @@ pref_key_open_links_in_a_private_tab pref_key_open_links_in_external_app + pref_key_external_download_manager pref_key_allow_screenshots_in_private_mode diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0047a3592..3040ca5cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -296,6 +296,8 @@ Account settings Open links in apps + + External download manager Add-ons diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 8e6062573..04de02720 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -132,6 +132,12 @@ android:key="@string/pref_key_open_links_in_external_app" android:title="@string/preferences_open_links_in_apps" /> + + { every { tabs } returns emptyList() + every { title } returns "" } controller.handleCollectionShareTabsClicked(collection) diff --git a/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt b/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt index bdea82de0..ace841db6 100644 --- a/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/share/ShareControllerTest.kt @@ -48,6 +48,7 @@ class ShareControllerTest { // Need a valid context to retrieve Strings for example, but we also need it to return our "metrics" private val context: Context = spyk(testContext) private val metrics: MetricController = mockk(relaxed = true) + private val shareSubject = "shareSubject" private val shareData = listOf( ShareData(url = "url0", title = "title0"), ShareData(url = "url1", title = "title1") @@ -65,7 +66,7 @@ class ShareControllerTest { private val dismiss = mockk<(ShareController.Result) -> Unit>(relaxed = true) private val recentAppStorage = mockk(relaxed = true) private val controller = DefaultShareController( - context, shareData, sendTabUseCases, snackbar, navController, + context, shareSubject, shareData, sendTabUseCases, snackbar, navController, recentAppStorage, testCoroutineScope, dismiss ) @@ -91,8 +92,8 @@ class ShareControllerTest { // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we // need to use an Activity Context. val activityContext: Context = mockk() - val testController = DefaultShareController(activityContext, shareData, mockk(), mockk(), mockk(), - recentAppStorage, testCoroutineScope, dismiss) + val testController = DefaultShareController(activityContext, shareSubject, shareData, mockk(), + mockk(), mockk(), recentAppStorage, testCoroutineScope, dismiss) every { activityContext.startActivity(capture(shareIntent)) } just Runs every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs @@ -101,6 +102,7 @@ class ShareControllerTest { // Check that the Intent used for querying apps has the expected structure assertTrue(shareIntent.isCaptured) assertEquals(Intent.ACTION_SEND, shareIntent.captured.action) + assertEquals(shareSubject, shareIntent.captured.extras!![Intent.EXTRA_SUBJECT]) assertEquals(textToShare, shareIntent.captured.extras!![Intent.EXTRA_TEXT]) assertEquals("text/plain", shareIntent.captured.type) assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, shareIntent.captured.flags) @@ -124,8 +126,8 @@ class ShareControllerTest { // needed for capturing the actual Intent used the `slot` one doesn't have this flag so we // need to use an Activity Context. val activityContext: Context = mockk() - val testController = DefaultShareController(activityContext, shareData, mockk(), snackbar, - mockk(), mockk(), testCoroutineScope, dismiss) + val testController = DefaultShareController(activityContext, shareSubject, shareData, mockk(), + snackbar, mockk(), mockk(), testCoroutineScope, dismiss) every { activityContext.startActivity(capture(shareIntent)) } throws SecurityException() every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app" @@ -247,6 +249,7 @@ class ShareControllerTest { fun `getSuccessMessage should return different strings depending on the number of shared tabs`() { val controllerWithOneSharedTab = DefaultShareController( context, + shareSubject, listOf(ShareData(url = "url0", title = "title0")), mockk(), mockk(), @@ -280,7 +283,7 @@ class ShareControllerTest { ShareData(url = "url1") ) val controller = DefaultShareController( - context, shareData, sendTabUseCases, snackbar, navController, + context, shareSubject, shareData, sendTabUseCases, snackbar, navController, recentAppStorage, testCoroutineScope, dismiss ) @@ -288,6 +291,21 @@ class ShareControllerTest { assertEquals(expectedShareText, controller.getShareText()) } + @Test + fun `getShareSubject will return "shareSubject" if that is non null`() { + assertEquals(shareSubject, controller.getShareSubject()) + } + + @Test + fun `getShareSubject will return a concatenation of tab titles if "shareSubject" is null`() { + val controller = DefaultShareController( + context, null, shareData, sendTabUseCases, snackbar, navController, + recentAppStorage, testCoroutineScope, dismiss + ) + + assertEquals("title0, title1", controller.getShareSubject()) + } + @Test fun `ShareTab#toTabData maps a list of ShareTab to a TabData list`() { var tabData: List diff --git a/config/detekt.yml b/config/detekt.yml index 56b6041c2..2568a929e 100644 --- a/config/detekt.yml +++ b/config/detekt.yml @@ -76,7 +76,7 @@ complexity: # https://github.com/mozilla-mobile/fenix/issues/4861 threshold: 75 LongParameterList: - active: trued + active: true excludes: "**/*Controller.kt, **/*Integration.kt" functionThreshold: 6 constructorThreshold: 7