diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt new file mode 100644 index 000000000..c0a87fe13 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt @@ -0,0 +1,59 @@ +/* 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.ui + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.uiautomator.UiDevice +import okhttp3.mockwebserver.MockWebServer +import org.junit.Rule +import org.junit.Before +import org.junit.After +import org.junit.Test +import org.mozilla.fenix.helpers.AndroidAssetDispatcher +import org.mozilla.fenix.helpers.HomeActivityIntentTestRule +import org.mozilla.fenix.ui.robots.homeScreen + +/** + * Tests for verifying the advanced section in Settings + * + */ + +class SettingsAdvancedTest { + /* ktlint-disable no-blank-line-before-rbrace */ // This imposes unreadable grouping. + + private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) + private lateinit var mockWebServer: MockWebServer + + @get:Rule + val activityIntentTestRule = HomeActivityIntentTestRule() + + @Before + fun setUp() { + mockWebServer = MockWebServer().apply { + setDispatcher(AndroidAssetDispatcher()) + start() + } + } + + @After + fun tearDown() { + mockWebServer.shutdown() + } + + @Test + // Walks through settings menu and sub-menus to ensure all items are present + fun settingsAboutItemsTest() { + // ADVANCED + homeScreen { + }.openThreeDotMenu { + }.openSettings { + // ADVANCED + verifyAdvancedHeading() + verifyAddons() + verifyRemoteDebug() + verifyLeakCanaryButton() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt index f60e50915..f42902c99 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsDeveloperToolsTest.kt @@ -49,7 +49,6 @@ class SettingsDeveloperToolsTest { homeScreen { }.openThreeDotMenu { }.openSettings { - verifyDeveloperToolsHeading() verifyRemoteDebug() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt index c5cf4a061..cb017834e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsPrivacyTest.kt @@ -111,7 +111,6 @@ class SettingsPrivacyTest { verifyDeleteBrowsingDataButton() verifyDeleteBrowsingDataOnQuitButton() verifyDataCollectionButton() - verifyLeakCanaryButton() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index 2c1718708..7db88955a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -64,9 +64,9 @@ class SettingsRobot { fun verifyLeakCanaryButton() = assertLeakCanaryButton() fun verifySettingsView() = assertSettingsView() - // DEVELOPER TOOLS SECTION - fun verifyDeveloperToolsHeading() = assertDeveloperToolsHeading() - + // ADVANCED SECTION + fun verifyAdvancedHeading() = assertAdvancedHeading() + fun verifyAddons() = assertAddons() fun verifyRemoteDebug() = assertRemoteDebug() // ABOUT SECTION @@ -174,7 +174,7 @@ private fun assertSettingsView() { // verify that we are in the correct library view assertGeneralHeading() assertPrivacyHeading() - assertDeveloperToolsHeading() + assertAdvancedHeading() assertAboutHeading() } @@ -255,13 +255,22 @@ private fun assertDeleteBrowsingDataOnQuitButton() { private fun assertDataCollectionButton() = onView(withText("Data collection")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -private fun assertLeakCanaryButton() = onView(withText("LeakCanary")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +private fun assertLeakCanaryButton() { + scrollToElementByText("LeakCanary") + onView(withText("LeakCanary")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} -// DEVELOPER TOOLS SECTION -private fun assertDeveloperToolsHeading() { - scrollToElementByText("Developer tools") - onView(withText("Developer tools")) +// ADVANCED SECTION +private fun assertAdvancedHeading() { + scrollToElementByText("Advanced") + onView(withText("Advanced")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) +} + +private fun assertAddons() { + scrollToElementByText("Add-ons") + onView(withText("Add-ons")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) } 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 099923f41..d405d2434 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -86,6 +86,7 @@ import org.mozilla.fenix.ext.sessionsOfType import org.mozilla.fenix.ext.settings import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.theme.ThemeManager +import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration import java.lang.ref.WeakReference /** @@ -119,6 +120,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session private val fullScreenFeature = ViewBoundFeatureWrapper() private val swipeRefreshFeature = ViewBoundFeatureWrapper() private val webchannelIntegration = ViewBoundFeatureWrapper() + private val sitePermissionWifiIntegration = ViewBoundFeatureWrapper() var customTabSessionId: String? = null @@ -392,6 +394,15 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session view = view ) + sitePermissionWifiIntegration.set( + feature = SitePermissionsWifiIntegration( + settings = context.settings(), + wifiConnectionMonitor = context.components.wifiConnectionMonitor + ), + owner = this, + view = view + ) + context.settings().setSitePermissionSettingListener(viewLifecycleOwner) { // If the user connects to WIFI while on the BrowserFragment, this will update the // SitePermissionsRules (specifically autoplay) accordingly @@ -536,6 +547,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session override fun onStart() { super.onStart() requireComponents.core.sessionManager.register(this, this, autoPause = true) + sitePermissionWifiIntegration.get()?.maybeAddWifiConnectedListener() } @CallSuper diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 9b377861d..17f5db6a0 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -19,11 +19,9 @@ import mozilla.components.lib.publicsuffixlist.PublicSuffixList import mozilla.components.support.migration.state.MigrationStore import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.HomeActivity -import org.mozilla.fenix.ext.settings import org.mozilla.fenix.test.Mockable import org.mozilla.fenix.utils.ClipboardHandler import org.mozilla.fenix.wifi.WifiConnectionMonitor -import org.mozilla.fenix.wifi.WifiIntegration import java.util.concurrent.TimeUnit private const val DAY_IN_MINUTES = 24 * 60L @@ -110,12 +108,5 @@ class Components(private val context: Context) { val migrationStore by lazy { MigrationStore() } val performance by lazy { PerformanceComponent() } val push by lazy { Push(context, analytics.crashReporter) } - val wifiIntegration by lazy { - WifiIntegration( - settings = context.settings(), - wifiConnectionMonitor = WifiConnectionMonitor( - context as Application - ) - ) - } + val wifiConnectionMonitor by lazy { WifiConnectionMonitor(context as Application) } } diff --git a/app/src/main/java/org/mozilla/fenix/components/FxaServer.kt b/app/src/main/java/org/mozilla/fenix/components/FxaServer.kt index 78d76342b..5967bac44 100644 --- a/app/src/main/java/org/mozilla/fenix/components/FxaServer.kt +++ b/app/src/main/java/org/mozilla/fenix/components/FxaServer.kt @@ -7,6 +7,7 @@ import android.content.Context import mozilla.components.service.fxa.ServerConfig import mozilla.components.service.fxa.ServerConfig.Server import org.mozilla.fenix.FeatureFlags +import org.mozilla.fenix.ext.settings /** * Utility to configure Firefox Account servers. @@ -24,6 +25,11 @@ object FxaServer { } fun config(context: Context): ServerConfig { - return ServerConfig(Server.RELEASE, CLIENT_ID, redirectUrl(context)) + val serverOverride = context.settings().overrideFxAServer + val tokenServerOverride = context.settings().overrideSyncTokenServer.ifEmpty { null } + if (serverOverride.isEmpty()) { + return ServerConfig(Server.RELEASE, CLIENT_ID, redirectUrl(context), tokenServerOverride) + } + return ServerConfig(serverOverride, CLIENT_ID, redirectUrl(context), tokenServerOverride) } } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt index 2dd904b94..9ee67d35d 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlAdapter.kt @@ -22,12 +22,12 @@ import org.mozilla.fenix.home.OnboardingState import org.mozilla.fenix.home.Tab import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder +import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.NoContentMessageViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.NoContentMessageWithActionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.PrivateBrowsingDescriptionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.SaveTabGroupViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TabHeaderViewHolder -import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TabViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.TopSiteViewHolder import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingAutomaticSignInViewHolder @@ -172,7 +172,7 @@ class SessionControlAdapter( NoContentMessageWithActionViewHolder.LAYOUT_ID -> NoContentMessageWithActionViewHolder(view) CollectionHeaderViewHolder.LAYOUT_ID -> CollectionHeaderViewHolder(view) CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, interactor) - TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, interactor) + TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, interactor, differentLastItem = true) OnboardingHeaderViewHolder.LAYOUT_ID -> OnboardingHeaderViewHolder(view) OnboardingSectionHeaderViewHolder.LAYOUT_ID -> OnboardingSectionHeaderViewHolder(view) OnboardingAutomaticSignInViewHolder.LAYOUT_ID -> OnboardingAutomaticSignInViewHolder(view) diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SwipeToDeleteCallback.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SwipeToDeleteCallback.kt index 1b33e4ebe..014b18801 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SwipeToDeleteCallback.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SwipeToDeleteCallback.kt @@ -50,7 +50,7 @@ class SwipeToDeleteCallback( icon?.setTint(recyclerView.context.getColorFromAttr(R.attr.destructive)) val backgroundDrawable = when { - viewHolder is TabInCollectionViewHolder && viewHolder.isLastTab -> { + viewHolder is TabInCollectionViewHolder && viewHolder.isLastItem -> { R.drawable.tab_in_collection_last_swipe_background } viewHolder is TabInCollectionViewHolder -> { diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CollectionViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CollectionViewHolder.kt index e5afaeddb..055af0c66 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CollectionViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/CollectionViewHolder.kt @@ -17,7 +17,6 @@ import mozilla.components.browser.menu.BrowserMenuBuilder import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.feature.tab.collections.TabCollection import org.mozilla.fenix.R -import org.mozilla.fenix.components.description import org.mozilla.fenix.ext.getIconColor import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor @@ -77,17 +76,18 @@ class CollectionViewHolder( private fun updateCollectionUI() { view.collection_title.text = collection.title - view.collection_description.text = collection.description(view.context) val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams view.isActivated = expanded if (expanded) { layoutParams.bottomMargin = 0 collection_title.setPadding(0, 0, 0, EXPANDED_PADDING) - view.collection_description.visibility = View.GONE + view.collection_share_button.visibility = View.VISIBLE + view.collection_overflow_button.visibility = View.VISIBLE } else { layoutParams.bottomMargin = COLLAPSED_MARGIN - view.collection_description.visibility = View.VISIBLE + view.collection_share_button.visibility = View.GONE + view.collection_overflow_button.visibility = View.GONE } view.collection_icon.colorFilter = createBlendModeColorFilterCompat( diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt index 0fd2808be..feca7b61f 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/TabInCollectionViewHolder.kt @@ -10,7 +10,10 @@ import android.view.ViewOutlineProvider import androidx.appcompat.content.res.AppCompatResources import androidx.recyclerview.widget.RecyclerView import kotlinx.android.extensions.LayoutContainer -import kotlinx.android.synthetic.main.tab_in_collection.* +import kotlinx.android.synthetic.main.list_element.list_element_title +import kotlinx.android.synthetic.main.list_element.list_item_action_button +import kotlinx.android.synthetic.main.list_element.list_item_favicon +import kotlinx.android.synthetic.main.list_element.list_item_url import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.support.ktx.android.content.getColorFromAttr import mozilla.components.support.ktx.android.util.dpToFloat @@ -25,6 +28,7 @@ import mozilla.components.feature.tab.collections.Tab as ComponentTab class TabInCollectionViewHolder( val view: View, val interactor: CollectionInteractor, + private val differentLastItem: Boolean = false, override val containerView: View? = view ) : RecyclerView.ViewHolder(view), LayoutContainer { @@ -32,11 +36,11 @@ class TabInCollectionViewHolder( private set lateinit var tab: ComponentTab private set - var isLastTab = false + var isLastItem = false init { - collection_tab_icon.clipToOutline = true - collection_tab_icon.outlineProvider = object : ViewOutlineProvider() { + list_item_favicon.clipToOutline = true + list_item_favicon.outlineProvider = object : ViewOutlineProvider() { override fun getOutline(view: View, outline: Outline?) { outline?.setRoundRect( 0, @@ -52,8 +56,8 @@ class TabInCollectionViewHolder( interactor.onCollectionOpenTabClicked(tab) } - collection_tab_close_button.increaseTapArea(buttonIncreaseDps) - collection_tab_close_button.setOnClickListener { + list_item_action_button.increaseTapArea(buttonIncreaseDps) + list_item_action_button.setOnClickListener { interactor.onCollectionRemoveTab(collection, tab) } } @@ -61,28 +65,26 @@ class TabInCollectionViewHolder( fun bindSession(collection: TabCollection, tab: ComponentTab, isLastTab: Boolean) { this.collection = collection this.tab = tab - this.isLastTab = isLastTab + this.isLastItem = isLastTab updateTabUI() } private fun updateTabUI() { - collection_tab_hostname.text = tab.url.toShortUrl(view.context.components.publicSuffixList) + list_item_url.text = tab.url.toShortUrl(view.context.components.publicSuffixList) - collection_tab_title.text = tab.title - collection_tab_icon.context.components.core.icons.loadIntoView(collection_tab_icon, tab.url) + list_element_title.text = tab.title + list_item_favicon.context.components.core.icons.loadIntoView(list_item_favicon, tab.url) - // If I'm the last one... - if (isLastTab) { + // If last item and we want to change UI for it + if (isLastItem && differentLastItem) { view.background = AppCompatResources.getDrawable(view.context, R.drawable.rounded_bottom_corners) - divider_line.visibility = View.GONE } else { view.setBackgroundColor(view.context.getColorFromAttr(R.attr.above)) - divider_line.visibility = View.VISIBLE } } companion object { const val buttonIncreaseDps = 12 - const val LAYOUT_ID = R.layout.tab_in_collection + const val LAYOUT_ID = R.layout.list_element } } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt index 60af3cc2c..20d6d8aaa 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchFragment.kt @@ -27,6 +27,7 @@ import kotlinx.android.synthetic.main.search_suggestions_onboarding.view.* import kotlinx.coroutines.ExperimentalCoroutinesApi import mozilla.components.concept.storage.HistoryStorage import mozilla.components.feature.qr.QrFeature +import mozilla.components.feature.qr.QrFragment import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.base.feature.ViewBoundFeatureWrapper @@ -278,6 +279,31 @@ class SearchFragment : Fragment(), UserInteractionHandler { permissionDidUpdate = false hideToolbar() + + if (!isQrFragmentVisible()) { + refocusUrlView() + } + } + + /** + * Refocus URL editText. Needed after the user brings back the app + * into the foreground. + * See https://github.com/mozilla-mobile/fenix/issues/6290 + **/ + private fun refocusUrlView() { + val urlView = toolbarView.view + .findViewById(R.id.mozac_browser_toolbar_edit_url_view) + if (!urlView.hasFocus()) { + urlView.requestFocus() + } + } + + /** + * Check to see if QrFragment exists & is visible. + * */ + private fun isQrFragmentVisible(): Boolean { + val foundQrFragment = parentFragmentManager.fragments.firstOrNull { it is QrFragment } + return foundQrFragment != null && foundQrFragment.isVisible } override fun onPause() { 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 f7e529aa1..8aae91345 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -10,6 +10,8 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import androidx.appcompat.content.res.AppCompatResources +import android.os.Handler +import android.widget.Toast import androidx.lifecycle.lifecycleScope import androidx.navigation.NavDirections import androidx.navigation.findNavController @@ -45,6 +47,7 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.account.AccountAuthErrorPreference import org.mozilla.fenix.settings.account.AccountPreference +import kotlin.system.exitProcess @Suppress("LargeClass", "TooManyFunctions") class SettingsFragment : PreferenceFragmentCompat() { @@ -300,6 +303,29 @@ class SettingsFragment : PreferenceFragmentCompat() { requireComponents.core.engine.settings.remoteDebuggingEnabled = newValue true } + + val preferenceFxAOverride = + findPreference(getPreferenceKey(R.string.pref_key_override_fxa_server)) + val preferenceSyncOverride = + findPreference(getPreferenceKey(R.string.pref_key_override_sync_tokenserver)) + + val syncFxAOverrideUpdater = object : StringSharedPreferenceUpdater() { + override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { + return super.onPreferenceChange(preference, newValue).also { + updateFxASyncOverrideMenu() + Toast.makeText( + context, + getString(R.string.toast_override_fxa_sync_server_done), + Toast.LENGTH_LONG + ).show() + Handler().postDelayed({ + exitProcess(0) + }, FXA_SYNC_OVERRIDE_EXIT_DELAY) + } + } + } + preferenceFxAOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater + preferenceSyncOverride?.onPreferenceChangeListener = syncFxAOverrideUpdater } private fun navigateFromSettings(directions: NavDirections) { @@ -343,6 +369,8 @@ class SettingsFragment : PreferenceFragmentCompat() { val accountManager = requireComponents.backgroundServices.accountManager val account = accountManager.authenticatedAccount() + updateFxASyncOverrideMenu() + // Signed-in, no problems. if (account != null && !accountManager.accountNeedsReauth()) { preferenceSignIn?.isVisible = false @@ -388,7 +416,31 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + private fun updateFxASyncOverrideMenu() { + val preferenceFxAOverride = + findPreference(getPreferenceKey(R.string.pref_key_override_fxa_server)) + val preferenceSyncOverride = + findPreference(getPreferenceKey(R.string.pref_key_override_sync_tokenserver)) + val settings = requireContext().settings() + val show = settings.overrideFxAServer.isNotEmpty() || + settings.overrideSyncTokenServer.isNotEmpty() || + settings.showSecretDebugMenuThisSession + // Only enable changes to these prefs when the user isn't connected to an account. + val enabled = requireComponents.backgroundServices.accountManager.authenticatedAccount() == null + preferenceFxAOverride?.apply { + isVisible = show + isEnabled = enabled + summary = settings.overrideFxAServer.ifEmpty { null } + } + preferenceSyncOverride?.apply { + isVisible = show + isEnabled = enabled + summary = settings.overrideSyncTokenServer.ifEmpty { null } + } + } + companion object { private const val SCROLL_INDICATOR_DELAY = 10L + private const val FXA_SYNC_OVERRIDE_EXIT_DELAY = 2000L } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt index 4109e3f95..e96d6be35 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/about/AboutFragment.kt @@ -10,6 +10,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.core.content.pm.PackageInfoCompat import androidx.fragment.app.Fragment import androidx.recyclerview.widget.DividerItemDecoration @@ -20,6 +21,7 @@ import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.lib.Do import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.settings.about.AboutItemType.LICENSING_INFO @@ -36,6 +38,8 @@ import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig class AboutFragment : Fragment(), AboutPageListener { private lateinit var appName: String private val aboutPageAdapter: AboutPageAdapter = AboutPageAdapter(this) + private var secretDebugMenuClicks = 0 + private var lastDebugMenuToast: Toast? = null override fun onCreateView( inflater: LayoutInflater, @@ -49,6 +53,11 @@ class AboutFragment : Fragment(), AboutPageListener { return rootView } + override fun onResume() { + super.onResume() + secretDebugMenuClicks = 0 + } + @ExperimentalCoroutinesApi override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -63,8 +72,36 @@ class AboutFragment : Fragment(), AboutPageListener { ) } + // 5 taps on the logo activate the "secret" debug menu. + wordmark.setOnClickListener { + // Because the user will mostly likely tap the logo in rapid succession, + // we ensure only 1 toast is shown at any given time. + lastDebugMenuToast?.let { toast -> toast.cancel() } + secretDebugMenuClicks += 1 + when (secretDebugMenuClicks) { + in 2 until SECRET_DEBUG_MENU_CLICKS -> { + val clicksLeft = SECRET_DEBUG_MENU_CLICKS - secretDebugMenuClicks + val toast = Toast.makeText( + context, + getString(R.string.about_debug_menu_toast_progress, clicksLeft), + Toast.LENGTH_SHORT + ) + toast.show() + lastDebugMenuToast = toast + } + SECRET_DEBUG_MENU_CLICKS -> { + Toast.makeText( + context, + getString(R.string.about_debug_menu_toast_done), + Toast.LENGTH_LONG + ).show() + requireContext().settings().showSecretDebugMenuThisSession = true + } + } + } + populateAboutHeader() - aboutPageAdapter.updateData(populateAboutList()) + aboutPageAdapter.submitList(populateAboutList()) } private fun populateAboutHeader() { @@ -183,5 +220,7 @@ class AboutFragment : Fragment(), AboutPageListener { companion object { private const val ABOUT_LICENSE_URL = "about:license" + // Number of clicks on the app logo to enable the "secret" debug menu. + private const val SECRET_DEBUG_MENU_CLICKS = 5 } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/about/AboutPageAdapter.kt b/app/src/main/java/org/mozilla/fenix/settings/about/AboutPageAdapter.kt index 3e38e04ac..e4b418dd7 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/about/AboutPageAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/about/AboutPageAdapter.kt @@ -6,33 +6,33 @@ package org.mozilla.fenix.settings.about import android.view.LayoutInflater import android.view.ViewGroup -import androidx.annotation.VisibleForTesting -import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter import org.mozilla.fenix.settings.about.viewholders.AboutItemViewHolder -class AboutPageAdapter(private val listener: AboutPageListener) : RecyclerView.Adapter() { - - @VisibleForTesting - var aboutList: List? = null - - fun updateData(items: List) { - this.aboutList = items - notifyDataSetChanged() - } +class AboutPageAdapter(private val listener: AboutPageListener) : + ListAdapter(DiffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AboutItemViewHolder { val view = LayoutInflater.from(parent.context) .inflate(AboutItemViewHolder.LAYOUT_ID, parent, false) - return AboutItemViewHolder(view, listener) } - override fun getItemCount(): Int = aboutList?.size ?: 0 - override fun onBindViewHolder(holder: AboutItemViewHolder, position: Int) { - (aboutList?.get(position) as AboutPageItem.Item).also { - holder.bind(it) - } + holder.bind(getItem(position) as AboutPageItem.Item) + } + + private object DiffCallback : DiffUtil.ItemCallback() { + + override fun areItemsTheSame(oldItem: AboutPageItem, newItem: AboutPageItem) = + oldItem === newItem + + override fun areContentsTheSame(oldItem: AboutPageItem, newItem: AboutPageItem) = + when (oldItem) { + is AboutPageItem.Item -> + newItem is AboutPageItem.Item && oldItem.title == newItem.title + } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt index 1629674e9..24a5d2834 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragment.kt @@ -65,6 +65,7 @@ class SavedLoginsFragment : Fragment() { savedLoginsStore = StoreProvider.get(this) { SavedLoginsFragmentStore( SavedLoginsFragmentState( + isLoading = true, items = listOf(), filteredItems = listOf() ) diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragmentStore.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragmentStore.kt index 86f9842bb..68898bf39 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragmentStore.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsFragmentStore.kt @@ -48,6 +48,7 @@ sealed class SavedLoginsFragmentAction : Action { * @property items Filtered (or not) list of logins to display */ data class SavedLoginsFragmentState( + val isLoading: Boolean = false, val items: List, val filteredItems: List ) : State @@ -61,14 +62,19 @@ private fun savedLoginsStateReducer( ): SavedLoginsFragmentState { return when (action) { is SavedLoginsFragmentAction.UpdateLogins -> state.copy( + isLoading = false, items = action.list, filteredItems = action.list ) is SavedLoginsFragmentAction.FilterLogins -> { if (action.newText.isNullOrBlank()) { - state.copy(filteredItems = state.items) + state.copy( + isLoading = false, + filteredItems = state.items) } else { - state.copy(filteredItems = state.items.filter { it.url.contains(action.newText) }) + state.copy( + isLoading = false, + filteredItems = state.items.filter { it.url.contains(action.newText) }) } } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsView.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsView.kt index 293ea31a0..42170ae5d 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsView.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/SavedLoginsView.kt @@ -14,6 +14,7 @@ import androidx.core.view.isVisible import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.extensions.LayoutContainer import kotlinx.android.synthetic.main.component_saved_logins.view.* +import kotlinx.android.synthetic.main.component_saved_logins.view.progress_bar import org.mozilla.fenix.R /** @@ -69,8 +70,13 @@ class SavedLoginsView( } fun update(state: SavedLoginsFragmentState) { - view.saved_logins_list.isVisible = state.items.isNotEmpty() - view.saved_passwords_empty_view.isVisible = state.items.isEmpty() + if (state.isLoading) { + view.progress_bar.isVisible = true + } else { + view.progress_bar.isVisible = false + view.saved_logins_list.isVisible = state.items.isNotEmpty() + view.saved_passwords_empty_view.isVisible = state.items.isEmpty() + } loginsAdapter.submitList(state.filteredItems) } } diff --git a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt index d21adccac..b8c40daf5 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/sitepermissions/SitePermissionsManagePhoneFeatureFragment.kt @@ -4,7 +4,6 @@ package org.mozilla.fenix.settings.sitepermissions -import android.content.Context import android.content.Intent import android.graphics.Color import android.net.Uri @@ -30,7 +29,6 @@ import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.AL import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.ASK_TO_ALLOW import mozilla.components.feature.sitepermissions.SitePermissionsRules.Action.BLOCKED import org.mozilla.fenix.R -import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.PhoneFeature @@ -122,7 +120,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { // TODO replace with AUTOPLAY_ALLOW_ON_WIFI when // https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed. This GV bug // makes ALLOW_ALL behave as ALLOW_ON_WIFI - saveActionInSettings(it.context, AUTOPLAY_ALLOW_ALL) + saveActionInSettings(AUTOPLAY_ALLOW_ALL) } // TODO replace with AUTOPLAY_ALLOW_ON_WIFI when // https://bugzilla.mozilla.org/show_bug.cgi?id=1621825 is fixed. This GV bug @@ -144,7 +142,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { visibility = View.VISIBLE text = getString(R.string.preference_option_autoplay_block_audio2) setOnClickListener { - saveActionInSettings(it.context, AUTOPLAY_BLOCK_AUDIBLE) + saveActionInSettings(AUTOPLAY_BLOCK_AUDIBLE) } restoreState(AUTOPLAY_BLOCK_AUDIBLE) } else { @@ -162,7 +160,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { getString(R.string.phone_feature_recommended) ) setOnClickListener { - saveActionInSettings(it.context, AUTOPLAY_BLOCK_ALL) + saveActionInSettings(AUTOPLAY_BLOCK_ALL) } restoreState(AUTOPLAY_BLOCK_ALL) } else { @@ -195,19 +193,18 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() { * See [Settings.setAutoplayUserSetting] kdoc for an explanation of why this cannot follow the * same code path as other permissions. */ - private fun saveActionInSettings(context: Context, autoplaySetting: Int) { + private fun saveActionInSettings(autoplaySetting: Int) { settings.setAutoplayUserSetting(autoplaySetting) val (audible, inaudible) = when (autoplaySetting) { - AUTOPLAY_ALLOW_ALL -> ALLOWED to ALLOWED + AUTOPLAY_ALLOW_ALL, AUTOPLAY_ALLOW_ON_WIFI -> { - context.components.wifiIntegration.addWifiConnectedListener() + settings.setAutoplayUserSetting(AUTOPLAY_ALLOW_ON_WIFI) return } AUTOPLAY_BLOCK_AUDIBLE -> BLOCKED to ALLOWED AUTOPLAY_BLOCK_ALL -> BLOCKED to BLOCKED else -> return } - context.components.wifiIntegration.removeWifiConnectedListener() settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_AUDIBLE, audible) settings.setSitePermissionsPhoneFeatureAction(AUTOPLAY_INAUDIBLE, inaudible) } 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 0510f67d3..5b4c5f4cf 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -187,6 +187,8 @@ class Settings private constructor( (trackingProtectionOnboardingCount < trackingProtectionOnboardingMaximumCount && !trackingProtectionOnboardingShownThisSession) + var showSecretDebugMenuThisSession = false + val shouldShowSecurityPinWarningSync: Boolean get() = loginsSecureWarningSyncCount < showLoginsSecureWarningSyncMaxCount @@ -597,4 +599,14 @@ class Settings private constructor( appContext.getPreferenceKey(R.string.pref_key_open_links_in_external_app), default = false ) + + var overrideFxAServer by stringPreference( + appContext.getPreferenceKey(R.string.pref_key_override_fxa_server), + default = "" + ) + + var overrideSyncTokenServer by stringPreference( + appContext.getPreferenceKey(R.string.pref_key_override_sync_tokenserver), + default = "" + ) } diff --git a/app/src/main/java/org/mozilla/fenix/wifi/WifiIntegration.kt b/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt similarity index 86% rename from app/src/main/java/org/mozilla/fenix/wifi/WifiIntegration.kt rename to app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt index b81df21fd..f4aea3bac 100644 --- a/app/src/main/java/org/mozilla/fenix/wifi/WifiIntegration.kt +++ b/app/src/main/java/org/mozilla/fenix/wifi/SitePermissionsWifiIntegration.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.wifi import mozilla.components.feature.sitepermissions.SitePermissionsRules +import mozilla.components.support.base.feature.LifecycleAwareFeature import org.mozilla.fenix.settings.PhoneFeature import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_ALLOW_ON_WIFI import org.mozilla.fenix.settings.sitepermissions.AUTOPLAY_BLOCK_ALL @@ -14,7 +15,10 @@ import org.mozilla.fenix.utils.Settings * Handles implementation details of only setting up a WIFI connectivity listener if the current * user settings require it. */ -class WifiIntegration(private val settings: Settings, private val wifiConnectionMonitor: WifiConnectionMonitor) { +class SitePermissionsWifiIntegration( + private val settings: Settings, + private val wifiConnectionMonitor: WifiConnectionMonitor +) : LifecycleAwareFeature { /** * Adds listener for autplay setting [AUTOPLAY_ALLOW_ON_WIFI]. Sets all autoplay to allowed when @@ -51,7 +55,7 @@ class WifiIntegration(private val settings: Settings, private val wifiConnection // only works while WIFI is active, so we are not using AUTOPLAY_ALLOW_ON_WIFI (or this class). // Once that is fixed, [start] and [maybeAddWifiConnectedListener] will need to be called on // activity startup. - fun start() { wifiConnectionMonitor.start() } + override fun start() { wifiConnectionMonitor.start() } - fun stop() { wifiConnectionMonitor.stop() } + override fun stop() { wifiConnectionMonitor.stop() } } diff --git a/app/src/main/res/layout/collection_home_list_row.xml b/app/src/main/res/layout/collection_home_list_row.xml index 366d4d8dc..302d65bf0 100644 --- a/app/src/main/res/layout/collection_home_list_row.xml +++ b/app/src/main/res/layout/collection_home_list_row.xml @@ -1,14 +1,12 @@ - - - + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_tab_collection" /> - - + app:layout_constraintTop_toTopOf="@id/collection_icon" + app:srcCompat="@drawable/ic_hollow_share" + tools:visibility="visible" /> + app:layout_constraintTop_toTopOf="@id/collection_icon" + app:srcCompat="@drawable/ic_menu" + tools:visibility="visible" /> + + + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintTop_toBottomOf="parent"/> + app:layout_constraintEnd_toEndOf="@id/list_element_title" + app:layout_constraintStart_toStartOf="@id/list_element_title" + app:layout_constraintTop_toBottomOf="@id/list_element_title" /> - - + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 04208143b..e2c4d33d7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1069,6 +1069,9 @@ Der Schutz für diese Website ist deaktiviert Verbesserter Schutz vor Aktivitätenverfolgung ist für diese Websites deaktiviert + + Rückwärts navigieren Ihre Rechte diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index eec883242..0a428c69d 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -1038,6 +1038,9 @@ Šćit jo znjemóžnjony za toś to sedło Pólěpšony slědowański šćit jo znjemóžnjony za toś te sedła + + Slědk nawigěrowaś Waše pšawa diff --git a/app/src/main/res/values-en-rCA/strings.xml b/app/src/main/res/values-en-rCA/strings.xml index 6c9819be8..966faeb95 100644 --- a/app/src/main/res/values-en-rCA/strings.xml +++ b/app/src/main/res/values-en-rCA/strings.xml @@ -107,7 +107,7 @@ Reader view - Open in app + Open in App Appearance @@ -1028,6 +1028,9 @@ Protections are OFF for this site Enhanced Tracking Protection is off for these websites + + Navigate back Your rights diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 7efb26e09..e2d2fef5a 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -106,7 +106,7 @@ Reader view - Open in app + Open in App Appearance diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index 6b87d0f1a..41c0a0405 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -1057,6 +1057,9 @@ Las protecciones están OFF para este sitio La protección contra rastreo aumentada está deshabilitada para estos sitios + + Ir hacia atrás Tus derechos diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 000000000..43e35c6f7 --- /dev/null +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,143 @@ + + + + Firefox Preview privado + + Firefox Preview (privado) + + + Más opciones + + Habilitar navegación privada + + Deshabilitar navegación privada + + Buscar o ingresar dirección + + No hay pestañas abiertas + + Las pestañas abiertas aparecerán aquí. + + + + Estás en una sesión privada + + %1$s limpia tu historial de búsqueda y navegación cuando cierras la aplicación o todas las pestañas privadas. Aunque no te hace anónimo para los sitios web o proveedores de servicios de Internet, + te ayuda a mantener en privado lo que haces en línea frente a cualquier otra persona que use este dispositivo. + Mitos comunes sobre la navegación privada + + Eliminar sesión + + + + Agregar un acceso directo para abrir pestañas privadas desde su pantalla de inicio. + + Agregar acceso directo + + No, gracias + + + + Nueva pestaña + + Nueva pestaña privada + + + + Abrir pestañas + + Atrás + + Avanzar + + Actualizar + + Detener + + Marcador + + Editar marcador + + Complementos + + No hay complementos aquí + + Ayuda + + Novedades + + Ajustes + + Biblioteca + + Sitio de escritorio + + + Agregar a pantalla de inicio + + Instalar + + Encontrar en página + + Pestaña privada + + Nueva pestaña + + Guardar en colección + + Reportar problema con el sitio + + Compartir + + Compartir con… + + Abrir en %1$s + + PATROCINADO POR %1$s + + Patrocinado por %1$s + + Vista de lectura + + Abrir en la aplicación + + + Apariencia + + + + Seleccionar idioma + + Buscar + + Usar el idioma del dispositivo + + Buscar idioma + + + + Escanear + + Atajos + + Configuración del buscador + + Buscar con + + Esta vez, buscar con: + + Pegar enlace del portapapeles + + Permitir + + No compartir + + ¿Permitir sugerencias de búsqueda en sesiones privadas? + + %s compartirá todo lo que escribas en la barra de direcciones con tu buscador predeterminado. + + diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 422d955d5..e9dbd2e3e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -1052,6 +1052,9 @@ Suojaukset ovat POIS PÄÄLTÄ tällä sivustolla Tehostettu seurannan suojaus ei ole käytössä näillä sivustoilla + + Siirry taaksepäin Oikeutesi diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7fbf110bf..2c8b05b00 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1071,6 +1071,9 @@ Les protections sont désactivées pour ce site La protection renforcée contre le pistage est désactivée pour ces sites web + + Précédent Vos droits diff --git a/app/src/main/res/values-gn/strings.xml b/app/src/main/res/values-gn/strings.xml index 57b8aef62..586739dc2 100644 --- a/app/src/main/res/values-gn/strings.xml +++ b/app/src/main/res/values-gn/strings.xml @@ -1057,6 +1057,9 @@ Umi ñemo’ã ojepe’áma ko tendápe g̃uarã Ñemo’ã tapykuehogua oñemboguéma ko’ã tendápe g̃uarã + + Eikundaha tapykuévo Nde derécho diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 9706741d0..505164be5 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -71,7 +71,7 @@ Biblioteka - Web-stanica za desktop + Klasični prikaz Dodaj na početni ekran @@ -337,7 +337,7 @@ Uključi sinkronizaciju - Skeniraj kod za uparivanje u desktop Firefoxu + Skeniraj kôd za uparivanje u Firefoxu za računalo Prijavi se @@ -381,7 +381,7 @@ Zabilješke - Desktop zabilješke + Zabilješke računala Izbornik za zabilješke diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index f7a6c8eea..b5e4d624e 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -1039,6 +1039,9 @@ Škit je znjemóžnjeny za tute sydło Polěpšeny slědowanski škit je znjemóžnjeny za tute sydła + + Wróćo nawigować Waše prawa diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 90f8a266f..d6d2b0192 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -948,6 +948,9 @@ ההגנות כבויות עבור אתר זה הגנת מעקב מתקדמת כבויה עבור האתרים האלו + + ניווט אחורה הזכויות שלך diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 727772b7d..b15004ea1 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1082,6 +1082,9 @@ 이 사이트에서 보호 꺼짐 이 웹 사이트에 대해 향상된 추적 방지 기능이 꺼져 있습니다 + + 뒤로 사용자 권리 diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index d889a99c8..48ac4c94b 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -21,6 +21,10 @@ आपण खाजगी सत्रात आहात + + आपण अप किंवा सर्व खाजगी टॅब बंद केल्यावर आपला शोध किंवा ब्राऊझिंग इतिहास %1$s मिटवते. यामुळे आपण वापरणाऱ्या साईट किंवा इंटरनेट सेवा देणार्यांपासून आपण होत नाही, + पण आपण ऑनलाईन काय करता हे आपले डिव्हाईस वापरणाऱ्या इतरांपासून खाजगी ठेवण्यास सोपे होते. खाजगी ब्राउझिंग बद्दल सामान्य समजुती सत्र हटवा @@ -56,7 +60,7 @@ वाचनखूण संपादीत करा - अ‍ॅड-ऑन व्यवस्थापक + ॲड-ऑन येथे अ‍ॅड-ऑन नाहीत @@ -66,7 +70,7 @@ सेटिंग - आपले ग्रंथालय + लायब्ररी डेस्कटॉप साइट @@ -80,7 +84,7 @@ नवीन टॅब - संग्रहात जतन करा + संग्रहात जतन करा साईटची त्रुटी कळवा @@ -134,6 +138,8 @@ परवानगी देऊ नका खाजगी सत्रांमध्ये शोध प्रस्तावांना परवानगी द्यायची का? + + पत्ता पट्टी मध्ये आपण जे काही टाईप कराल ते सर्व %s आपल्या पूर्वनिर्धारित शोध इंजिन सह शेअर करेल. अधिक जाणून घ्या @@ -187,6 +193,8 @@ गोपनीय ब्राउझिंग दुवा खाजगी टॅबमध्ये उघडा + + खाजगी ब्राउझिंग शॉर्टकट जोडा सुलभता @@ -199,6 +207,8 @@ रंगयोजना स्वेच्छेनुरूप करा + + आपल्या Firefox खात्यासह बुकमार्क, इतिहास आणि बरेच काही सिंक करा Firefox खाते @@ -214,6 +224,16 @@ विकासकांची साधने + + USB द्वारे दूरस्थ डीबगिंग + + शोध शॉर्टकट दर्शवा + + शोध सूचना दाखवा + + खाजगी सत्रांमध्ये दर्शवा + + क्लिपबोर्ड सूचना दर्शवा ब्राउझिंग इतिहास शोधा @@ -228,6 +248,8 @@ आत्ता सिंक करा + + काय सिंक करायचे ते निवडा इतिहास @@ -239,45 +261,87 @@ डिव्हाईसचे नाव + + डिव्हाइसचे नाव रिक्त असू शकत नाही. + + सिंक करत आहे… + + सिंक अयशस्वी. शेवटचे यश: %s + + सिंक अयशस्वी. शेवटचे सिंक: कधीच नाही + + शेवटचे सिंक: %s + + शेवटचे सिंक: कधीच नाही + + %s %s %s वर + प्राप्त टॅब + + इतर Firefox डिव्हाइसमधून प्राप्त केलेल्या टॅबच्या सूचना. टॅब प्राप्त झाला टॅब प्राप्त झाले + + %s कडून टॅब + ट्रॅकिंग संरक्षण ट्रॅकिंग संरक्षण + + ऑनलाइन ट्रॅक करणारी मजकूर आणि स्क्रिप्ट अवरोधित करा अपवाद या साइटसाठी ट्रॅकिंग संरक्षण बंद आहे सर्व साईट साठी चालू करा + + अपवाद आपल्याला निवडलेल्या साइटसाठी ट्रॅकिंग संरक्षण अक्षम करू देतात. अधिक जाणा + + सर्व स्तरावर बंद, चालू करण्यासाठी सेटिंगवर जा. + दूरमापन वापर आणि तांत्रिक माहिती + + आम्ही %1$s उत्तमोत्तम बनवण्यासाठी ब्राऊझरची कार्यक्षमता, वापर, हार्डवेअर आणि सानुकूलन माहिती Mozilla सोबत शेअर करते विपणनाची माहिती + + आपण %1$s मधील कोणती वैशिष्ठ्ये वापरता याची माहिती आमचे मोबाईल मार्केटर Leanplum यांच्यासोबत शेअर करते. प्रयोग Mozilla ला प्रायोगिक वैशिष्ट्ये स्थापित करण्यासाठी आणि माहिती गोळा करण्यासाठी अनुमती देते + + क्रॅश अहवाल देणारा Mozilla ची स्थान सेवा %s आरोग्य अहवाल + + + सिंक चालू करा + + डेस्कटॉप Firefox मध्ये जोडणी कोड स्कॅन करा साइन इन करा + + पुन्हा जोडण्यासाठी साइन इन करा खाते काढून टाका @@ -300,6 +364,8 @@ फिकट गडद + + बॅटरी सेव्हरद्वारे सेट केलेले डिव्हाइस थीमचे अनुसरण करा @@ -308,10 +374,18 @@ सत्रे स्क्रीनशॉट + + डाउनलोड वाचनखुणा + + डेस्कटॉप वाचनखूणा वाचनखुणा मेनू + + वाचनखूणा साधनपट्टी + + इतर वाचनखूणा इतिहास @@ -320,6 +394,10 @@ शोधा लायब्ररी + + सेटिंग + + इतिहास आयटम मेनू बंद करा @@ -341,12 +419,20 @@ टॅबचा मेनू उघडा सर्व टॅब बंद करा + + टॅब शेअर करा संग्रहात जतन करा + + टॅब मेनू + + टॅब शेअर करा नष्ट करा जतन करा + + शेअर करा चालू सत्राचे चित्र @@ -390,6 +476,8 @@ क्षमस्व. %1$s ते पृष्ठ लोड करू शकत नाही. + + आपण खाली हा टॅब पुनर्संचयित किंवा बंद करण्याचा प्रयत्न करू शकता. Mozilla ला क्रॅश अहवाल पाठवा @@ -400,12 +488,20 @@ सत्र पर्याय + + सत्र शेअर करा + + + + वाचनखूणा मेनू वाचनखूण संपादीत करा फोल्डर निवडा फोल्डर जोडा + + वाचनखुण बनवली. वाचनखुण जतन केली! @@ -433,6 +529,8 @@ वाचनखूण संपादीत करा फोल्डर संपादित करा + + सिंक केलेल्या वाचनखुणा पाहण्यासाठी साइन इन करा URL @@ -464,6 +562,10 @@ परवानग्या सेटिंग मध्ये जा + + द्रुत सेटिंग पत्रक शिफारसीय @@ -499,18 +601,8 @@ बंद - - व्हिडिओ आणि ऑडिओ अवरोधित - - व्हिडिओ आणि ऑडिओला परवानगी आहे ऑडिओ आणि व्हिडिओला परवानगी द्या - - केवळ Wi-Fi वर ऑडिओ आणि व्हिडिओला अनुमती द्या - - ऑडिओ अवरोधित करा - - व्हिडिओ आणि ऑडिओ अवरोधित करा सुरू @@ -606,6 +698,8 @@ खाजगी टॅब बंद केले + + नाकारा हटवा @@ -705,4 +799,162 @@ आपली थीम निवडा - + + गडद रंगसंगती वापरून थोडी बॅटरी आणि तुमची दृष्टी वाचवा. + + स्वयंचलित + + गडद रंगसंगती + + + टॅब्स पाठवले! + + पाठविण्यात असमर्थ + + पुन्हा प्रयत्न करा + + + https://firefox.com/pair वर जा]]> + + स्कॅन करण्यास सज्ज + + त्याऐवजी ईमेल वापरा + + जोडणी तोडा + + रद्द करा + + + + संरक्षण सेटिंग + + वर्धित ट्रॅकिंग संरक्षण + + पाठलाग करून न घेता ब्राउझ करा + + अधिक जाणा + + प्रमाणित + + प्रमाणित (सुचवलेले) + + काटेकोर + + + कुकीज + + भेट न दिलेल्या संकेतस्थळांवरील कुकीज + + सर्व टॅब मध्ये + + फक्त गोपनीय टॅब मध्ये + अवरोधित + + अनुमती दिलेले + + या संकेतस्थळासाठी संरक्षण चालू आहे + + आपले हक्क + + %s मध्ये नवीन काय आहे + + + मदत + + गोपनीयता सूचना + + आपले हक्क जाणा + + अनुज्ञप्तीची माहिती + + + + प्रत बनवा + + चिकटवा व जा + + चिकटवा + + + मुख्य पटलावर जोडा + + रद्द करा + + जोडा + + + जतन करण्याबद्दल विचारा + + कधीही जतन करू नका + + स्वयंचलितपणे भरा + + सुरू + + बंद करा + + पुनर्जोडणी करा + + अपवाद + + वर्णक्रमानुसार + + अलीकडे वापरलेले + + संकेतस्थळ + + वापरकर्तानाव + + पासवर्ड + + पिन पुन्हा प्रविष्ट करा + + + ही जोडणी सुरक्षित नाही. येथे प्रविष्ट केलेल्या लॉगिनचा गैरवापर होऊ शकतो. + + अधिक जाणा + + जतन करा + + जतन करू नका + + नंतर + + + जतन करा + + संपादित करा + + काढून टाका + + + इतर + + नाव + + अधिक जाणा + + + %s अद्ययावत करत आहोत… + + %s सुरु करा + + स्थित्यंतर पूर्ण + + पासवर्ड + + + अनुमती देण्यासाठी: + + + सुरक्षित जोडणी + + असुरक्षित जोडणी + + %1$s : द्वारे सत्यापित + + काढून टाका + + काढून टाका + diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index fb9ba0cc7..8fae80706 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -67,7 +67,7 @@ ਬੁੱਕਮਾਰਕ ਸੋਧੋ - ਐਡ-ਆਨ ਮੈਨੇਜਰ + ਐਡ-ਆਨ ਕੋਈ ਐਡ-ਆਨ ਨਹੀਂ ਹੈ @@ -77,7 +77,7 @@ ਸੈਟਿੰਗਾਂ - ਤੁਹਾਡੀ ਲਾਇਬਰੇਰੀ + ਲਾਇਬਰੇਰੀ ਡੈਸਕਟਾਪ ਸਾਈਟ @@ -90,9 +90,9 @@ ਪ੍ਰਾਈਵੇਟ ਟੈਬ ਨਵੀਂ ਟੈਬ - - ਭੰਡਾਰ ‘ਚ ਸੰਭਾਲੋ + + ਭੰਡਾਰ ‘ਚ ਸੰਭਾਲੋ ਸਾਈਟ ਮਸਲੇ ਬਾਰੇ ਰਿਪੋਰਟ ਕਰੋ @@ -613,19 +613,12 @@ ਬੰਦ - - ਵਿਡੀਓ ਤੇ ਆਡੀਓ ‘ਤੇ ਪਾਬੰਦੀ ਲਾਈ - - ਵਿਡੀਓ ਅਤੇ ਆਡੀਓ ਦੀ ਇਜਾਜ਼ਤ ਹੈ - ਆਡੀਓ ਅਤੇ ਵੀਡਿਓ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ - - ਸਿਰਫ਼ Wi-Fi ਉੱਤੇ ਆਡੀਓ ਤੇ ਵੀਡਿਡ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ - ਆਡੀਓ ਤੇ ਪਾਬੰਦੀ ਲਾਓ + ਸਿਰਫ਼ ਆਡੀਓ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਓ - ਵੀਡਿਓ ਅਤੇ ਆਡੀਓ ਤੇ ਪਾਬੰਦੀ ਲਾਓ + ਆਡੀਓ ਅਤੇ ਵੀਡਿਓ ਤੇ ਪਾਬੰਦੀ ਲਾਓ ਚਾਲੂ @@ -1054,6 +1047,9 @@ ਇਸ ਸਾਈਟ ਲਈ ਸੁਰੱਖਿਆ ਬੰਦ ਹੈ ਇਹਨਾਂ ਵੈੱਬਸਾਈਟਾਂ ਲਈ ਵਧੇਰੇ ਟਰੈਕਿੰਗ ਸੁਰੱਖਿਆ ਬੰਦ ਹੈ + + ਪਿੱਛੇ ਵੱਲ ਜਾਓ ਤੁਹਾਡੇ ਹੱਕ diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a0e8b6f66..c6f864d8b 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1039,6 +1039,9 @@ As proteções estão DESATIVADAS neste site A proteção aprimorada contra rastreamento está desativada nesses sites + + Voltar à página anterior Seus direitos diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 15bbdab7c..89d6cbc84 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -1054,6 +1054,9 @@ Skydd är AV för den här webbplatsen Förbättrat spårningsskydd är avstängt för dessa webbplatser + + Navigera bakåt Dina rättigheter diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 3683b54fc..11b3f1c37 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1032,6 +1032,9 @@ Bu sitede korumalar KAPALI Aşağıdaki sitelerde gelişmiş izlenme koruması kapatıldı + + Geri git Haklarınız diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index df5e5ab35..a0faa22a2 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -1052,6 +1052,9 @@ Захист на цьому сайті вимкнено Розширений захист від стеження вимкнено для цих вебсайтів + + Перейти назад Ваші права diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 39478b43c..3a45fe728 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1074,6 +1074,9 @@ 对此网站已关闭保护 对下列网站已关闭增强型跟踪保护 + + 浏览上一页 您的权利 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index d8b28c694..a55e5401c 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1068,6 +1068,9 @@ 已關閉此網站的追蹤保護 針對下列網站關閉加強型追蹤保護 + + 瀏覽上一頁 您的權利 diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 1b622472f..fd44fb5bf 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -38,6 +38,8 @@ pref_key_account pref_key_sign_in pref_key_account_auth_error + pref_key_override_fxa_server + pref_key_override_sync_tokenserver pref_key_private_mode pref_key_customize pref_key_toolbar diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b1111b18..9cffd5513 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -202,6 +202,12 @@ Add private browsing shortcut Accessibility + + Custom Firefox Account server + + Custom Sync server + + Firefox Account/Sync server modified. Quitting the application to apply changes… Account @@ -1062,6 +1068,10 @@ Licensing information Libraries that we use + + Debug menu: %1$d click(s) left to enable + Debug menu enabled 1 tab diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index b063228e2..2f727bef3 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -29,6 +29,20 @@ android:key="@string/pref_key_account_auth_error"/> + + + + @@ -103,13 +117,6 @@ android:key="@string/pref_key_open_links_in_external_app" android:title="@string/preferences_open_links_in_apps" /> - - - - + +