1
0
Fork 0

Copione merged onto master
continuous-integration/drone/push Build is passing Details

master
blallo 2020-07-07 00:00:44 +02:00
commit dd65dc2995
65 changed files with 2086 additions and 248 deletions

View File

@ -22,10 +22,11 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
uri: String,
hasUserGesture: Boolean,
isSameDomain: Boolean,
isRedirect: Boolean
isRedirect: Boolean,
isDirectNavigation: Boolean
): RequestInterceptor.InterceptionResponse? {
return appContext.components.services.accountsAuthFeature.interceptor.onLoadRequest(
engineSession, uri, hasUserGesture, isSameDomain, isRedirect
engineSession, uri, hasUserGesture, isSameDomain, isRedirect, isDirectNavigation
)
}
}

View File

@ -173,6 +173,7 @@ class ContextMenusTest {
}
@Test
@Ignore("Intermittent: https://github.com/mozilla-mobile/fenix/issues/12309")
fun verifyContextSaveImage() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)
@ -197,6 +198,7 @@ class ContextMenusTest {
}
@Test
@Ignore("Intermittent: https://github.com/mozilla-mobile/fenix/issues/12309")
fun verifyContextMixedVariations() {
val pageLinks =
TestAssetHelper.getGenericAsset(mockWebServer, 4)

View File

@ -43,7 +43,7 @@ class ThreeDotMenuMainTest {
@JvmStatic
fun setDevicePreference() {
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
mDevice.executeShellCommand("settings put secure long_press_timeout 1500")
mDevice.executeShellCommand("settings put secure long_press_timeout 3000")
}
}

View File

@ -21,10 +21,11 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
uri: String,
hasUserGesture: Boolean,
isSameDomain: Boolean,
isRedirect: Boolean
isRedirect: Boolean,
isDirectNavigation: Boolean
): RequestInterceptor.InterceptionResponse? {
return context.components.services.appLinksInterceptor
.onLoadRequest(engineSession, uri, hasUserGesture, isSameDomain, isRedirect)
.onLoadRequest(engineSession, uri, hasUserGesture, isSameDomain, isRedirect, isDirectNavigation)
}
override fun onErrorRequest(

View File

@ -63,8 +63,8 @@ import org.mozilla.fenix.exceptions.ExceptionsFragmentDirections
import org.mozilla.fenix.ext.alreadyOnDestination
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.resetPoliciesAfter
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.home.HomeFragmentDirections
import org.mozilla.fenix.home.intent.CrashReporterIntentProcessor
import org.mozilla.fenix.home.intent.DeepLinkIntentProcessor
@ -100,7 +100,7 @@ import org.mozilla.fenix.utils.RunWhenReadyQueue
* - browser screen
*/
@SuppressWarnings("TooManyFunctions", "LargeClass")
open class HomeActivity : LocaleAwareAppCompatActivity() {
open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
private var webExtScope: CoroutineScope? = null
lateinit var themeManager: ThemeManager
@ -392,7 +392,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
* Returns the [supportActionBar], inflating it if necessary.
* Everyone should call this instead of supportActionBar.
*/
fun getSupportActionBarAndInflateIfNecessary(): ActionBar {
override fun getSupportActionBarAndInflateIfNecessary(): ActionBar {
if (!isToolbarInflated) {
navigationToolbar = navigationToolbarStub.inflate() as Toolbar

View File

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix
import androidx.appcompat.app.ActionBar
/**
* Interface for the main activity in a single-activity architecture.
* All fragments will be displayed inside this activity.
*/
interface NavHostActivity {
/**
* Returns the support action bar, inflating it if necessary.
* Everyone should call this instead of supportActionBar.
*/
fun getSupportActionBarAndInflateIfNecessary(): ActionBar
}

View File

@ -5,10 +5,11 @@
package org.mozilla.fenix.addons
import android.content.Intent
import android.net.Uri
import android.content.Intent.ACTION_VIEW
import android.os.Bundle
import android.view.View
import androidx.annotation.StringRes
import androidx.core.net.toUri
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
@ -26,7 +27,7 @@ private const val LEARN_MORE_URL =
/**
* A fragment to show the permissions of an add-on.
*/
class AddonPermissionsDetailsFragment : Fragment(R.layout.fragment_add_on_permissions), View.OnClickListener {
class AddonPermissionsDetailsFragment : Fragment(R.layout.fragment_add_on_permissions) {
private val args by navArgs<AddonPermissionsDetailsFragmentArgs>()
@ -55,12 +56,9 @@ class AddonPermissionsDetailsFragment : Fragment(R.layout.fragment_add_on_permis
}
private fun bindLearnMore(view: View) {
view.learn_more_label.setOnClickListener(this)
}
override fun onClick(v: View?) {
val intent =
Intent(Intent.ACTION_VIEW).setData(Uri.parse(LEARN_MORE_URL))
startActivity(intent)
view.learn_more_label.setOnClickListener {
val intent = Intent(ACTION_VIEW, LEARN_MORE_URL.toUri())
startActivity(intent)
}
}
}

View File

@ -24,7 +24,6 @@ import mozilla.components.feature.app.links.AppLinksUseCases
import mozilla.components.feature.contextmenu.ContextMenuCandidate
import mozilla.components.feature.readerview.ReaderViewFeature
import mozilla.components.feature.search.SearchFeature
import mozilla.components.feature.session.TrackingProtectionUseCases
import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.tab.collections.TabCollection
import mozilla.components.feature.tabs.WindowFeature
@ -207,11 +206,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
override fun navToTrackingProtectionPanel(session: Session) {
val navController = findNavController()
val useCase = TrackingProtectionUseCases(
sessionManager = requireComponents.core.sessionManager,
engine = requireComponents.core.engine
)
useCase.containsException(session) { contains ->
requireComponents.useCases.trackingProtectionUseCases.containsException(session.id) { contains ->
val isEnabled = session.trackerBlockingEnabled && !contains
val directions =
BrowserFragmentDirections.actionBrowserFragmentToTrackingProtectionPanelDialogFragment(

View File

@ -84,11 +84,7 @@ class TabCollectionStorage(
}
fun removeTabFromCollection(tabCollection: TabCollection, tab: Tab) {
if (tabCollection.tabs.size == 1) {
removeCollection(tabCollection)
} else {
collectionStorage.removeTabFromCollection(tabCollection, tab)
}
collectionStorage.removeTabFromCollection(tabCollection, tab)
}
fun renameCollection(tabCollection: TabCollection, title: String) {

View File

@ -18,6 +18,7 @@ import mozilla.components.feature.pwa.WebAppUseCases
import mozilla.components.feature.search.SearchUseCases
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.session.SettingsUseCases
import mozilla.components.feature.session.TrackingProtectionUseCases
import mozilla.components.feature.tabs.TabsUseCases
import org.mozilla.fenix.utils.Mockable
@ -42,7 +43,7 @@ class UseCases(
/**
* Use cases that provide tab management.
*/
val tabsUseCases: TabsUseCases by lazy { TabsUseCases(sessionManager) }
val tabsUseCases: TabsUseCases by lazy { TabsUseCases(store, sessionManager) }
/**
* Use cases that provide search engine integration.
@ -65,4 +66,6 @@ class UseCases(
val contextMenuUseCases by lazy { ContextMenuUseCases(sessionManager, store) }
val engineSessionUseCases by lazy { EngineSessionUseCases(sessionManager) }
val trackingProtectionUseCases by lazy { TrackingProtectionUseCases(store, engine) }
}

View File

@ -11,7 +11,6 @@ import androidx.core.view.isVisible
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.session.Session
import mozilla.components.concept.engine.manifest.WebAppManifestParser
@ -22,7 +21,6 @@ import mozilla.components.feature.pwa.feature.ManifestUpdateFeature
import mozilla.components.feature.pwa.feature.WebAppActivityFeature
import mozilla.components.feature.pwa.feature.WebAppHideToolbarFeature
import mozilla.components.feature.pwa.feature.WebAppSiteControlsFeature
import mozilla.components.feature.session.TrackingProtectionUseCases
import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
@ -171,11 +169,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler
}
override fun navToTrackingProtectionPanel(session: Session) {
val useCase = TrackingProtectionUseCases(
sessionManager = requireComponents.core.sessionManager,
engine = requireComponents.core.engine
)
useCase.containsException(session) { contains ->
requireComponents.useCases.trackingProtectionUseCases.containsException(session.id) { contains ->
val isEnabled = session.trackerBlockingEnabled && !contains
val directions =
ExternalAppBrowserFragmentDirections

View File

@ -44,10 +44,7 @@ class ExceptionsFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_exceptions, container, false)
trackingProtectionUseCases = TrackingProtectionUseCases(
sessionManager = view.context.components.core.sessionManager,
engine = view.context.components.core.engine
)
trackingProtectionUseCases = view.context.components.useCases.trackingProtectionUseCases
exceptionsStore = StoreProvider.get(this) {
ExceptionsFragmentStore(
ExceptionsFragmentState(

View File

@ -1,29 +0,0 @@
/* 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.ext
import org.mozilla.fenix.search.telemetry.SearchProviderModel
fun SearchProviderModel.containsAds(urlList: List<String>): Boolean {
return urlList.containsAds(this.extraAdServersRegexps)
}
private fun String.isAd(adRegexps: List<String>): Boolean {
for (adsRegex in adRegexps) {
if (Regex(adsRegex).containsMatchIn(this)) {
return true
}
}
return false
}
private fun List<String>.containsAds(adRegexps: List<String>): Boolean {
for (url in this) {
if (url.isAd(adRegexps)) {
return true
}
}
return false
}

View File

@ -13,7 +13,7 @@ import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.navigation.fragment.findNavController
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavHostActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.Components
@ -43,7 +43,7 @@ fun Fragment.getPreferenceKey(@StringRes resourceId: Int): String = getString(re
*/
fun Fragment.showToolbar(title: String) {
(requireActivity() as AppCompatActivity).title = title
(activity as HomeActivity).getSupportActionBarAndInflateIfNecessary().show()
(activity as NavHostActivity).getSupportActionBarAndInflateIfNecessary().show()
}
/**

View File

@ -20,7 +20,6 @@ import android.view.accessibility.AccessibilityEvent
import android.widget.Button
import android.widget.LinearLayout
import android.widget.PopupWindow
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
@ -133,11 +132,11 @@ class HomeFragment : Fragment() {
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) {
scrollAndAnimateCollection(sessions.size)
scrollAndAnimateCollection()
}
override fun onTabsAdded(tabCollection: TabCollection, sessions: List<Session>) {
scrollAndAnimateCollection(sessions.size, tabCollection)
scrollAndAnimateCollection(tabCollection)
}
override fun onCollectionRenamed(tabCollection: TabCollection, title: String) {
@ -218,7 +217,8 @@ class HomeFragment : Fragment() {
sessionControlView = SessionControlView(
view.sessionControlRecyclerView,
sessionControlInteractor,
homeViewModel
homeViewModel,
requireComponents.core.store.state.normalTabs.isNotEmpty()
)
updateSessionControlView(view)
@ -470,11 +470,10 @@ class HomeFragment : Fragment() {
}
}
private fun showDeleteCollectionPrompt(tabCollection: TabCollection) {
private fun showDeleteCollectionPrompt(tabCollection: TabCollection, title: String?, message: String) {
val context = context ?: return
AlertDialog.Builder(context).apply {
val message =
context.getString(R.string.tab_collection_dialog_message, tabCollection.title)
setTitle(title)
setMessage(message)
setNegativeButton(R.string.tab_collection_dialog_negative) { dialog: DialogInterface, _ ->
dialog.cancel()
@ -787,7 +786,6 @@ class HomeFragment : Fragment() {
}
private fun scrollAndAnimateCollection(
tabsAddedToCollectionSize: Int,
changedCollection: TabCollection? = null
) {
if (view != null) {
@ -818,7 +816,7 @@ class HomeFragment : Fragment() {
) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == SCROLL_STATE_IDLE) {
animateCollection(tabsAddedToCollectionSize, indexOfCollection)
animateCollection(indexOfCollection)
recyclerView.removeOnScrollListener(this)
}
}
@ -826,13 +824,13 @@ class HomeFragment : Fragment() {
recyclerView.addOnScrollListener(onScrollListener)
recyclerView.smoothScrollToPosition(indexOfCollection)
} else {
animateCollection(tabsAddedToCollectionSize, indexOfCollection)
animateCollection(indexOfCollection)
}
}
}
}
private fun animateCollection(addedTabsSize: Int, indexOfCollection: Int) {
private fun animateCollection(indexOfCollection: Int) {
viewLifecycleOwner.lifecycleScope.launch {
val viewHolder =
sessionControlView!!.view.findViewHolderForAdapterPosition(indexOfCollection)
@ -859,26 +857,20 @@ class HomeFragment : Fragment() {
?.setDuration(FADE_ANIM_DURATION)
?.setListener(listener)?.start()
}.invokeOnCompletion {
showSavedSnackbar(addedTabsSize)
showSavedSnackbar()
}
}
private fun showSavedSnackbar(tabSize: Int) {
private fun showSavedSnackbar() {
viewLifecycleOwner.lifecycleScope.launch {
delay(ANIM_SNACKBAR_DELAY)
view?.let { view ->
@StringRes
val stringRes = if (tabSize > 1) {
R.string.create_collection_tabs_saved
} else {
R.string.create_collection_tab_saved
}
FenixSnackbar.make(
view = view,
duration = Snackbar.LENGTH_LONG,
isDisplayedWithBrowserToolbar = false
)
.setText(view.context.getString(stringRes))
.setText(view.context.getString(R.string.create_collection_tabs_saved_new_collection))
.setAnchorView(snackbarAnchorView)
.show()
}

View File

@ -108,7 +108,8 @@ class AdapterItemDiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
}
class SessionControlAdapter(
private val interactor: SessionControlInteractor
private val interactor: SessionControlInteractor,
private val hasNormalTabsOpened: Boolean
) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(AdapterItemDiffCallback()) {
// This method triggers the ComplexMethod lint error when in fact it's quite simple.
@ -119,7 +120,8 @@ class SessionControlAdapter(
ButtonTipViewHolder.LAYOUT_ID -> ButtonTipViewHolder(view, interactor)
TopSiteViewHolder.LAYOUT_ID -> TopSiteViewHolder(view, interactor)
PrivateBrowsingDescriptionViewHolder.LAYOUT_ID -> PrivateBrowsingDescriptionViewHolder(view, interactor)
NoCollectionsMessageViewHolder.LAYOUT_ID -> NoCollectionsMessageViewHolder(view, interactor)
NoCollectionsMessageViewHolder.LAYOUT_ID ->
NoCollectionsMessageViewHolder(view, interactor, hasNormalTabsOpened)
CollectionHeaderViewHolder.LAYOUT_ID -> CollectionHeaderViewHolder(view)
CollectionViewHolder.LAYOUT_ID -> CollectionViewHolder(view, interactor)
TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, interactor, differentLastItem = true)

View File

@ -136,7 +136,7 @@ class DefaultSessionControlController(
private val getListOfTabs: () -> List<Tab>,
private val hideOnboarding: () -> Unit,
private val registerCollectionStorageObserver: () -> Unit,
private val showDeleteCollectionPrompt: (tabCollection: TabCollection) -> Unit,
private val showDeleteCollectionPrompt: (tabCollection: TabCollection, title: String?, message: String) -> Unit,
private val openSettingsScreen: () -> Unit,
private val openWhatsNewLink: () -> Unit,
private val openPrivacyNotice: () -> Unit,
@ -196,8 +196,14 @@ class DefaultSessionControlController(
override fun handleCollectionRemoveTab(collection: TabCollection, tab: ComponentTab) {
metrics.track(Event.CollectionTabRemoved)
viewLifecycleScope.launch(Dispatchers.IO) {
tabCollectionStorage.removeTabFromCollection(collection, tab)
if (collection.tabs.size == 1) {
val title = activity.resources.getString(R.string.delete_tab_and_collection_dialog_title, collection.title)
val message = activity.resources.getString(R.string.delete_tab_and_collection_dialog_message)
showDeleteCollectionPrompt(collection, title, message)
} else {
viewLifecycleScope.launch(Dispatchers.IO) {
tabCollectionStorage.removeTabFromCollection(collection, tab)
}
}
}
@ -207,7 +213,8 @@ class DefaultSessionControlController(
}
override fun handleDeleteCollectionTapped(collection: TabCollection) {
showDeleteCollectionPrompt(collection)
val message = activity.resources.getString(R.string.tab_collection_dialog_message, collection.title)
showDeleteCollectionPrompt(collection, null, message)
}
override fun handleOpenInPrivateTabClicked(topSite: TopSite) {

View File

@ -114,12 +114,13 @@ private fun collectionTabItems(collection: TabCollection) = collection.tabs.mapI
class SessionControlView(
override val containerView: View?,
interactor: SessionControlInteractor,
private var homeScreenViewModel: HomeScreenViewModel
private var homeScreenViewModel: HomeScreenViewModel,
private val hasNormalTabsOpened: Boolean
) : LayoutContainer {
val view: RecyclerView = containerView as RecyclerView
private val sessionControlAdapter = SessionControlAdapter(interactor)
private val sessionControlAdapter = SessionControlAdapter(interactor, hasNormalTabsOpened)
init {
view.apply {

View File

@ -5,6 +5,7 @@
package org.mozilla.fenix.home.sessioncontrol.viewholders
import android.view.View
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.no_collections_message.view.*
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.ViewHolder
@ -12,13 +13,15 @@ import org.mozilla.fenix.home.sessioncontrol.CollectionInteractor
open class NoCollectionsMessageViewHolder(
view: View,
interactor: CollectionInteractor
interactor: CollectionInteractor,
hasNormalTabsOpened: Boolean
) : ViewHolder(view) {
init {
view.add_tabs_to_collections_button.setOnClickListener {
interactor.onAddTabsToCollectionTapped()
}
view.add_tabs_to_collections_button.isVisible = hasNormalTabsOpened
}
companion object {
const val LAYOUT_ID = R.layout.no_collections_message

View File

@ -37,7 +37,7 @@ import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.UserInteractionHandler
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavHostActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.StoreProvider
@ -147,7 +147,7 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
override fun onResume() {
super.onResume()
(activity as HomeActivity).getSupportActionBarAndInflateIfNecessary().show()
(activity as NavHostActivity).getSupportActionBarAndInflateIfNecessary().show()
// Reload bookmarks when returning to this fragment in case they have been edited
val args by navArgs<BookmarkFragmentArgs>()

View File

@ -31,7 +31,7 @@ import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import mozilla.components.support.ktx.android.content.getColorFromAttr
import mozilla.components.support.ktx.android.view.hideKeyboard
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavHostActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.metrics.Event
@ -111,15 +111,13 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
}
private fun initToolbar() {
val activity = activity as? AppCompatActivity
val actionBar = (activity as HomeActivity).getSupportActionBarAndInflateIfNecessary()
val activity = activity as AppCompatActivity
val actionBar = (activity as NavHostActivity).getSupportActionBarAndInflateIfNecessary()
val toolbar = activity.findViewById<Toolbar>(R.id.navigationToolbar)
context?.let {
toolbar?.setToolbarColors(
foreground = it.getColorFromAttr(R.attr.primaryText),
background = it.getColorFromAttr(R.attr.foundation)
)
}
toolbar?.setToolbarColors(
foreground = activity.getColorFromAttr(R.attr.primaryText),
background = activity.getColorFromAttr(R.attr.foundation)
)
actionBar.show()
}

View File

@ -101,6 +101,7 @@ class SearchFragment : Fragment(), UserInteractionHandler {
requireComponents.analytics.metrics.track(Event.InteractWithSearchURLArea)
val areShortcutsAvailable = areShortcutsAvailable()
searchStore = StoreProvider.get(this) {
SearchFragmentStore(
SearchFragmentState(
@ -111,7 +112,10 @@ class SearchFragment : Fragment(), UserInteractionHandler {
defaultEngineSource = currentSearchEngine,
showSearchSuggestions = shouldShowSearchSuggestions(isPrivate),
showSearchSuggestionsHint = false,
showSearchShortcuts = requireContext().settings().shouldShowSearchShortcuts && url.isEmpty(),
showSearchShortcuts = requireContext().settings().shouldShowSearchShortcuts &&
url.isEmpty() &&
areShortcutsAvailable,
areShortcutsAvailable = areShortcutsAvailable,
showClipboardSuggestions = requireContext().settings().shouldShowClipboardSuggestions,
showHistorySuggestions = requireContext().settings().shouldShowHistorySuggestions,
showBookmarkSuggestions = requireContext().settings().shouldShowBookmarkSuggestions,
@ -334,6 +338,12 @@ class SearchFragment : Fragment(), UserInteractionHandler {
)
}
// Users can from this fragment go to install/uninstall search engines and then return.
val areShortcutsAvailable = areShortcutsAvailable()
if (searchStore.state.areShortcutsAvailable != areShortcutsAvailable) {
searchStore.dispatch(SearchFragmentAction.UpdateShortcutsAvailability(areShortcutsAvailable))
}
if (!permissionDidUpdate) {
toolbarView.view.edit.focus()
}
@ -431,6 +441,8 @@ class SearchFragment : Fragment(), UserInteractionHandler {
private fun updateSearchShortcutsIcon(searchState: SearchFragmentState) {
view?.apply {
search_shortcuts_button.isVisible = searchState.areShortcutsAvailable
val showShortcuts = searchState.showSearchShortcuts
search_shortcuts_button.isChecked = showShortcuts
@ -441,7 +453,16 @@ class SearchFragment : Fragment(), UserInteractionHandler {
}
}
/**
* Return if the user has *at least 2* installed search engines.
* Useful to decide whether to show / enable certain functionalities.
*/
private fun areShortcutsAvailable() =
requireContext().components.search.provider.installedSearchEngines(requireContext())
.list.size >= MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS
companion object {
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
private const val MINIMUM_SEARCH_ENGINES_NUMBER_TO_SHOW_SHORTCUTS = 2
}
}

View File

@ -41,6 +41,8 @@ sealed class SearchEngineSource {
* @property showSearchSuggestions Whether or not to show search suggestions from the search engine in the AwesomeBar
* @property showSearchSuggestionsHint Whether or not to show search suggestions in private hint panel
* @property showSearchShortcuts Whether or not to show search shortcuts in the AwesomeBar
* @property areShortcutsAvailable Whether or not there are >=2 search engines installed
* so to know to present users with certain options or not.
* @property showClipboardSuggestions Whether or not to show clipboard suggestion in the AwesomeBar
* @property showHistorySuggestions Whether or not to show history suggestions in the AwesomeBar
* @property showBookmarkSuggestions Whether or not to show the bookmark suggestion in the AwesomeBar
@ -55,6 +57,7 @@ data class SearchFragmentState(
val showSearchSuggestions: Boolean,
val showSearchSuggestionsHint: Boolean,
val showSearchShortcuts: Boolean,
val areShortcutsAvailable: Boolean,
val showClipboardSuggestions: Boolean,
val showHistorySuggestions: Boolean,
val showBookmarkSuggestions: Boolean,
@ -71,6 +74,7 @@ sealed class SearchFragmentAction : Action {
data class SearchShortcutEngineSelected(val engine: SearchEngine) : SearchFragmentAction()
data class SelectNewDefaultSearchEngine(val engine: SearchEngine) : SearchFragmentAction()
data class ShowSearchShortcutEnginePicker(val show: Boolean) : SearchFragmentAction()
data class UpdateShortcutsAvailability(val areShortcutsAvailable: Boolean) : SearchFragmentAction()
data class AllowSearchSuggestionsInPrivateModePrompt(val show: Boolean) : SearchFragmentAction()
data class UpdateQuery(val query: String) : SearchFragmentAction()
}
@ -86,7 +90,9 @@ private fun searchStateReducer(state: SearchFragmentState, action: SearchFragmen
showSearchShortcuts = false
)
is SearchFragmentAction.ShowSearchShortcutEnginePicker ->
state.copy(showSearchShortcuts = action.show)
state.copy(showSearchShortcuts = action.show && state.areShortcutsAvailable)
is SearchFragmentAction.UpdateShortcutsAvailability ->
state.copy(areShortcutsAvailable = action.areShortcutsAvailable)
is SearchFragmentAction.UpdateQuery ->
state.copy(query = action.query)
is SearchFragmentAction.SelectNewDefaultSearchEngine ->

View File

@ -82,14 +82,8 @@ abstract class BaseSearchTelemetry {
abstract fun install(engine: Engine, store: BrowserStore)
internal fun getProviderForUrl(url: String): SearchProviderModel? {
for (provider in providerList) {
if (Regex(provider.regexp).containsMatchIn(url)) {
return provider
}
}
return null
}
internal fun getProviderForUrl(url: String): SearchProviderModel? =
providerList.find { provider -> provider.regexp.containsMatchIn(url) }
internal fun installWebExtension(
engine: Engine,

View File

@ -6,11 +6,41 @@ package org.mozilla.fenix.search.telemetry
data class SearchProviderModel(
val name: String,
val regexp: String,
val regexp: Regex,
val queryParam: String,
val codeParam: String = "",
val codePrefixes: List<String> = ArrayList(),
val followOnParams: List<String> = ArrayList(),
val extraAdServersRegexps: List<String> = ArrayList(),
val followOnCookies: List<SearchProviderCookie> = ArrayList()
)
val codeParam: String,
val codePrefixes: List<String>,
val followOnParams: List<String>,
val extraAdServersRegexps: List<Regex>,
val followOnCookies: List<SearchProviderCookie>
) {
constructor(
name: String,
regexp: String,
queryParam: String,
codeParam: String = "",
codePrefixes: List<String> = emptyList(),
followOnParams: List<String> = emptyList(),
extraAdServersRegexps: List<String> = emptyList(),
followOnCookies: List<SearchProviderCookie> = emptyList()
) : this(
name = name,
regexp = regexp.toRegex(),
queryParam = queryParam,
codeParam = codeParam,
codePrefixes = codePrefixes,
followOnParams = followOnParams,
extraAdServersRegexps = extraAdServersRegexps.map { it.toRegex() },
followOnCookies = followOnCookies
)
/**
* Checks if any of the given URLs represent an ad from the search engine.
* Used to check if a clicked link was for an ad.
*/
fun containsAds(urlList: List<String>) = urlList.any { url -> isAd(url) }
private fun isAd(url: String) =
extraAdServersRegexps.any { adsRegex -> adsRegex.containsMatchIn(url) }
}

View File

@ -10,7 +10,6 @@ import mozilla.components.concept.engine.Engine
import org.json.JSONObject
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.containsAds
import org.mozilla.fenix.search.telemetry.BaseSearchTelemetry
import org.mozilla.fenix.search.telemetry.ExtensionInfo

View File

@ -14,7 +14,6 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
@ -36,6 +35,7 @@ import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.searchengine.CustomSearchEngineStore
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.SupportUtils
import java.util.Locale
@ -93,7 +93,7 @@ class AddSearchEngineFragment : Fragment(), CompoundButton.OnCheckedChangeListen
availableEngines.forEachIndexed(setupSearchEngineItem)
val engineItem = makeCustomButton(layoutInflater)
val engineItem = makeCustomButton(layoutInflater, res = resources)
engineItem.id = CUSTOM_INDEX
engineItem.radio_button.isChecked = selectedIndex == CUSTOM_INDEX
engineViews.add(engineItem)
@ -115,8 +115,7 @@ class AddSearchEngineFragment : Fragment(), CompoundButton.OnCheckedChangeListen
override fun onResume() {
super.onResume()
(activity as AppCompatActivity).title = getString(R.string.search_engine_add_custom_search_engine_title)
(activity as HomeActivity).getSupportActionBarAndInflateIfNecessary().show()
showToolbar(getString(R.string.search_engine_add_custom_search_engine_title))
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@ -250,11 +249,12 @@ class AddSearchEngineFragment : Fragment(), CompoundButton.OnCheckedChangeListen
toggleCustomForm(selectedIndex == -1)
}
private fun makeCustomButton(layoutInflater: LayoutInflater): View {
private fun makeCustomButton(layoutInflater: LayoutInflater, res: Resources): View {
val wrapper = layoutInflater
.inflate(R.layout.custom_search_engine_radio_button, null) as ConstraintLayout
wrapper.setOnClickListener { wrapper.radio_button.isChecked = true }
wrapper.radio_button.setOnCheckedChangeListener(this)
wrapper.minHeight = res.getDimensionPixelSize(R.dimen.radio_button_preference_height)
return wrapper
}
@ -280,6 +280,7 @@ class AddSearchEngineFragment : Fragment(), CompoundButton.OnCheckedChangeListen
engineIcon.setBounds(0, 0, iconSize, iconSize)
wrapper.engine_icon.setImageDrawable(engineIcon)
wrapper.overflow_menu.visibility = View.GONE
wrapper.minHeight = res.getDimensionPixelSize(R.dimen.radio_button_preference_height)
return wrapper
}

View File

@ -28,7 +28,7 @@ import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import mozilla.components.feature.sitepermissions.SitePermissions
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.NavHostActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.loadIntoView
@ -44,7 +44,7 @@ class SitePermissionsExceptionsFragment :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(activity as HomeActivity).getSupportActionBarAndInflateIfNecessary().show()
(activity as NavHostActivity).getSupportActionBarAndInflateIfNecessary().show()
}
override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {

View File

@ -51,11 +51,11 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) {
showCollectionSnackbar()
showCollectionSnackbar(sessions.size, true)
}
override fun onTabsAdded(tabCollection: TabCollection, sessions: List<Session>) {
showCollectionSnackbar()
showCollectionSnackbar(sessions.size)
}
}
@ -245,8 +245,19 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
}
}
private fun showCollectionSnackbar() {
private fun showCollectionSnackbar(tabSize: Int, isNewCollection: Boolean = false) {
view.let {
val messageStringRes = when {
isNewCollection -> {
R.string.create_collection_tabs_saved_new_collection
}
tabSize > 1 -> {
R.string.create_collection_tabs_saved
}
else -> {
R.string.create_collection_tab_saved
}
}
val snackbar = FenixSnackbar
.make(
duration = FenixSnackbar.LENGTH_LONG,
@ -254,7 +265,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
view = (view as View)
)
.setAnchorView(snackbarAnchor)
.setText(requireContext().getString(R.string.create_collection_tabs_saved))
.setText(requireContext().getString(messageStringRes))
.setAction(requireContext().getString(R.string.create_collection_view)) {
dismissAllowingStateLoss()
findNavController().navigate(

View File

@ -61,11 +61,7 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val components = requireComponents
trackingProtectionUseCases = TrackingProtectionUseCases(
sessionManager = components.core.sessionManager,
engine = components.core.engine
)
trackingProtectionUseCases = requireComponents.useCases.trackingProtectionUseCases
}
override fun onCreateView(
@ -115,7 +111,7 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
private fun updateTrackers(session: Session) {
trackingProtectionUseCases.fetchTrackingLogs(
session,
session.id,
onSuccess = {
trackingProtectionStore.dispatch(TrackingProtectionAction.TrackerLogChange(it))
},
@ -150,10 +146,10 @@ class TrackingProtectionPanelDialogFragment : AppCompatDialogFragment(), UserInt
val session = context.components.core.sessionManager.findSessionById(args.sessionId)
session?.let {
if (isEnabled) {
trackingProtectionUseCases.removeException(it)
trackingProtectionUseCases.removeException(it.id)
} else {
context.metrics.track(Event.TrackingProtectionException)
trackingProtectionUseCases.addException(it)
trackingProtectionUseCases.addException(it.id)
}
with(context.components) {

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
@ -10,7 +13,6 @@
android:id="@+id/locale_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="@dimen/locale_list_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@ -29,6 +29,7 @@
android:id="@+id/edit_engine_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/accessibility_min_height"
android:hint="@string/search_add_custom_engine_name_hint"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
@ -46,6 +47,7 @@
android:id="@+id/edit_search_string"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/accessibility_min_height"
android:hint="@string/search_add_custom_engine_search_string_hint"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>

View File

@ -20,7 +20,8 @@
android:textAppearance="?android:attr/textAppearanceListItem"
android:layout_marginStart="@dimen/search_bar_search_engine_icon_padding"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/engine_text"
android:textColor="?primaryText"
@ -29,8 +30,9 @@
android:layout_marginStart="@dimen/search_bar_search_icon_margin"
android:layout_marginEnd="@dimen/radio_button_padding_horizontal"
android:text="@string/search_add_custom_engine_label_other"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@id/radio_button"
app:layout_constraintTop_toTopOf="@id/radio_button"
app:layout_constraintBottom_toBottomOf="@id/radio_button"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"

View File

@ -1,19 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="48dp">
<ImageView
android:id="@+id/locale_selected_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/locale_item_vertical_margin"
android:layout_marginBottom="@dimen/locale_item_vertical_margin"
android:layout_marginStart="@dimen/locale_list_margin"
android:contentDescription="@string/a11y_selected_locale_content_description"
app:srcCompat="@drawable/mozac_ic_check"
android:tint="?primaryText"
android:visibility="gone"
app:tint="?primaryText"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -23,7 +26,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/locale_item_text_margin_start"
android:layout_marginTop="@dimen/locale_item_vertical_margin"
android:layout_marginEnd="@dimen/locale_item_text_margin_end"
android:textColor="?primaryText"
android:textAlignment="viewStart"
app:layout_goneMarginStart="@dimen/locale_item_text_margin_gone_start"
@ -33,22 +36,24 @@
app:layout_constraintStart_toEndOf="@+id/locale_selected_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
app:layout_goneMarginBottom="@dimen/locale_item_vertical_margin" />
tools:text="English (United States)" />
<TextView
android:id="@+id/locale_subtitle_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/locale_item_text_margin_start"
android:layout_marginBottom="@dimen/locale_item_vertical_margin"
android:layout_marginEnd="@dimen/locale_item_text_margin_end"
android:textColor="?secondaryText"
android:textAlignment="viewStart"
android:textSize="@dimen/locale_item_subtitle_size"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_goneMarginStart="@dimen/locale_item_text_margin_gone_start"
app:layout_constraintStart_toEndOf="@+id/locale_selected_icon"
app:layout_constraintTop_toBottomOf="@+id/locale_title_text"
app:layout_constraintVertical_chainStyle="packed" />
app:layout_constraintVertical_chainStyle="packed"
tools:text="English (United States)" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/title"
style="?android:attr/listViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/listViewStyle"
android:layout_marginTop="16dp"
android:textAlignment="viewStart"
android:layout_marginStart="72dp"
android:layout_marginTop="16dp"
android:gravity="start|center_vertical"
app:fontFamily="@font/metropolis_semibold"
android:id="@android:id/title" />
android:textAlignment="viewStart"
app:fontFamily="@font/metropolis_semibold" />

View File

@ -29,6 +29,7 @@
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_marginStart="8dp"
android:layout_height="wrap_content"
android:gravity="center|start"
android:layout_marginEnd="@dimen/radio_button_preference_horizontal"

View File

@ -3,8 +3,8 @@
- 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/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/synced_tabs_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -12,17 +12,19 @@
<TextView
android:id="@+id/synced_tabs_group_name"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:drawablePadding="32dp"
android:gravity="center_vertical|start"
android:textAppearance="@style/Header14TextStyle"
android:textColor="?primaryText"
android:textSize="12sp"
android:gravity="center"
app:drawableStartCompat="@drawable/mozac_ic_device_desktop"
app:drawableTint="?primaryText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Header" />

View File

@ -807,6 +807,9 @@
<string name="tip_firefox_preview_moved_description">Firefox Nightly anuévase cada nueche y tien carauterístiques esperimentales.
Por embargu, ye menos estable. Baxa la versión beta del restolador pa una esperiencia más estable.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Consiguir Firefox Beta p\'Android</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly mudó</string>
<!-- text for firefox preview moving tip description -->
@ -819,6 +822,9 @@
<string name="tip_firefox_preview_moved_description_preview_not_installed">Dexa d\'usar esta aplicación darréu que nun va recibir más anovamientos de seguranza. Consigui la versión nueva de Nightly.
\n\nPa tresferir los marcadores, anicios de sesión y l\'historial a otra aplicación, crea una cuenta de Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_not_installed">Consiguir el Nightly nuevu</string>
<!-- Onboarding -->
<!-- Text for onboarding welcome message
The first parameter is the name of the app (e.g. Firefox Preview) -->

View File

@ -698,6 +698,8 @@
<!-- Confirmation dialog button -->
<string name="sync_confirmation_button">Зразумела</string>
<!-- Share error message -->
<string name="share_error_snackbar">Немагчыма падзяліцца гэтай праграмай</string>
<!-- Add new device screen title -->
<string name="sync_add_new_device_title">Даслаць на прыладу</string>
<!-- Text for the warning message on the Add new device screen -->
@ -751,6 +753,9 @@
<string name="a11y_dialog_deleted_undo">Адмяніць</string>
<!-- Text for action to confirm deleting a tab or collection shown in a11y dialog -->
<string name="a11y_dialog_deleted_confirm">Пацвердзіць</string>
<!-- QR code scanner prompt which appears after scanning a code, but before navigating to it
First parameter is the name of the app, second parameter is the URL or text scanned-->
<string name="qr_scanner_confirmation_dialog_message">Дазволіць %1$s адкрыць %2$s</string>
<!-- QR code scanner prompt dialog positive option to allow navigation to scanned link -->
<string name="qr_scanner_dialog_positive">ДАЗВОЛІЦЬ</string>
<!-- QR code scanner prompt dialog positive option to deny navigation to scanned link -->
@ -766,12 +771,18 @@
<!-- Message for copying the URL via long press on the toolbar -->
<string name="url_copied">URL скапіраваны</string>
<!-- Sample text for accessibility font size -->
<string name="accessibility_text_size_sample_text_1">Гэта ўзор тэксту. Ён тут, каб паказаць, як тэкст будзе выглядаць пры павелічэнні або памяншэнні памеру з дапамогай гэтай налады.</string>
<!-- Summary for Accessibility Text Size Scaling Preference -->
<string name="preference_accessibility_text_size_summary">Зрабіць тэкст на сайтах большым ці меншым</string>
<!-- Title for Accessibility Text Size Scaling Preference -->
<string name="preference_accessibility_font_size_title">Памер шрыфту</string>
<!-- Title for Accessibility Text Automatic Size Scaling Preference -->
<string name="preference_accessibility_auto_size_2">Аўтаматычны памер шрыфту</string>
<!-- Title for the Delete browsing data preference -->
<string name="preferences_delete_browsing_data">Выдаліць дадзеныя аглядання</string>
<!-- Title for the tabs item in Delete browsing data -->
<string name="preferences_delete_browsing_data_tabs_title_2">Адкрытыя карткі</string>
<!-- Subtitle for the tabs item in Delete browsing data, parameter will be replaced with the number of open tabs -->
@ -788,12 +799,18 @@
<string name="preferences_delete_browsing_data_browsing_history_subtitle">Старонак: %d</string>
<!-- Title for the cookies item in Delete browsing data -->
<string name="preferences_delete_browsing_data_cookies">Кукі</string>
<!-- Subtitle for the cookies item in Delete browsing data -->
<string name="preferences_delete_browsing_data_cookies_subtitle">Вы выйдзеце з большасці сайтаў</string>
<!-- Title for the cached images and files item in Delete browsing data -->
<string name="preferences_delete_browsing_data_cached_files">Кэшаваныя відарысы і файлы</string>
<!-- Title for the site permissions item in Delete browsing data -->
<string name="preferences_delete_browsing_data_site_permissions">Дазволы для сайтаў</string>
<!-- Text for the button to delete browsing data -->
<string name="preferences_delete_browsing_data_button">Выдаліць звесткі аглядання</string>
<!-- Title for the Delete browsing data on quit preference -->
<string name="preferences_delete_browsing_data_on_quit">Выдаляць звесткі аглядання пры выхадзе</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit">Аўтаматычна выдаляе дадзеныя аглядання, калі вы выбіраеце &quot;Выйсці&quot; ў галоўным меню</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Выйсці</string>
@ -802,6 +819,15 @@
<!-- Text for the allow button for the data deletion dialog -->
<string name="delete_browsing_data_prompt_allow">Выдаліць</string>
<!-- Text for the snackbar confirmation that the data was deleted -->
<string name="preferences_delete_browsing_data_snackbar">Дадзеныя аглядання выдалены</string>
<!-- Tips -->
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox Preview цяпер Firefox Nightly</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">Firefox Nightly абнаўляецца кожную ноч і мае новыя эксперыментальныя магчымасці.
Аднак ён можа быць менш стабільным. Сцягніце нашу бэта-версію для больш стабільнай працы.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Атрымаць Firefox для Android Beta</string>
@ -835,8 +861,14 @@
<!-- text for the firefox account onboarding card header
The first parameter is the name of the app (e.g. Firefox Preview) -->
<string name="onboarding_firefox_account_header">Атрымайце максімум ад %s.</string>
<!-- text for the button to confirm automatic sign-in -->
<string name="onboarding_firefox_account_auto_signin_confirm">Так, увайсці</string>
<!-- text for the automatic sign-in button while signing in is in process -->
<string name="onboarding_firefox_account_signing_in">Уваход…</string>
<!-- text for the button to manually sign into Firefox account. The word "Firefox" should not be translated -->
<string name="onboarding_firefox_account_sign_in">Увайсці ў Firefox</string>
<!-- text for the button to stay signed out when presented with an option to automatically sign-in. -->
<string name="onboarding_firefox_account_stay_signed_out">Не ўваходзіць</string>
<!-- text to display in the snackbar once account is signed-in -->
<string name="onboarding_firefox_account_sync_is_on">Сінхранізацыя ўключана</string>
<!-- text to display in the snackbar if automatic sign-in fails. user may try again -->
@ -940,6 +972,8 @@
<string name="preference_enhanced_tracking_protection_explanation_learn_more">Даведацца больш</string>
<!-- Preference for enhanced tracking protection for the standard protection settings -->
<string name="preference_enhanced_tracking_protection_standard_default_1">Стандартная (прадвызначана)</string>
<!-- Preference description for enhanced tracking protection for the standard protection settings -->
<string name="preference_enhanced_tracking_protection_standard_description_3">Блакуе менш трэкераў. Старонкі загружаюцца нармальна.</string>
<!-- Accessibility text for the Standard protection information icon -->
<string name="preference_enhanced_tracking_protection_standard_info_button">Што блакуецца стандартнай аховай ад сачэння</string>
<!-- Preference for enhanced tracking protection for the strict protection settings -->
@ -1149,6 +1183,13 @@
<!-- Text shown when a user leaves the name field empty -->
<string name="search_add_custom_engine_error_empty_name">Увядзіце назву пошукавай сістэмы</string>
<!-- Text shown when a user leaves the search string field empty -->
<string name="search_add_custom_engine_error_empty_search_string">Увядзіце радок пошуку</string>
<!-- Text on the disabled button while in progress. Placeholder replaced with app name -->
<string name="migration_updating_app_button_text">Абнаўленне %s…</string>
<!-- Text on the enabled button. Placeholder replaced with app name-->
<string name="migration_update_app_button">Запусціць %s</string>
<!-- Accessibility description text for a completed migration item -->
<string name="migration_icon_description">Міграцыя завершана</string>
<!--Text on list of migrated items (e.g. Settings, History, etc.)-->
@ -1184,6 +1225,10 @@
<string name="login_deletion_confirmation">Вы сапраўды хочаце выдаліць гэтае лагін?</string>
<!-- Positive action of a dialog asking to delete -->
<string name="dialog_delete_positive">Выдаліць</string>
<!-- The editable text field for a login's web address. -->
<string name="saved_login_hostname_description">Тэкставае поле для рэдагавання вэб-адраса для ўваходу ў сістэму.</string>
<!-- The editable text field for a login's username. -->
<string name="saved_login_username_description">Тэкставае поле для рэдагавання імені карыстальніка для ўваходу ў сістэму.</string>
<!-- The error message in edit login view when password field is blank. -->
<string name="saved_login_password_required">Патрабуецца пароль</string>
<!-- Voice search button content description -->

View File

@ -914,7 +914,7 @@
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">Mae Firefox Nightly wedi symud</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_installed">Ni fydd yr ap hon yn derbyn diweddariadau diogelwch mwyach. Peidiwch a defnyddior ap hon a symud ir Nightly newydd.
<string name="tip_firefox_preview_moved_description_preview_installed">Ni fydd yr ap hwn yn derbyn diweddariadau diogelwch mwyach. Peidiwch â defnyddior ap hwn a newidiwch ir Nightly newydd.
\n\nEr mwyn trosglwyddoch nodau tudalen, eich mewngofnodion ach hanes i ap arall, crëwch gyfrif Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_installed">Newid ir Nightly newydd</string>
@ -922,7 +922,7 @@
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_not_installed">Mae Firefox Nightly wedi symud</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_not_installed">Ni fydd yr ap hon yn derbyn diweddariadau diogelwch bellach. Estynnwch y Nightly newydd a pheidio a defnyddior ap hon.
<string name="tip_firefox_preview_moved_description_preview_not_installed">Ni fydd yr ap hwn yn derbyn diweddariadau diogelwch bellach. Estynnwch y Nightly newydd a pheidio â defnyddior ap hwn bellach.
\n\nEr mwyn trosglwyddoch nodau tudalen, eich mewngofnodion ach hanes i ap arall, crëwch gyfrif Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_not_installed">Estyn y Nightly newydd</string>

View File

@ -908,8 +908,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">Elimina automáticamente los datos de navegación cuando seleccionás &quot;Salir&quot; en el menú principal</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">Elimina automáticamente los datos de navegación cuando seleccionás &quot;Salir&quot; en el menú principal</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">Historial de navegación</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Salir</string>
@ -931,25 +929,22 @@
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox Nightly ahora es Firefox Preview</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">Firefox Nightly se actualiza todas las noches y tiene nuevas funciones experimentales.
        Sin embargo, puede ser menos estable. Descargá nuestro navegador beta para una experiencia más estable.</string>
<string name="tip_firefox_preview_moved_description">Firefox Nightly se actualiza todas las noches y tiene nuevas funciones experimentales.  Sin embargo, puede ser menos estable. Para una experiencia más estable descargá nuestro navegador beta.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Obtené Firefox para Android Beta</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly se mov</string>
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly camb</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_installed">Esta aplicación ya no va arecibir actualizaciones de seguridad. Deja de usar la y cambiá al nuevo Nightly.
        \ n \ nPara transferir tus marcadores, inicios de sesión e historial a otra aplicación, creá una cuenta de Firefox.</string>
<string name="tip_firefox_preview_moved_description_preview_installed">Esta aplicación ya no va a recibir actualizaciones de seguridad. Dejá de usarla y cambiá al nuevo Nightly. Para transferir tus marcadores, inicios de sesión e historial a otra aplicación, creá una cuenta de Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_installed">Cambiá al nuevo Nightly</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_not_installed">Firefox Nightly se mov</string>
<string name="tip_firefox_preview_moved_header_preview_not_installed">Firefox Nightly camb</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_not_installed">Esta aplicación ya no va a recibir actualizaciones de seguridad. Deja de usarla y cambiá al nuevo Nightly.
        \ n \ nPara transferir tus marcadores, inicios de sesión e historial a otra aplicación, creá una cuenta de Firefox.</string>
<string name="tip_firefox_preview_moved_description_preview_not_installed">Esta aplicación ya no va a recibir actualizaciones de seguridad. Deja de usarla y cambiá al nuevo Nightly. Para transferir tus marcadores, inicios de sesión e historial a otra aplicación, creá una cuenta de Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_not_installed">Obtené el nuevo Nightly</string>

View File

@ -892,8 +892,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">Automatski briše podatke pregledavanja kad u glavnom izborniku odabereš „Zatvori”</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">Automatski briše podatke pregledavanja kad u glavnom izborniku odabereš „Zatvori”</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">Povijest pregledavanja</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Zatvori</string>
@ -915,8 +913,8 @@
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox pregled je sada Firefox Nightly</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">Firefox Nightly se aktualizira svake večeri i sadrži nove eksperimentalne funkcije.
        Međutim, vjerojatno je manje stabilna verzija. Preuzmi naš beta preglednik za stabilnije iskustvo.</string>
<string name="tip_firefox_preview_moved_description">Firefox Nightly je aktualiziran svake noći i sadrži nove eksperimentalne značajke.
Međutim, Nightly može biti manje stabilan. Preuzmi beta verziju našeg preglednika za stabilnije iskustvo.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Preuzmite Firefox za Android Beta</string>

View File

@ -1107,7 +1107,7 @@
<!-- Accessibility text for the Standard protection information icon -->
<string name="preference_enhanced_tracking_protection_standard_info_button">Elementi bloccati nella protezione antitracciamento normale</string>
<!-- Preference for enhanced tracking protection for the strict protection settings -->
<string name="preference_enhanced_tracking_protection_strict">Restrittivo</string>
<string name="preference_enhanced_tracking_protection_strict">Restrittiva</string>
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
<string name="preference_enhanced_tracking_protection_strict_description_2">Blocca più elementi traccianti, annunci pubblicitari e pop-up. Le pagine verranno caricate più velocemente, ma alcuni elementi potrebbero non funzionare correttamente.</string>
<!-- Accessibility text for the Strict protection information icon -->

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App name for private browsing mode. The first parameter is the name of the app defined in app_name (for example: Fenix)-->
<string name="app_name_private_5">Privou %s</string>
<!-- App name for private browsing mode. The first parameter is the name of the app defined in app_name (for example: Fenix)-->
<string name="app_name_private_4">%s (Privou)</string>
<!-- Home Fragment -->
<!-- Content description (not visible, for screen readers etc.): "Three dot" menu button. -->
<string name="content_description_menu">Ciù inpostaçioin</string>
<!-- Content description (not visible, for screen readers etc.): "Private Browsing" menu button. -->
<string name="content_description_private_browsing_button">Abilita Navegaçion privâ</string>
<!-- Content description (not visible, for screen readers etc.): "Private Browsing" menu button. -->
<string name="content_description_disable_private_browsing_button">Dizabilita Navegaçion privâ</string>
<!-- Placeholder text shown in the search bar before a user enters text -->
<string name="search_hint">Scrivi ò çerca indirisso</string>
<!-- Text for the negative button -->
<string name="cfr_neg_button_text">No graçie</string>
<!-- Text for the positive button -->
<string name="search_widget_cfr_pos_button_text">Azonzi widget</string>
<!-- Text for the negative button -->
<string name="search_widget_cfr_neg_button_text">Oua no</string>
<!-- Home screen icons - Long press shortcuts -->
<!-- Shortcut action to open new tab -->
<string name="home_screen_shortcut_open_new_tab_2">Neuvo feuggio</string>
<!-- Shortcut action to open new private tab -->
<string name="home_screen_shortcut_open_new_private_tab_2">Neuvo feuggio privou</string>
<!-- Heading for the Top Sites block -->
<string name="home_screen_top_sites_heading">I megio sciti</string>
<!-- Browser Fragment -->
<!-- Content description (not visible, for screen readers etc.): Navigate to open tabs -->
<string name="browser_tabs_button">Arvi Feuggi</string>
<!-- Content description (not visible, for screen readers etc.): Navigate backward (browsing history) -->
<string name="browser_menu_back">Inderê</string>
<!-- Content description (not visible, for screen readers etc.): Navigate forward (browsing history) -->
<string name="browser_menu_forward"></string>
<!-- Content description (not visible, for screen readers etc.): Refresh current website -->
<string name="browser_menu_refresh">Agiorna</string>
<!-- Content description (not visible, for screen readers etc.): Stop loading current website -->
<string name="browser_menu_stop">Ferma</string>
<!-- Content description (not visible, for screen readers etc.): Bookmark the current page -->
<string name="browser_menu_bookmark">Segnalibbro</string>
<!-- Content description (not visible, for screen readers etc.): Un-bookmark the current page -->
<string name="browser_menu_edit_bookmark">Cangia segnalibbro</string>
<!-- Browser menu button that opens the addon manager -->
<string name="browser_menu_add_ons">Conponenti azonti</string>
<!-- Browser menu button that sends a user to help articles -->
<string name="browser_menu_help">Agiutto</string>
<!-- Browser menu button that sends a to a the what's new article -->
<string name="browser_menu_whats_new">Cöse gh\'é de neuvo</string>
<!-- Browser menu button that opens the settings menu -->
<string name="browser_menu_settings">Inpostaçioin</string>
<!-- Browser menu button that opens a user's library -->
<string name="browser_menu_library">Libraia</string>
<!-- Browser menu toggle that requests a desktop site -->
<string name="browser_menu_desktop_site">Scito desktop</string>
<!-- Browser menu toggle that adds a shortcut to the site on the device home screen. -->
<string name="browser_menu_add_to_homescreen">Azonzi a-a Pagina Prinçipâ</string>
<!-- Browser menu toggle that installs a Progressive Web App shortcut to the site on the device home screen. -->
<string name="browser_menu_install_on_homescreen">Installa</string>
<!-- Menu option on the toolbar that takes you to synced tabs page-->
<string name="synced_tabs"></string>
<!-- Browser menu button that opens the find in page menu -->
<string name="browser_menu_find_in_page">Treuva in pagina</string>
<!-- Browser menu button that creates a private tab -->
<string name="browser_menu_private_tab">Feuggio privou</string>
<!-- Browser menu button that creates a new tab -->
<string name="browser_menu_new_tab">Neuvo feuggio</string>
<!-- Browser menu button that open a share menu to share the current site -->
<string name="browser_menu_share">Condividdi</string>
<!-- Share menu title, displayed when a user is sharing their current site -->
<string name="menu_share_with">Condividdi con…</string>
<!-- Browser menu button shown in custom tabs that opens the current tab in Fenix
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
<string name="browser_menu_open_in_fenix">Arvi in %1$s</string>
<!-- Browser menu text shown in custom tabs to indicate this is a Fenix tab
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
<string name="browser_menu_powered_by">FÆTO CON %1$s</string>
<!-- Browser menu text shown in custom tabs to indicate this is a Fenix tab
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
<string name="browser_menu_powered_by2">Tecnologia de %s</string>
<!-- Browser menu button to put the current page in reader mode -->
<string name="browser_menu_read">Mòddo letua</string>
<!-- Browser menu button content description to close reader mode and return the user to the regular browser -->
<string name="browser_menu_read_close">Særa modalitæ letua</string>
<!-- Browser menu button to open the current page in an external app -->
<string name="browser_menu_open_app_link">Arvi in app</string>
<!-- Browser menu button to configure reader mode appearance e.g. the used font type and size -->
<string name="browser_menu_read_appearance">Aparensa</string>
<!-- Locale Settings Fragment -->
<!-- Content description for tick mark on selected language -->
<string name="a11y_selected_locale_content_description">Seleçionn-a lengoa</string>
<!-- Content description for search icon -->
<string name="a11y_search_icon_content_description">Çerca</string>
<!-- Text for default locale item -->
<string name="default_locale_text">Deuvia lengoa do dispoxitivo</string>
<!-- Placeholder text shown in the search bar before a user enters text -->
<string name="locale_search_hint">Çerca lengoa</string>
<!-- Search Fragment -->
<!-- Button in the search view that lets a user search by scanning a QR code -->
<string name="search_scan_button">Scanscionn-a</string>
<!-- Button in the search view that lets a user search by using a shortcut -->
<string name="search_shortcuts_button">Scorsaiéu</string>
<!-- DEPRECATED: Header displayed when selecting a shortcut search engine -->
<string name="search_shortcuts_search_with">Çerca con</string>
<!-- Button in the search suggestions onboarding that allows search suggestions in private sessions -->
<string name="search_suggestions_onboarding_allow_button">Permetti</string>
<!-- Button in the search suggestions onboarding that does not allow search suggestions in private sessions -->
<string name="search_suggestions_onboarding_do_not_allow_button">No permette</string>
<!-- Search suggestion onboarding hint Learn more link text -->
<string name="search_suggestions_onboarding_learn_more_link">Atre informaçioin</string>
<!-- Search Widget -->
<!-- Text preview for smaller sized widgets -->
<string name="search_widget_text_short">Çerca</string>
<!-- Text preview for larger sized widgets -->
<string name="search_widget_text_long">Çerca inta ræ</string>
<!-- Content description (not visible, for screen readers etc.): Voice search -->
<string name="search_widget_voice">Çerca co-a voxe</string>
<!-- Preferences -->
<!-- Title for the settings page-->
<string name="settings">Inpostaçioin</string>
<!-- Preference category for basic settings -->
<string name="preferences_category_basics">Generale</string>
</resources>

File diff suppressed because one or more lines are too long

View File

@ -894,8 +894,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">Sletter nettlesardata automatisk når du vel «Avslutt» frå hovudmenyen</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">Slettar nettlesardata automatisk når du vel «Avslutt» frå hovudmenyen</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">Nettlesarhistorikk</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Avslutt</string>
@ -980,17 +978,17 @@
<string name="onboarding_tracking_protection_header_2">Automatisk personvern</string>
<!-- text for the tracking protection card description
The first parameter is the name of the app (e.g. Firefox Preview) -->
<string name="onboarding_tracking_protection_description_2">Innstillingar for personvern og sikkerheit blokkerer sporfølgjarar, skadeleg kode og selskap som følgjer deg.</string>
<string name="onboarding_tracking_protection_description_2">Innstillingar for personvern og sikkerheit blokkerer sporarar, skadeleg kode og selskap som følgjer deg.</string>
<!-- text for tracking protection radio button option for standard level of blocking -->
<string name="onboarding_tracking_protection_standard_button_2">Standard (standard)</string>
<!-- text for standard blocking option button description -->
<string name="onboarding_tracking_protection_standard_button_description_2">Blokkerer færre sporfølgjarar. Sider vert lasta normalt.</string>
<string name="onboarding_tracking_protection_standard_button_description_2">Blokkerer færre sporarar. Sider vert lasta normalt.</string>
<!-- text for tracking protection radio button option for strict level of blocking -->
<string name="onboarding_tracking_protection_strict_button">Streng (tilrådd)</string>
<!-- text for tracking protection radio button option for strict level of blocking -->
<string name="onboarding_tracking_protection_strict_option">Streng</string>
<!-- text for strict blocking option button description -->
<string name="onboarding_tracking_protection_strict_button_description_2">Blokkerer fleire sporfølgjarar, reklamer og sprettoppvindauge. Sider vert lasta raskere, men nokre funksjonar fungerer kanskje ikkje.</string>
<string name="onboarding_tracking_protection_strict_button_description_2">Blokkerer fleire sporarar, reklamer og sprettoppvindauge. Sider vert lasta raskere, men nokre funksjonar fungerer kanskje ikkje.</string>
<!-- text for the toolbar position card header
In English this is an idiom for "choose a side as in an argument or fight"
but it is ok to make this more literally about "choosing a position in a physical space -->
@ -1079,19 +1077,19 @@
<!-- Preference for enhanced tracking protection for the standard protection settings -->
<string name="preference_enhanced_tracking_protection_standard_default_1">Standard (standard)</string>
<!-- Preference description for enhanced tracking protection for the standard protection settings -->
<string name="preference_enhanced_tracking_protection_standard_description_3">Blokkerer færre sporfølgjarar. Sider vert lasta normalt.</string>
<string name="preference_enhanced_tracking_protection_standard_description_3">Blokkerer færre sporarar. Sider vert lasta normalt.</string>
<!-- Accessibility text for the Standard protection information icon -->
<string name="preference_enhanced_tracking_protection_standard_info_button">Kva er blokkert av standard sporingsvern</string>
<!-- Preference for enhanced tracking protection for the strict protection settings -->
<string name="preference_enhanced_tracking_protection_strict">Streng</string>
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
<string name="preference_enhanced_tracking_protection_strict_description_2">Blokkerer fleire sporfølgjarar, reklamer og sprettoppvindauge. Sider vert lasta raskere, men nokre funksjonar fungerer kanskje ikkje.</string>
<string name="preference_enhanced_tracking_protection_strict_description_2">Blokkerer fleire sporarar, reklamer og sprettoppvindauge. Sider vert lasta raskere, men nokre funksjonar fungerer kanskje ikkje.</string>
<!-- Accessibility text for the Strict protection information icon -->
<string name="preference_enhanced_tracking_protection_strict_info_button">Kva er blokkert av strengt sporingsvern?</string>
<!-- Preference for enhanced tracking protection for the custom protection settings -->
<string name="preference_enhanced_tracking_protection_custom">Tilpassa</string>
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
<string name="preference_enhanced_tracking_protection_custom_description_2">Vel kva for sporfølgjarar og skript som skal blokkerast.</string>
<string name="preference_enhanced_tracking_protection_custom_description_2">Vel kva for sporarar og skript som skal blokkerast.</string>
<!-- Accessibility text for the Strict protection information icon -->
<string name="preference_enhanced_tracking_protection_custom_info_button">Kva er blokkert av tilpassa sporingsvern</string>
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
@ -1141,7 +1139,7 @@
<!-- Description of tracking content that can be blocked by Enhanced Tracking Protection -->
<string name="etp_tracking_content_description">Stoppar innlasting av eksterne annonsar, videoar og anna innhald, då dei kan innehalde sporingskode. Kan påverke visse nettstadfunksjonar.</string>
<!-- Enhanced Tracking Protection Onboarding Message shown in a dialog above the toolbar. The first parameter is the name of the application (For example: Fenix) -->
<string name="etp_onboarding_cfr_message">Kvar gong skjoldet er lilla, har %s blokkert sporfølgjarar på ein nettstad. Trykk for meir info.</string>
<string name="etp_onboarding_cfr_message">Kvar gong skjoldet er lilla, har %s blokkert sporarar på ein nettstad. Trykk for meir info.</string>
<!-- Enhanced Tracking Protection message that protection is currently on for this site -->
<string name="etp_panel_on">Vern er slått PÅ for denne nettstaden</string>
<!-- Enhanced Tracking Protection message that protection is currently off for this site -->

View File

@ -886,8 +886,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">ਜਦੋਂ ਤੁਸੀਂ ਮੁੱਖ ਮੇਨੂ ਤੋਂ &quot;ਬਾਹਰ&quot; ਨੂੰ ਚੁਣਦੇ ਹੋ ਤਾਂ ਬਰਾਊਜ਼ ਕਰਨ ਵਾਲਾ ਡਾਟਾ ਆਪਣੇ-ਆਪ ਹਟਾਇਆ ਜਾਂਦਾ ਹੈ</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">ਜਦੋਂ ਤੁਸੀਂ ਮੁੱਖ ਮੇਨੂ ਰਾਹੀਂ \&quot;ਬਾਹਰ\&quot; ਨੂੰ ਚੁਣਦੇ ਹੋ ਤਾਂ ਬਰਾਊਜ਼ ਕੀਤੇ ਡਾਟੇ ਨੂੰ ਆਪਣੇ-ਆਪ ਹਟਾਇਆ ਜਾਂਦਾ ਹੈ</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">ਬਰਾਊਜ਼ਿੰਗ ਅਤੀਤ</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">ਬਾਹਰ</string>
@ -1396,6 +1394,8 @@
<string name="synced_tabs_connect_another_device">ਹੋਰ ਡਿਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।</string>
<!-- Text displayed asking user to re-authenticate -->
<string name="synced_tabs_reauth">ਮੁੜ-ਪ੍ਰਮਾਣਿਤ ਕਰੋ।</string>
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
<string name="synced_tabs_enable_tab_syncing">ਟੈਬ ਨੂੰ ਸਿੰਕ ਕਰਨਾ ਸਮਰੱਥ ਕਰੋ।</string>
<!-- Text displayed on a button in the synced tabs screen to link users to sign in when a user is not signed in to Firefox Sync -->
<string name="synced_tabs_sign_in_button">ਸਿੰਕ ਕਰਨ ਲਈ ਸਾਈਨ ਇਨ ਕਰੋ</string>

View File

@ -911,7 +911,7 @@
No entanto, pode ser menos estável. Instale nosso navegador beta se quiser uma experiência de uso mais estável.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Instale o Firefox para Android Beta</string>
<string name="tip_firefox_preview_moved_button_2">Instale o Firefox Beta para Android</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">O Firefox Nightly mudou</string>

View File

@ -917,8 +917,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">Автоматически удаляет данные веб-сёрфинга, когда вы выбираете «Выйти» в главном меню</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">Автоматически удаляет данные веб-сёрфинга, когда вы выбираете \&quot;Выйти\&quot; в главном меню</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">История веб-сёрфинга</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Выйти</string>
@ -940,9 +938,8 @@
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox Preview теперь стал Firefox Nightly</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">
· Firefox Nightly обновляется каждую ночь и включает в себя новые, экспериментальные возможности.¶
· Однако, он может быть менее стабилен. Если вы хотите более стабильной работы, загрузите нашу бета-версию браузера.</string>
<string name="tip_firefox_preview_moved_description">Firefox Nightly обновляется каждую ночь и включает в себя новые, экспериментальные возможности.
Однако, он может быть менее стабилен. Если вы хотите более стабильной работы, загрузите нашу бета-версию браузера.</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">Загрузить Firefox для Android Бета</string>
@ -950,18 +947,16 @@
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly переехал</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_installed">
· Это приложение больше не будет получать обновлений безопасности. Прекратите использование этого приложения и переключитесь на новый Nightly.¶
· \n\nЧтобы переместить ваши закладки, логины и историю в другое приложение, создайте аккаунт Firefox.</string>
<string name="tip_firefox_preview_moved_description_preview_installed">Это приложение больше не будет получать обновлений безопасности. Прекратите использование этого приложения и переключитесь на новый Nightly.
\n\nЧтобы переместить ваши закладки, логины и историю в другое приложение, создайте аккаунт Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_installed">Переключиться на новый Nightly</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_not_installed">Firefox Nightly переехал</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_not_installed">
· Это приложение больше не будет получать обновлений безопасности. Получите новый Nightly и прекратите использование этого приложения.¶
· \n\nЧтобы переместить ваши закладки, логины и историю в другое приложение, создайте аккаунт Firefox.</string>
<string name="tip_firefox_preview_moved_description_preview_not_installed">Это приложение больше не будет получать обновлений безопасности. Получите новый Nightly и прекратите использование этого приложения.
\n\nЧтобы переместить ваши закладки, логины и историю в другое приложение, создайте аккаунт Firefox.</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_not_installed">Получить новый Nightly</string>

View File

@ -150,6 +150,8 @@
<string name="preferences_theme">கருப்பொருள்</string>
<!-- Preference shown instead of account display name while account profile information isn't available yet. -->
<string name="preferences_account_default_name">பயர்பாக்சு கணக்கு</string>
<!-- Preference text for account title when there was an error syncing FxA -->
<string name="preferences_account_sync_error">ஒத்திசைவை மீள்தொடங்க மீண்டும் இணைக்கவும்</string>
<!-- Preference for language -->
<string name="preferences_language">மொழி</string>
<!-- Preference for data choices -->
@ -210,4 +212,129 @@
<!-- Name of the "receive tabs" notification channel. Displayed in the "App notifications" system settings for the app -->
<string name="fxa_received_tab_channel_name">பெறப்பட்ட கீற்றுகள்</string>
<!-- Description of the "receive tabs" notification channel. Displayed in the "App notifications" system settings for the app -->
<string name="fxa_received_tab_channel_description">பிற பயர்பாக்சு சாதனங்களிலிருந்து பெறப்பட்ட கீற்றுகளுக்கான அறிவிப்புகள்.</string>
<!-- The body for these is the URL of the tab received -->
<string name="fxa_tab_received_notification_name">கீற்று பெறப்பட்டது</string>
<!-- When multiple tabs have been received -->
<string name="fxa_tabs_received_notification_name">கீற்றுகள் பெறப்பட்டன</string>
<!-- Advanced Preferences -->
<!-- Preference for tracking protection settings -->
<string name="preferences_tracking_protection_settings">தடமறியல் பாதுகாப்பு</string>
<!-- Preference switch for tracking protection -->
<string name="preferences_tracking_protection">தடமறியல் பாதுகாப்பு</string>
<!-- Preference for tracking protection exceptions -->
<string name="preferences_tracking_protection_exceptions">விதிவிலக்குகள்</string>
<!-- Button in Exceptions Preference to turn on tracking protection for all sites (remove all exceptions) -->
<string name="preferences_tracking_protection_exceptions_turn_on_for_all">எல்லா தளங்களுக்கும் இயக்கு</string>
<!-- Text displayed when there are no exceptions, with learn more link that brings users to a tracking protection SUMO page -->
<string name="exceptions_empty_message_learn_more_link">மேலும் அறிய</string>
<!-- Title for experiments preferences -->
<string name="preference_experiments">சோதனைகள்</string>
<!-- Preference switch for crash reporter -->
<string name="preferences_crash_reporter">செயலிழப்பு அறிக்கையாளர்</string>
<!-- Preference switch for Mozilla location service -->
<string name="preferences_mozilla_location_service">மொசில்லா புவியிடச்சேவை</string>
<!-- Turn On Sync Preferences -->
<!-- Header of the Turn on Sync preference view -->
<string name="preferences_sync">ஒத்திசைவை இயக்கு</string>
<!-- Preference for account login -->
<string name="preferences_sync_sign_in">புகுபதிகை</string>
<!-- Preference for reconnecting to FxA sync -->
<string name="preferences_sync_sign_in_to_reconnect">மறுஇணைக்க புகுபதியுங்கள்</string>
<!-- Preference for removing FxA account -->
<string name="preferences_sync_remove_account">கணக்கை அகற்று</string>
<!-- Button to open camera for pairing -->
<string name="pair_open_camera">படக்கருவியைத் திற</string>
<!-- Button to cancel pairing -->
<string name="pair_cancel">இரத்து</string>
<!-- Toolbar Preferences -->
<!-- Preference for using top toolbar -->
<string name="preference_top_toolbar">மேல்</string>
<!-- Preference for using bottom toolbar -->
<string name="preference_bottom_toolbar">கீழ்</string>
<!-- Theme Preferences -->
<!-- Preference for using light theme -->
<string name="preference_light_theme">வெளிர்</string>
<!-- Preference for using dark theme -->
<string name="preference_dark_theme">கருமை</string>
<!-- Preference for using using dark or light theme automatically set by battery -->
<string name="preference_auto_battery_theme">மின்கலச்சேமிப்பான் அமைத்தது</string>
<!-- Preference for using following device theme -->
<string name="preference_follow_device_theme">சாதனக் கருப்பொருளைப் பின்பற்று</string>
<!-- Library -->
<!-- Option in Library to open Sessions page -->
<string name="library_sessions">அமர்வுகள்</string>
<!-- Option in Library to open Screenshots page -->
<string name="library_screenshots">திரைப்பிடிப்புகள்</string>
<!-- Option in Library to open Downloads page -->
<string name="library_downloads">பதிவிறக்கங்கள்</string>
<!-- Option in library to open Bookmarks page -->
<string name="library_bookmarks">புத்தகக்குறிகள்</string>
<!-- Option in library to open Desktop Bookmarks root page -->
<string name="library_desktop_bookmarks_root">மேசைக்கணினி புத்தகக்குறிகள்</string>
<!-- Option in library to open Desktop Bookmarks "menu" page -->
<string name="library_desktop_bookmarks_menu">புத்தகக்குறிகள் பட்டி</string>
<!-- Option in library to open Desktop Bookmarks "toolbar" page -->
<string name="library_desktop_bookmarks_toolbar">புத்தகக்குறிகள் கருவிப்பட்டை</string>
<!-- Option in library to open Desktop Bookmarks "unfiled" page -->
<string name="library_desktop_bookmarks_unfiled">பிற புத்தகக்குறிகள்</string>
<!-- Option in Library to open History page -->
<string name="library_history">வரலாறு</string>
<!-- Option in Library to open Reading List -->
<string name="library_reading_list">வாசிப்புப் பட்டியல்</string>
<!-- Menu Item Label for Search in Library -->
<string name="library_search">தேடல்</string>
<!-- Settings Page Title -->
<string name="settings_title">அமைவுகள்</string>
<!-- Content description (not visible, for screen readers etc.): "Menu icon for items on a history item" -->
<string name="content_description_history_menu">வரலாறு உருப்படி பட்டி</string>
<!-- Content description (not visible, for screen readers etc.): "Close button for library settings" -->
<string name="content_description_close_button">மூடு</string>
<!-- Sessions -->
<!-- Title for the list of tabs -->
<string name="tab_header_label">திறந்த கீற்றுகள்</string>
<!-- Title for the list of tabs in the current private session -->
<string name="tabs_header_private_title">கமுக்க அமர்வு</string>
<!-- Title for the list of tabs in the current private session -->
<string name="tabs_header_private_tabs_title">கமுக்கக் கீற்றுகள்</string>
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
<string name="add_tab">கீற்றைச் சேர்</string>
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
<string name="close_tab">கீற்றை மூடு</string>
<!-- Content description (not visible, for screen readers etc.): Close tab <title> button. First parameter is tab title -->
<string name="close_tab_title">%s கீற்றை மூடு</string>
<!-- Content description (not visible, for screen readers etc.): Opens the open tabs menu when pressed -->
<string name="open_tabs_menu">கீற்றுப் பட்டியைத் திற</string>
<!-- Open tabs menu item to close all tabs -->
<string name="tabs_menu_close_all_tabs">எல்லாக் கீற்றுகளையும் மூடு</string>
<!-- Open tabs menu item to share all tabs -->
<string name="tabs_menu_share_tabs">கீற்றுகளைப் பகிர்</string>
<!-- Content description (not visible, for screen readers etc.): Opens the tab menu when pressed -->
<string name="tab_menu">கீற்றுப் பட்டி</string>
<!-- Tab menu item to share the tab -->
<string name="tab_share">தரவைப் பகிர்</string>
<!-- Button in the current session menu. Deletes the session when pressed -->
<string name="current_session_delete">நீக்கு</string>
<!-- Button in the current session menu. Saves the session when pressed -->
<string name="current_session_save">சேமி</string>
<!-- Button in the current session menu. Opens the share menu when pressed -->
<string name="current_session_share">பகிர்</string>
<!-- Button to save the current set of tabs into a collection -->
<string name="save_to_collection">திரட்டில் சேமி</string>
<!-- Text for the menu button to delete a collection -->
<string name="collection_delete">திரட்டை நீக்கு</string>
<!-- Text for the menu button to rename a collection -->
<string name="collection_rename">திரட்டை மறுபெயரிடு</string>
<!-- Text for the button to open tabs of the selected collection -->
<string name="collection_open_tabs">கீற்றுகளைத் திற</string>
</resources>

View File

@ -897,8 +897,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">Автоматично видаляє дані перегляду при виборі &quot;Вихід&quot; в головному меню</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">Автоматично видаляє дані перегляду при виборі \&quot;Вихід\&quot; в головному меню</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">Історія перегляду</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">Вихід</string>
@ -1444,7 +1442,7 @@
<!-- Text displayed to ask user to connect another device as no devices found with account -->
<string name="synced_tabs_connect_another_device">Під’єднати інший пристрій.</string>
<!-- Text displayed asking user to re-authenticate -->
<string name="synced_tabs_reauth">Необхідно повторно авторизуватись.</string>
<string name="synced_tabs_reauth">Повторіть автентифікацію.</string>
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
<string name="synced_tabs_enable_tab_syncing">Увімкніть синхронізацію вкладок.</string>
<!-- Text displayed when user has no tabs that have been synced -->

View File

@ -926,8 +926,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">从主菜单中选择“退出”时,自动删除浏览数据</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">从主菜单中选择“退出”时,自动删除浏览数据</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">浏览历史</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">退出</string>
@ -947,7 +945,7 @@
<!-- Tips -->
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox Preview 即为现在的 Firefox Nightly</string>
<string name="tip_firefox_preview_moved_header">Firefox Preview 已迁移至 Firefox Nightly</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">Firefox Nightly 每日获得更新,包含实验性的新功能。
但可能不够稳定,您可以下载我们的 Beta 版浏览器以获得更稳定的体验。</string>

View File

@ -919,8 +919,6 @@
<string name="preference_summary_delete_browsing_data_on_quit">當您點擊主選單當中的「離開」時,自動刪除瀏覽資料</string>
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
<string name="preference_summary_delete_browsing_data_on_quit_2">點擊主選單中的「離開」時,自動清除上網資料</string>
<!-- Category for history items to delete on quit in delete browsing data on quit -->
<string name="preferences_delete_browsing_data_on_quit_browsing_history">瀏覽紀錄</string>
<!-- Action item in menu for the Delete browsing data on quit feature -->
<string name="delete_browsing_data_on_quit_action">離開</string>
@ -940,9 +938,9 @@
<!-- Tips -->
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header">Firefox Nightly 已被 Firefox Preview 取代</string>
<string name="tip_firefox_preview_moved_header">Firefox Nightly 已接手原 Firefox Preview 功能</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description">Firefox Nightly 每天都會更新一次,當中包含實驗中的新功能,然而這些新功能可能會較不穩定。若須有較穩定的使用體驗,請下載我們的 Beta 測試版。</string>
<string name="tip_firefox_preview_moved_description">Firefox Nightly 每天都會更新,當中包含實驗中的新功能,然而這些新功能可能會較不穩定。\n\n若想要有較穩定的使用體驗,請下載我們的 Beta 測試版。</string>
<!-- text for firefox preview moving tip button. "Firefox for Android Beta" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_button_2">下載 Firefox for Android Beta 測試版</string>
@ -950,14 +948,14 @@
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly 版本更新</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_installed">此應用程式不會再收到安全性更新。請改用新版的 Nightly 並停用此應用程式。\n\n註冊 Firefox 帳號,即可快速移轉書籤、登入資訊、瀏覽紀錄到新版本當中</string>
<string name="tip_firefox_preview_moved_description_preview_installed">此應用程式不會再收到安全性更新。請改用新版的 Nightly 並停止使用此應用程式。\n\n註冊 Firefox 帳號,即可快速移轉書籤、登入資訊、瀏覽紀錄到新版本。</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_installed">改用新版 Nightly</string>
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
<string name="tip_firefox_preview_moved_header_preview_not_installed">Firefox Nightly 版本更新</string>
<!-- text for firefox preview moving tip description -->
<string name="tip_firefox_preview_moved_description_preview_not_installed">此應用程式不會再收到安全性更新。請下載新版的 Nightly 並停用此應用程式。\n\n請註冊 Firefox 帳號,即可快速移轉書籤、登入資訊、瀏覽紀錄到新版本當中</string>
<string name="tip_firefox_preview_moved_description_preview_not_installed">此應用程式不會再收到安全性更新。請改用新版的 Nightly 並停止使用此版應用程式。\n\n註冊 Firefox 帳號,即可快速移轉書籤、登入資訊、瀏覽紀錄到新版本。</string>
<!-- text for firefox preview moving tip button -->
<string name="tip_firefox_preview_moved_button_preview_not_installed">下載新版 Nightly</string>

View File

@ -109,12 +109,10 @@
<dimen name="about_header_text_line_spacing_extra">4dp</dimen>
<!-- Locale Settings Fragment -->
<dimen name="locale_search_bar_margin">8dp</dimen>
<dimen name="locale_search_bar_padding_start">-12dp</dimen>
<dimen name="locale_list_margin">16dp</dimen>
<dimen name="locale_item_vertical_margin">8dp</dimen>
<dimen name="locale_item_text_margin_start">16dp</dimen>
<dimen name="locale_item_text_margin_gone_start">40dp</dimen>
<dimen name="locale_item_text_margin_start">32dp</dimen>
<dimen name="locale_item_text_margin_end">16dp</dimen>
<dimen name="locale_item_text_margin_gone_start">72dp</dimen>
<dimen name="locale_item_title_size">16sp</dimen>
<dimen name="locale_item_subtitle_size">12sp</dimen>

View File

@ -714,6 +714,8 @@
<string name="create_collection_save_to_collection_tab_selected">%d tab selected</string>
<!-- Text shown in snackbar when multiple tabs have been saved in a collection -->
<string name="create_collection_tabs_saved">Tabs saved!</string>
<!-- Text shown in snackbar when one or multiple tabs have been saved in a new collection -->
<string name="create_collection_tabs_saved_new_collection">Collection saved!</string>
<!-- Text shown in snackbar when one tab has been saved in a collection -->
<string name="create_collection_tab_saved">Tab saved!</string>
<!-- Content description (not visible, for screen readers etc.): button to close the collection creator -->
@ -817,6 +819,10 @@
<string name="qr_scanner_dialog_negative">DENY</string>
<!-- Tab collection deletion prompt dialog message. Placeholder will be replaced with the collection name -->
<string name="tab_collection_dialog_message">Are you sure you want to delete %1$s?</string>
<!-- Collection and tab deletion prompt dialog message. This will show when the last tab from a collection is deleted -->
<string name="delete_tab_and_collection_dialog_message">Deleting this tab will delete the entire collection. You can create new collections at any time.</string>
<!-- Collection and tab deletion prompt dialog title. Placeholder will be replaced with the collection name. This will show when the last tab from a collection is deleted -->
<string name="delete_tab_and_collection_dialog_title">Delete collection %1$s?</string>
<!-- Tab collection deletion prompt dialog option to delete the collection -->
<string name="tab_collection_dialog_positive">Delete</string>
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->

View File

@ -244,7 +244,8 @@
<item name="android:textAlignment">center</item>
<item name="android:background">@drawable/rounded_button_background</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">48dp</item>
<item name="android:minHeight">48dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textStyle">bold</item>
<item name="android:textAllCaps">false</item>
<item name="backgroundTint">@color/grey_button_color</item>

View File

@ -2,21 +2,17 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.preference.SwitchPreference
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:key="@string/pref_key_telemetry"
android:summary="@string/preferences_usage_data_description"
android:title="@string/preference_usage_data"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreference
android:title="@string/preference_usage_data" />
<SwitchPreference
android:key="@string/pref_key_marketing_telemetry"
android:summary="@string/preferences_marketing_data_description"
android:title="@string/preferences_marketing_data"
app:iconSpaceReserved="false" />
<androidx.preference.SwitchPreference
android:title="@string/preferences_marketing_data" />
<SwitchPreference
android:key="@string/pref_key_experimentation"
android:summary="@string/preference_experiments_summary"
android:title="@string/preference_experiments"
app:iconSpaceReserved="false" />
android:title="@string/preference_experiments" />
</PreferenceScreen>

View File

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix
import androidx.appcompat.app.ActionBar
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import io.mockk.mockk
import org.robolectric.Robolectric
class MockNavHostActivity : AppCompatActivity(), NavHostActivity {
private val mockActionBar = mockk<ActionBar>(relaxed = true)
override fun getSupportActionBarAndInflateIfNecessary() = mockActionBar
}
/**
* Set up an added [Fragment] to a [FragmentActivity] that has been initialized to a resumed state.
*
* Variant of [mozilla.components.support.test.robolectric.createAddedTestFragment] that uses
* a custom Fenix activity to hold the fragment.
*
* @param fragmentTag the name that will be used to tag the fragment inside the [FragmentManager].
* @param fragmentFactory a lambda function that returns a Fragment that will be added to the Activity.
*
* @return The same [Fragment] that was returned from [fragmentFactory] after it got added to the
* Activity.
*/
inline fun <T : Fragment> createAddedTestFragmentInNavHostActivity(
fragmentTag: String = "test",
fragmentFactory: () -> T
): T {
val activity = Robolectric.buildActivity(MockNavHostActivity::class.java)
.create()
.start()
.resume()
.get()
return fragmentFactory().also {
activity.supportFragmentManager.beginTransaction()
.add(it, fragmentTag)
.commitNow()
}
}

View File

@ -0,0 +1,47 @@
/* 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.addons
import android.content.Intent.ACTION_VIEW
import androidx.core.net.toUri
import kotlinx.android.synthetic.main.fragment_add_on_permissions.*
import mozilla.components.feature.addons.Addon
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.createAddedTestFragmentInNavHostActivity
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
import org.robolectric.Shadows.shadowOf
@RunWith(FenixRobolectricTestRunner::class)
class AddonPermissionsDetailsFragmentTest {
private val addon = Addon(
id = "",
translatableName = mapOf(
Addon.DEFAULT_LOCALE to "Some blank addon"
)
)
@Test
fun `trigger view intent when learn more is clicked`() {
val fragment = createAddedTestFragmentInNavHostActivity {
AddonPermissionsDetailsFragment().apply {
arguments = AddonPermissionsDetailsFragmentArgs(addon).toBundle()
}
}
assertEquals("Some blank addon", fragment.activity?.title)
fragment.learn_more_label.performClick()
val intent = shadowOf(fragment.activity).peekNextStartedActivity()
assertEquals(ACTION_VIEW, intent.action)
assertEquals(
"https://support.mozilla.org/kb/permission-request-messages-firefox-extensions".toUri(),
intent.data
)
}
}

View File

@ -49,7 +49,7 @@ class DefaultSessionControlControllerTest {
private val openPrivacyNotice: () -> Unit = mockk(relaxed = true)
private val registerCollectionStorageObserver: () -> Unit = mockk(relaxed = true)
private val showTabTray: () -> Unit = mockk(relaxed = true)
private val showDeleteCollectionPrompt: (tabCollection: TabCollection) -> Unit =
private val showDeleteCollectionPrompt: (tabCollection: TabCollection, title: String?, message: String) -> Unit =
mockk(relaxed = true)
private val metrics: MetricController = mockk(relaxed = true)
private val state: HomeFragmentState = mockk(relaxed = true)
@ -137,7 +137,7 @@ class DefaultSessionControlControllerTest {
fun handleDeleteCollectionTapped() {
val collection: TabCollection = mockk(relaxed = true)
controller.handleDeleteCollectionTapped(collection)
verify { showDeleteCollectionPrompt(collection) }
verify { showDeleteCollectionPrompt(collection, null, any()) }
}
@Test

View File

@ -47,6 +47,16 @@ class SearchFragmentStoreTest {
assertEquals(true, store.state.showSearchShortcuts)
}
@Test
fun hideSearchShortcutEnginePicker() = runBlocking {
val initialState = emptyDefaultState()
val store = SearchFragmentStore(initialState)
store.dispatch(SearchFragmentAction.UpdateShortcutsAvailability(false)).join()
assertNotSame(initialState, store.state)
assertEquals(false, store.state.showSearchShortcuts)
}
private fun emptyDefaultState(): SearchFragmentState = SearchFragmentState(
tabId = null,
url = "",
@ -57,6 +67,7 @@ class SearchFragmentStoreTest {
showSearchSuggestionsHint = false,
showSearchSuggestions = false,
showSearchShortcuts = false,
areShortcutsAvailable = true,
showClipboardSuggestions = false,
showHistorySuggestions = false,
showBookmarkSuggestions = false,

View File

@ -2,14 +2,14 @@
* 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.ext
package org.mozilla.fenix.search
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.mozilla.fenix.search.telemetry.SearchProviderModel
class AdsTest {
class SearchProviderModelTest {
private val testSearchProvider =
SearchProviderModel(

View File

@ -3,5 +3,5 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
object AndroidComponents {
const val VERSION = "49.0.20200702190156"
const val VERSION = "49.0.20200706130124"
}

View File

@ -7,14 +7,14 @@ object Versions {
const val coroutines = "1.3.3"
const val android_gradle_plugin = "3.5.0"
const val sentry = "1.7.10"
const val leakcanary = "2.3"
const val leakcanary = "2.4"
const val leanplum = "5.4.0"
const val osslicenses_plugin = "0.9.5"
const val osslicenses_library = "17.0.0"
const val detekt = "1.6.0"
const val androidx_appcompat = "1.2.0-rc01"
const val androidx_biometric = "1.0.1"
const val androidx_biometric = "1.1.0-alpha01"
const val androidx_coordinator_layout = "1.1.0-rc01"
const val androidx_constraint_layout = "2.0.0-beta6"
const val androidx_preference = "1.1.0"
@ -22,7 +22,7 @@ object Versions {
const val androidx_annotation = "1.1.0"
const val androidx_lifecycle = "2.2.0"
const val androidx_fragment = "1.2.5"
const val androidx_navigation = "2.2.1"
const val androidx_navigation = "2.3.0"
const val androidx_recyclerview = "1.1.0"
const val androidx_core = "1.2.0"
const val androidx_paging = "2.1.0"
@ -44,7 +44,7 @@ object Versions {
const val google_ads_id_version = "16.0.0"
const val airbnb_lottie = "3.3.0"
const val airbnb_lottie = "3.4.0"
}
@Suppress("unused")