Copione merged onto master
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
acf33e754f
|
@ -100,3 +100,7 @@ test_artifacts/
|
||||||
/build/test-tools/google-cloud-sdk/
|
/build/test-tools/google-cloud-sdk/
|
||||||
/build/test-tools/*.jar
|
/build/test-tools/*.jar
|
||||||
/build/test-tools/*.gz
|
/build/test-tools/*.gz
|
||||||
|
|
||||||
|
|
||||||
|
# Web extensions: manifest.json files are generated
|
||||||
|
manifest.json
|
||||||
|
|
|
@ -186,6 +186,10 @@ android {
|
||||||
// GeckoView must uncompress it before it can do anything else which
|
// GeckoView must uncompress it before it can do anything else which
|
||||||
// causes a significant delay on startup.
|
// causes a significant delay on startup.
|
||||||
noCompress 'ja'
|
noCompress 'ja'
|
||||||
|
|
||||||
|
// manifest.template.json is converted to manifest.json at build time.
|
||||||
|
// No need to package the template in the APK.
|
||||||
|
ignoreAssetsPattern "manifest.template.json"
|
||||||
}
|
}
|
||||||
|
|
||||||
testOptions {
|
testOptions {
|
||||||
|
@ -755,3 +759,34 @@ if (gradle.hasProperty('localProperties.autoPublish.application-services.dir'))
|
||||||
ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
|
ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
|
||||||
apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
|
apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define a reusable task for updating the versions of our built-in web extensions. We automate this
|
||||||
|
// to make sure we never forget to update the version, either in local development or for releases.
|
||||||
|
// In both cases, we want to make sure the latest version of all extensions (including their latest
|
||||||
|
// changes) are installed on first start-up.
|
||||||
|
// We're using the A-C version here as we want to uplift all built-in extensions to A-C (Once that's
|
||||||
|
// done we can also remove the task below):
|
||||||
|
// https://github.com/mozilla-mobile/android-components/issues/7249
|
||||||
|
ext.updateExtensionVersion = { task, extDir ->
|
||||||
|
configure(task) {
|
||||||
|
from extDir
|
||||||
|
include 'manifest.template.json'
|
||||||
|
rename { 'manifest.json' }
|
||||||
|
into extDir
|
||||||
|
|
||||||
|
def values = ['version': AndroidComponents.VERSION + "." + new Date().format('MMddHHmmss')]
|
||||||
|
inputs.properties(values)
|
||||||
|
expand(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("updateAdsExtensionVersion", Copy) { task ->
|
||||||
|
updateExtensionVersion(task, 'src/main/assets/extensions/ads')
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("updateCookiesExtensionVersion", Copy) { task ->
|
||||||
|
updateExtensionVersion(task, 'src/main/assets/extensions/cookies')
|
||||||
|
}
|
||||||
|
|
||||||
|
preBuild.dependsOn updateAdsExtensionVersion
|
||||||
|
preBuild.dependsOn updateCookiesExtensionVersion
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.screenshots
|
package org.mozilla.fenix.screenshots
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
import androidx.test.rule.ActivityTestRule
|
import androidx.test.rule.ActivityTestRule
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mozilla.fenix.helpers.HomeActivityTestRule
|
import org.mozilla.fenix.helpers.HomeActivityTestRule
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||||
import org.mozilla.fenix.ui.robots.homeScreen
|
import org.mozilla.fenix.ui.robots.homeScreen
|
||||||
import org.mozilla.fenix.ui.robots.mDevice
|
import org.mozilla.fenix.ui.robots.mDevice
|
||||||
import tools.fastlane.screengrab.Screengrab
|
import tools.fastlane.screengrab.Screengrab
|
||||||
|
@ -30,15 +32,17 @@ class DefaultHomeScreenTest : ScreenshotTest() {
|
||||||
fun showDefaultHomeScreen() {
|
fun showDefaultHomeScreen() {
|
||||||
homeScreen {
|
homeScreen {
|
||||||
verifyAccountsSignInButton()
|
verifyAccountsSignInButton()
|
||||||
Screengrab.screenshot("HomeScreenRobot_home-screen")
|
|
||||||
swipeToBottom()
|
swipeToBottom()
|
||||||
Screengrab.screenshot("HomeScreenRobot_home-screen-scroll")
|
Screengrab.screenshot("HomeScreenRobot_home-screen-scroll")
|
||||||
|
TestAssetHelper.waitingTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun privateBrowsingTest() {
|
fun privateBrowsingTest() {
|
||||||
homeScreen {
|
homeScreen {
|
||||||
|
SystemClock.sleep(TestAssetHelper.waitingTimeShort)
|
||||||
|
Screengrab.screenshot("HomeScreenRobot_home-screen")
|
||||||
}.openThreeDotMenu {
|
}.openThreeDotMenu {
|
||||||
}.openSettings { }
|
}.openSettings { }
|
||||||
// To get private screenshot,
|
// To get private screenshot,
|
||||||
|
@ -48,6 +52,7 @@ class DefaultHomeScreenTest : ScreenshotTest() {
|
||||||
togglePrivateBrowsingModeOnOff()
|
togglePrivateBrowsingModeOnOff()
|
||||||
Screengrab.screenshot("HomeScreenRobot_private-browsing-menu")
|
Screengrab.screenshot("HomeScreenRobot_private-browsing-menu")
|
||||||
togglePrivateBrowsingModeOnOff()
|
togglePrivateBrowsingModeOnOff()
|
||||||
|
Screengrab.screenshot("HomeScreenRobot_after-onboarding")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,13 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.screenshots
|
package org.mozilla.fenix.screenshots
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
import androidx.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
import androidx.test.rule.ActivityTestRule
|
import androidx.test.rule.ActivityTestRule
|
||||||
|
import androidx.test.uiautomator.By
|
||||||
|
import androidx.test.uiautomator.Until
|
||||||
import tools.fastlane.screengrab.Screengrab
|
import tools.fastlane.screengrab.Screengrab
|
||||||
import tools.fastlane.screengrab.locale.LocaleTestRule
|
import tools.fastlane.screengrab.locale.LocaleTestRule
|
||||||
import okhttp3.mockwebserver.MockWebServer
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
|
@ -21,6 +24,7 @@ import org.mozilla.fenix.helpers.AndroidAssetDispatcher
|
||||||
import org.mozilla.fenix.helpers.HomeActivityTestRule
|
import org.mozilla.fenix.helpers.HomeActivityTestRule
|
||||||
import org.mozilla.fenix.helpers.TestAssetHelper
|
import org.mozilla.fenix.helpers.TestAssetHelper
|
||||||
import org.mozilla.fenix.helpers.click
|
import org.mozilla.fenix.helpers.click
|
||||||
|
import org.mozilla.fenix.helpers.ext.waitNotNull
|
||||||
import org.mozilla.fenix.ui.robots.homeScreen
|
import org.mozilla.fenix.ui.robots.homeScreen
|
||||||
import org.mozilla.fenix.ui.robots.bookmarksMenu
|
import org.mozilla.fenix.ui.robots.bookmarksMenu
|
||||||
import org.mozilla.fenix.ui.robots.mDevice
|
import org.mozilla.fenix.ui.robots.mDevice
|
||||||
|
@ -125,13 +129,13 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||||
openBookmarksThreeDotMenu()
|
openBookmarksThreeDotMenu()
|
||||||
Screengrab.screenshot("BookmarksRobot_bookmarks-menu")
|
Screengrab.screenshot("BookmarksRobot_bookmarks-menu")
|
||||||
bookmarksMenu {
|
bookmarksMenu {
|
||||||
clickAddFolderButton()
|
clickAddFolderButtonUsingId()
|
||||||
Screengrab.screenshot("BookmarksRobot_add-folder-view")
|
Screengrab.screenshot("BookmarksRobot_add-folder-view")
|
||||||
saveNewFolder()
|
saveNewFolder()
|
||||||
Screengrab.screenshot("BookmarksRobot_error-empty-folder-name")
|
Screengrab.screenshot("BookmarksRobot_error-empty-folder-name")
|
||||||
addNewFolderName("test")
|
addNewFolderName("test")
|
||||||
saveNewFolder()
|
saveNewFolder()
|
||||||
}.openThreeDotMenu {
|
}.openThreeDotMenu("test") {
|
||||||
Screengrab.screenshot("ThreeDotMenuBookmarksRobot_folder-menu")
|
Screengrab.screenshot("ThreeDotMenuBookmarksRobot_folder-menu")
|
||||||
}
|
}
|
||||||
editBookmarkFolder()
|
editBookmarkFolder()
|
||||||
|
@ -139,7 +143,7 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||||
// It may be needed to wait here to have the screenshot
|
// It may be needed to wait here to have the screenshot
|
||||||
mDevice.pressBack()
|
mDevice.pressBack()
|
||||||
bookmarksMenu {
|
bookmarksMenu {
|
||||||
}.openThreeDotMenu {
|
}.openThreeDotMenu("test") {
|
||||||
deleteBookmarkFolder()
|
deleteBookmarkFolder()
|
||||||
Screengrab.screenshot("ThreeDotMenuBookmarksRobot_delete-bookmark-folder-menu")
|
Screengrab.screenshot("ThreeDotMenuBookmarksRobot_delete-bookmark-folder-menu")
|
||||||
}
|
}
|
||||||
|
@ -152,21 +156,12 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||||
Screengrab.screenshot("NavigationToolbarRobot_navigation-toolbar")
|
Screengrab.screenshot("NavigationToolbarRobot_navigation-toolbar")
|
||||||
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
||||||
Screengrab.screenshot("BrowserRobot_enter-url")
|
Screengrab.screenshot("BrowserRobot_enter-url")
|
||||||
}
|
}.openTabDrawer {
|
||||||
tapOnTabCounter()
|
TestAssetHelper.waitingTime
|
||||||
// Homescreen with visited tabs
|
Screengrab.screenshot("TabDrawerRobot_one-tab-open")
|
||||||
Screengrab.screenshot("HomeScreenRobot_homescreen-with-tabs-open")
|
|
||||||
homeScreen {
|
|
||||||
}.openTabsListThreeDotMenu {
|
}.openTabsListThreeDotMenu {
|
||||||
Screengrab.screenshot("open-tabs-menu")
|
TestAssetHelper.waitingTime
|
||||||
}.close {
|
Screengrab.screenshot("TabDrawerRobot_three-dot-menu")
|
||||||
// It may be needed to wait here for tests working on Firebase
|
|
||||||
saveToCollectionButton()
|
|
||||||
Screengrab.screenshot("HomeScreenRobot_save-collection-view")
|
|
||||||
typeCollectionName("CollectionName")
|
|
||||||
mDevice.pressBack()
|
|
||||||
// It may be needed to wait here for tests working on Firebase
|
|
||||||
Screengrab.screenshot("HomeScreenRobot_saved-collection")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,12 +171,13 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||||
navigationToolbar {
|
navigationToolbar {
|
||||||
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
}.enterURLAndEnterToBrowser(defaultWebPage.url) {
|
||||||
}.openThreeDotMenu {
|
}.openThreeDotMenu {
|
||||||
Screengrab.screenshot("browser-tab-menu")
|
Screengrab.screenshot("TabDrawerRobot_browser-tab-menu")
|
||||||
}.closeBrowserMenuToBrowser {
|
}.closeBrowserMenuToBrowser {
|
||||||
}.openTabDrawer {
|
}.openTabDrawer {
|
||||||
Screengrab.screenshot("tab-drawer-with-tabs")
|
Screengrab.screenshot("TabDrawerRobot_tab-drawer-with-tabs")
|
||||||
closeTab()
|
closeTab()
|
||||||
Screengrab.screenshot("remove-tab")
|
TestAssetHelper.waitingTime
|
||||||
|
Screengrab.screenshot("TabDrawerRobot_remove-tab")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +185,11 @@ class MenuScreenShotTest : ScreenshotTest() {
|
||||||
fun saveLoginPromptTest() {
|
fun saveLoginPromptTest() {
|
||||||
val saveLoginTest =
|
val saveLoginTest =
|
||||||
TestAssetHelper.getSaveLoginAsset(mockWebServer)
|
TestAssetHelper.getSaveLoginAsset(mockWebServer)
|
||||||
TestAssetHelper.waitingTimeShort
|
|
||||||
navigationToolbar {
|
navigationToolbar {
|
||||||
}.enterURLAndEnterToBrowser(saveLoginTest.url) {
|
}.enterURLAndEnterToBrowser(saveLoginTest.url) {
|
||||||
|
verifySaveLoginPromptIsShownNotSave()
|
||||||
|
SystemClock.sleep(TestAssetHelper.waitingTimeShort)
|
||||||
Screengrab.screenshot("save-login-prompt")
|
Screengrab.screenshot("save-login-prompt")
|
||||||
TestAssetHelper.waitingTime
|
|
||||||
// verifySaveLoginPromptIsShown()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,3 +231,11 @@ fun loginsAndPassword() = onView(withText(R.string.preferences_passwords_logins_
|
||||||
fun addOns() = onView(withText(R.string.preferences_addons)).click()
|
fun addOns() = onView(withText(R.string.preferences_addons)).click()
|
||||||
|
|
||||||
fun settingsLanguage() = onView(withText(R.string.preferences_language)).click()
|
fun settingsLanguage() = onView(withText(R.string.preferences_language)).click()
|
||||||
|
|
||||||
|
fun verifySaveLoginPromptIsShownNotSave() {
|
||||||
|
mDevice.waitNotNull(Until.findObjects(By.text("test@example.com")), TestAssetHelper.waitingTime)
|
||||||
|
val submitButton = mDevice.findObject(By.res("submit"))
|
||||||
|
submitButton.clickAndWait(Until.newWindow(), TestAssetHelper.waitingTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clickAddFolderButtonUsingId() = onView(withId(R.id.add_bookmark_folder)).click()
|
||||||
|
|
|
@ -131,7 +131,7 @@ class ContextMenusTest {
|
||||||
clickContextShareLink(genericURL.url) // verify share intent is matched with associated URL
|
clickContextShareLink(genericURL.url) // verify share intent is matched with associated URL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Ignore("Intermittent: https://github.com/mozilla-mobile/fenix/issues/12367")
|
||||||
@Test
|
@Test
|
||||||
fun verifyContextOpenImageNewTab() {
|
fun verifyContextOpenImageNewTab() {
|
||||||
val pageLinks =
|
val pageLinks =
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "ads@mozac.org"
|
||||||
|
}
|
||||||
|
},
|
||||||
"name": "Mozilla Android Components - Ads",
|
"name": "Mozilla Android Components - Ads",
|
||||||
"version": "1.0",
|
"version": "${version}",
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["https://*/*"],
|
"matches": ["https://*/*"],
|
||||||
|
@ -16,6 +21,7 @@
|
||||||
],
|
],
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"geckoViewAddons",
|
"geckoViewAddons",
|
||||||
"nativeMessaging"
|
"nativeMessaging",
|
||||||
|
"nativeMessagingFromContent"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
|
"applications": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "cookies@mozac.org"
|
||||||
|
}
|
||||||
|
},
|
||||||
"name": "Mozilla Android Components - Cookies",
|
"name": "Mozilla Android Components - Cookies",
|
||||||
"version": "1.0",
|
"version": "${version}",
|
||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["https://*/*"],
|
"matches": ["https://*/*"],
|
||||||
|
@ -23,6 +28,7 @@
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"geckoViewAddons",
|
"geckoViewAddons",
|
||||||
"nativeMessaging",
|
"nativeMessaging",
|
||||||
|
"nativeMessagingFromContent",
|
||||||
"webNavigation",
|
"webNavigation",
|
||||||
"webRequest",
|
"webRequest",
|
||||||
"webRequestBlocking",
|
"webRequestBlocking",
|
|
@ -277,8 +277,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||||
EngineView::class.java.name -> components.core.engine.createView(context, attrs).apply {
|
EngineView::class.java.name -> components.core.engine.createView(context, attrs).apply {
|
||||||
selectionActionDelegate = DefaultSelectionActionDelegate(
|
selectionActionDelegate = DefaultSelectionActionDelegate(
|
||||||
getSearchAdapter(components.core.store),
|
getSearchAdapter(components.core.store),
|
||||||
resources = context.resources,
|
resources = context.resources
|
||||||
appName = getString(R.string.app_name)
|
|
||||||
) {
|
) {
|
||||||
share(it)
|
share(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ import androidx.annotation.StringRes
|
||||||
import mozilla.components.feature.contextmenu.ContextMenuCandidate
|
import mozilla.components.feature.contextmenu.ContextMenuCandidate
|
||||||
import org.mozilla.fenix.components.FenixSnackbar
|
import org.mozilla.fenix.components.FenixSnackbar
|
||||||
|
|
||||||
class FenixSnackbarDelegate(val view: View) :
|
class FenixSnackbarDelegate(private val view: View) : ContextMenuCandidate.SnackbarDelegate {
|
||||||
ContextMenuCandidate.SnackbarDelegate {
|
|
||||||
override fun show(
|
override fun show(
|
||||||
snackBarParentView: View,
|
snackBarParentView: View,
|
||||||
@StringRes text: Int,
|
@StringRes text: Int,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import androidx.annotation.LayoutRes
|
import androidx.annotation.LayoutRes
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
@ -29,6 +30,8 @@ import kotlinx.android.synthetic.main.component_browser_top_toolbar.*
|
||||||
import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.*
|
import kotlinx.android.synthetic.main.component_browser_top_toolbar.view.*
|
||||||
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
|
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
|
import mozilla.components.browser.state.selector.selectedTab
|
||||||
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||||
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBottomBehavior
|
import mozilla.components.browser.toolbar.behavior.BrowserToolbarBottomBehavior
|
||||||
import mozilla.components.browser.toolbar.display.DisplayToolbar
|
import mozilla.components.browser.toolbar.display.DisplayToolbar
|
||||||
|
@ -94,9 +97,6 @@ class BrowserToolbarView(
|
||||||
view.context.resources.getDimensionPixelSize(R.dimen.context_menu_height),
|
view.context.resources.getDimensionPixelSize(R.dimen.context_menu_height),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|
||||||
val selectedSession = container.context.components.core.sessionManager.selectedSession
|
|
||||||
|
|
||||||
popupWindow.elevation =
|
popupWindow.elevation =
|
||||||
view.context.resources.getDimension(R.dimen.mozac_browser_menu_elevation)
|
view.context.resources.getDimension(R.dimen.mozac_browser_menu_elevation)
|
||||||
|
|
||||||
|
@ -110,11 +110,7 @@ class BrowserToolbarView(
|
||||||
|
|
||||||
customView.copy.setOnClickListener {
|
customView.copy.setOnClickListener {
|
||||||
popupWindow.dismiss()
|
popupWindow.dismiss()
|
||||||
if (isCustomTabSession) {
|
clipboard.text = getUrlForClipboard(it.context.components.core.store, customTabSession)
|
||||||
clipboard.text = customTabSession?.url
|
|
||||||
} else {
|
|
||||||
clipboard.text = selectedSession?.url
|
|
||||||
}
|
|
||||||
|
|
||||||
FenixSnackbar.make(
|
FenixSnackbar.make(
|
||||||
view = view,
|
view = view,
|
||||||
|
@ -300,5 +296,15 @@ class BrowserToolbarView(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TOOLBAR_ELEVATION = 16
|
private const val TOOLBAR_ELEVATION = 16
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
internal fun getUrlForClipboard(store: BrowserStore, customTabSession: Session? = null): String? {
|
||||||
|
return if (customTabSession != null) {
|
||||||
|
customTabSession.url
|
||||||
|
} else {
|
||||||
|
val selectedTab = store.state.selectedTab
|
||||||
|
selectedTab?.readerState?.activeUrl ?: selectedTab?.content?.url
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,19 +14,13 @@ import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
|
||||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
||||||
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
||||||
|
|
||||||
sealed class AdapterItem {
|
|
||||||
object DeleteButton : AdapterItem()
|
|
||||||
object Header : AdapterItem()
|
|
||||||
data class Item(val item: TrackingProtectionException) : AdapterItem()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for a list of sites that are exempted from Tracking Protection,
|
* Adapter for a list of sites that are exempted from Tracking Protection,
|
||||||
* along with controls to remove the exception.
|
* along with controls to remove the exception.
|
||||||
*/
|
*/
|
||||||
class ExceptionsAdapter(
|
class ExceptionsAdapter(
|
||||||
private val interactor: ExceptionsInteractor
|
private val interactor: ExceptionsInteractor
|
||||||
) : ListAdapter<AdapterItem, RecyclerView.ViewHolder>(DiffCallback) {
|
) : ListAdapter<ExceptionsAdapter.AdapterItem, RecyclerView.ViewHolder>(DiffCallback) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the list of items that are displayed.
|
* Change the list of items that are displayed.
|
||||||
|
@ -67,6 +61,12 @@ class ExceptionsAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AdapterItem {
|
||||||
|
object DeleteButton : AdapterItem()
|
||||||
|
object Header : AdapterItem()
|
||||||
|
data class Item(val item: TrackingProtectionException) : AdapterItem()
|
||||||
|
}
|
||||||
|
|
||||||
private object DiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
|
private object DiffCallback : DiffUtil.ItemCallback<AdapterItem>() {
|
||||||
override fun areItemsTheSame(oldItem: AdapterItem, newItem: AdapterItem) =
|
override fun areItemsTheSame(oldItem: AdapterItem, newItem: AdapterItem) =
|
||||||
areContentsTheSame(oldItem, newItem)
|
areContentsTheSame(oldItem, newItem)
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.mozilla.fenix.settings.SupportUtils
|
||||||
* along with controls to remove the exception.
|
* along with controls to remove the exception.
|
||||||
*/
|
*/
|
||||||
class ExceptionsFragment : Fragment() {
|
class ExceptionsFragment : Fragment() {
|
||||||
|
|
||||||
private lateinit var exceptionsStore: ExceptionsFragmentStore
|
private lateinit var exceptionsStore: ExceptionsFragmentStore
|
||||||
private lateinit var exceptionsView: ExceptionsView
|
private lateinit var exceptionsView: ExceptionsView
|
||||||
private lateinit var exceptionsInteractor: ExceptionsInteractor
|
private lateinit var exceptionsInteractor: ExceptionsInteractor
|
||||||
|
@ -48,7 +49,7 @@ class ExceptionsFragment : Fragment() {
|
||||||
exceptionsStore = StoreProvider.get(this) {
|
exceptionsStore = StoreProvider.get(this) {
|
||||||
ExceptionsFragmentStore(
|
ExceptionsFragmentStore(
|
||||||
ExceptionsFragmentState(
|
ExceptionsFragmentState(
|
||||||
items = listOf()
|
items = emptyList()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -61,7 +62,6 @@ class ExceptionsFragment : Fragment() {
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
consumeFrom(exceptionsStore) {
|
consumeFrom(exceptionsStore) {
|
||||||
exceptionsView.update(it)
|
exceptionsView.update(it)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.exceptions
|
package org.mozilla.fenix.exceptions
|
||||||
|
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.text.style.UnderlineSpan
|
import android.text.style.UnderlineSpan
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import androidx.core.text.toSpannable
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import kotlinx.android.synthetic.main.component_exceptions.view.*
|
import kotlinx.android.synthetic.main.component_exceptions.*
|
||||||
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
|
||||||
|
@ -42,35 +42,36 @@ interface ExceptionsViewInteractor {
|
||||||
* View that contains and configures the Exceptions List
|
* View that contains and configures the Exceptions List
|
||||||
*/
|
*/
|
||||||
class ExceptionsView(
|
class ExceptionsView(
|
||||||
override val containerView: ViewGroup,
|
container: ViewGroup,
|
||||||
val interactor: ExceptionsInteractor
|
interactor: ExceptionsInteractor
|
||||||
) : LayoutContainer {
|
) : LayoutContainer {
|
||||||
|
|
||||||
val view: FrameLayout = LayoutInflater.from(containerView.context)
|
override val containerView: FrameLayout = LayoutInflater.from(container.context)
|
||||||
.inflate(R.layout.component_exceptions, containerView, true)
|
.inflate(R.layout.component_exceptions, container, true)
|
||||||
.findViewById(R.id.exceptions_wrapper)
|
.findViewById(R.id.exceptions_wrapper)
|
||||||
|
|
||||||
private val exceptionsAdapter = ExceptionsAdapter(interactor)
|
private val exceptionsAdapter = ExceptionsAdapter(interactor)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
view.exceptions_list.apply {
|
exceptions_list.apply {
|
||||||
adapter = exceptionsAdapter
|
adapter = exceptionsAdapter
|
||||||
layoutManager = LinearLayoutManager(containerView.context)
|
layoutManager = LinearLayoutManager(container.context)
|
||||||
}
|
}
|
||||||
val learnMoreText = view.exceptions_learn_more.text.toString()
|
|
||||||
val textWithLink = SpannableString(learnMoreText).apply {
|
with(exceptions_learn_more) {
|
||||||
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
|
val learnMoreText = text
|
||||||
}
|
text = learnMoreText.toSpannable().apply {
|
||||||
with(view.exceptions_learn_more) {
|
setSpan(UnderlineSpan(), 0, learnMoreText.length, 0)
|
||||||
|
}
|
||||||
|
|
||||||
movementMethod = LinkMovementMethod.getInstance()
|
movementMethod = LinkMovementMethod.getInstance()
|
||||||
text = textWithLink
|
|
||||||
setOnClickListener { interactor.onLearnMore() }
|
setOnClickListener { interactor.onLearnMore() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(state: ExceptionsFragmentState) {
|
fun update(state: ExceptionsFragmentState) {
|
||||||
view.exceptions_empty_view.isVisible = state.items.isEmpty()
|
exceptions_empty_view.isVisible = state.items.isEmpty()
|
||||||
view.exceptions_list.isVisible = state.items.isNotEmpty()
|
exceptions_list.isVisible = state.items.isNotEmpty()
|
||||||
exceptionsAdapter.updateData(state.items)
|
exceptionsAdapter.updateData(state.items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@
|
||||||
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
|
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.Button
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.*
|
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import mozilla.components.service.fxa.manager.SignInWithShareableAccountResult
|
import mozilla.components.service.fxa.manager.SignInWithShareableAccountResult
|
||||||
import mozilla.components.service.fxa.sharing.ShareableAccount
|
import mozilla.components.service.fxa.sharing.ShareableAccount
|
||||||
|
@ -20,42 +22,18 @@ import org.mozilla.fenix.components.FenixSnackbar
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
|
||||||
class OnboardingAutomaticSignInViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
class OnboardingAutomaticSignInViewHolder(
|
||||||
|
view: View,
|
||||||
|
private val scope: CoroutineScope = MainScope()
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
private lateinit var shareableAccount: ShareableAccount
|
private lateinit var shareableAccount: ShareableAccount
|
||||||
private val headerText = view.header_text
|
private val headerText = view.header_text
|
||||||
|
|
||||||
init {
|
init {
|
||||||
view.turn_on_sync_button.setOnClickListener {
|
view.turn_on_sync_button.setOnClickListener {
|
||||||
it.context.components.analytics.metrics.track(Event.OnboardingAutoSignIn)
|
scope.launch {
|
||||||
|
onClick(it.turn_on_sync_button)
|
||||||
it.turn_on_sync_button.text = it.context.getString(
|
|
||||||
R.string.onboarding_firefox_account_signing_in
|
|
||||||
)
|
|
||||||
it.turn_on_sync_button.isEnabled = false
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
val result = view.context.components.backgroundServices.accountManager
|
|
||||||
.signInWithShareableAccountAsync(shareableAccount).await()
|
|
||||||
when (result) {
|
|
||||||
SignInWithShareableAccountResult.Failure -> {
|
|
||||||
// Failed to sign-in (e.g. bad credentials). Allow to try again.
|
|
||||||
it.turn_on_sync_button.text = it.context.getString(
|
|
||||||
R.string.onboarding_firefox_account_auto_signin_confirm
|
|
||||||
)
|
|
||||||
it.turn_on_sync_button.isEnabled = true
|
|
||||||
FenixSnackbar.make(
|
|
||||||
view = it,
|
|
||||||
duration = Snackbar.LENGTH_SHORT,
|
|
||||||
isDisplayedWithBrowserToolbar = false
|
|
||||||
).setText(
|
|
||||||
it.context.getString(R.string.onboarding_firefox_account_automatic_signin_failed)
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
SignInWithShareableAccountResult.WillRetry, SignInWithShareableAccountResult.Success -> {
|
|
||||||
// We consider both of these as a 'success'.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +47,34 @@ class OnboardingAutomaticSignInViewHolder(view: View) : RecyclerView.ViewHolder(
|
||||||
headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
|
headerText.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
internal suspend fun onClick(button: Button) {
|
||||||
|
val context = button.context
|
||||||
|
context.components.analytics.metrics.track(Event.OnboardingAutoSignIn)
|
||||||
|
|
||||||
|
button.text = context.getString(R.string.onboarding_firefox_account_signing_in)
|
||||||
|
button.isEnabled = false
|
||||||
|
|
||||||
|
val accountManager = context.components.backgroundServices.accountManager
|
||||||
|
when (accountManager.signInWithShareableAccountAsync(shareableAccount).await()) {
|
||||||
|
SignInWithShareableAccountResult.Failure -> {
|
||||||
|
// Failed to sign-in (e.g. bad credentials). Allow to try again.
|
||||||
|
button.text = context.getString(R.string.onboarding_firefox_account_auto_signin_confirm)
|
||||||
|
button.isEnabled = true
|
||||||
|
FenixSnackbar.make(
|
||||||
|
view = button,
|
||||||
|
duration = Snackbar.LENGTH_SHORT,
|
||||||
|
isDisplayedWithBrowserToolbar = false
|
||||||
|
).setText(
|
||||||
|
context.getString(R.string.onboarding_firefox_account_automatic_signin_failed)
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
SignInWithShareableAccountResult.WillRetry, SignInWithShareableAccountResult.Success -> {
|
||||||
|
// We consider both of these as a 'success'.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val LAYOUT_ID = R.layout.onboarding_automatic_signin
|
const val LAYOUT_ID = R.layout.onboarding_automatic_signin
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,6 @@ abstract class BaseSearchTelemetry {
|
||||||
engine.installWebExtension(
|
engine.installWebExtension(
|
||||||
id = extensionInfo.id,
|
id = extensionInfo.id,
|
||||||
url = extensionInfo.resourceUrl,
|
url = extensionInfo.resourceUrl,
|
||||||
allowContentMessaging = true,
|
|
||||||
onSuccess = { extension ->
|
onSuccess = { extension ->
|
||||||
store.flowScoped { flow -> subscribeToUpdates(flow, extension, extensionInfo) }
|
store.flowScoped { flow -> subscribeToUpdates(flow, extension, extensionInfo) }
|
||||||
},
|
},
|
||||||
|
|
|
@ -51,7 +51,7 @@ class AdsTelemetry(private val metrics: MetricController) : BaseSearchTelemetry(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal const val ADS_EXTENSION_ID = "mozacBrowserAds"
|
internal const val ADS_EXTENSION_ID = "ads@mozac.org"
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal const val ADS_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/ads/"
|
internal const val ADS_EXTENSION_RESOURCE_URL = "resource://android/assets/extensions/ads/"
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
@ -131,7 +131,7 @@ class InContentTelemetry(private val metrics: MetricController) : BaseSearchTele
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal const val COOKIES_EXTENSION_ID = "BrowserCookiesExtension"
|
internal const val COOKIES_EXTENSION_ID = "cookies@mozac.org"
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
internal const val COOKIES_EXTENSION_RESOURCE_URL =
|
internal const val COOKIES_EXTENSION_RESOURCE_URL =
|
||||||
"resource://android/assets/extensions/cookies/"
|
"resource://android/assets/extensions/cookies/"
|
||||||
|
|
|
@ -192,6 +192,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
||||||
getString(R.string.snackbar_deleted_undo),
|
getString(R.string.snackbar_deleted_undo),
|
||||||
{
|
{
|
||||||
sessionManager.add(snapshot.session, isSelected, engineSessionState = state)
|
sessionManager.add(snapshot.session, isSelected, engineSessionState = state)
|
||||||
|
tabTrayView.scrollToTab(snapshot.session.id)
|
||||||
},
|
},
|
||||||
operation = { },
|
operation = { },
|
||||||
elevation = ELEVATION,
|
elevation = ELEVATION,
|
||||||
|
|
|
@ -126,7 +126,7 @@ class TabTrayView(
|
||||||
}
|
}
|
||||||
if (!hasLoaded) {
|
if (!hasLoaded) {
|
||||||
hasLoaded = true
|
hasLoaded = true
|
||||||
scrollToSelectedTab()
|
scrollToTab(view.context.components.core.store.state.selectedTabId)
|
||||||
if (view.context.settings().accessibilityServicesEnabled) {
|
if (view.context.settings().accessibilityServicesEnabled) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
delay(SELECTION_DELAY.toLong())
|
delay(SELECTION_DELAY.toLong())
|
||||||
|
@ -145,27 +145,30 @@ class TabTrayView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tabTrayItemMenu = TabTrayItemMenu(view.context, { view.tab_layout.selectedTabPosition == 0 }) {
|
tabTrayItemMenu =
|
||||||
when (it) {
|
TabTrayItemMenu(view.context, { view.tab_layout.selectedTabPosition == 0 }) {
|
||||||
is TabTrayItemMenu.Item.ShareAllTabs -> interactor.onShareTabsClicked(
|
when (it) {
|
||||||
isPrivateModeSelected
|
is TabTrayItemMenu.Item.ShareAllTabs -> interactor.onShareTabsClicked(
|
||||||
)
|
isPrivateModeSelected
|
||||||
is TabTrayItemMenu.Item.SaveToCollection -> interactor.onSaveToCollectionClicked()
|
)
|
||||||
is TabTrayItemMenu.Item.CloseAllTabs -> interactor.onCloseAllTabsClicked(
|
is TabTrayItemMenu.Item.SaveToCollection -> interactor.onSaveToCollectionClicked()
|
||||||
isPrivateModeSelected
|
is TabTrayItemMenu.Item.CloseAllTabs -> interactor.onCloseAllTabsClicked(
|
||||||
)
|
isPrivateModeSelected
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
view.tab_tray_overflow.setOnClickListener {
|
view.tab_tray_overflow.setOnClickListener {
|
||||||
container.context.components.analytics.metrics.track(Event.TabsTrayMenuOpened)
|
container.context.components.analytics.metrics.track(Event.TabsTrayMenuOpened)
|
||||||
menu = tabTrayItemMenu.menuBuilder.build(container.context)
|
menu = tabTrayItemMenu.menuBuilder.build(container.context)
|
||||||
menu?.show(it)
|
menu?.show(it)
|
||||||
?.also { pu ->
|
?.also { pu ->
|
||||||
(pu.contentView as? CardView)?.setCardBackgroundColor(ContextCompat.getColor(
|
(pu.contentView as? CardView)?.setCardBackgroundColor(
|
||||||
view.context,
|
ContextCompat.getColor(
|
||||||
R.color.foundation_normal_theme
|
view.context,
|
||||||
))
|
R.color.foundation_normal_theme
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +214,7 @@ class TabTrayView(
|
||||||
filterTabs.invoke(filter)
|
filterTabs.invoke(filter)
|
||||||
|
|
||||||
updateState(view.context.components.core.store.state)
|
updateState(view.context.components.core.store.state)
|
||||||
scrollToSelectedTab()
|
scrollToTab(view.context.components.core.store.state.selectedTabId)
|
||||||
|
|
||||||
if (isPrivateModeSelected) {
|
if (isPrivateModeSelected) {
|
||||||
container.context.components.analytics.metrics.track(Event.TabsTrayPrivateModeTapped)
|
container.context.components.analytics.metrics.track(Event.TabsTrayPrivateModeTapped)
|
||||||
|
@ -220,8 +223,11 @@ class TabTrayView(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabReselected(tab: TabLayout.Tab?) { /*noop*/ }
|
override fun onTabReselected(tab: TabLayout.Tab?) { /*noop*/
|
||||||
override fun onTabUnselected(tab: TabLayout.Tab?) { /*noop*/ }
|
}
|
||||||
|
|
||||||
|
override fun onTabUnselected(tab: TabLayout.Tab?) { /*noop*/
|
||||||
|
}
|
||||||
|
|
||||||
fun updateState(state: BrowserState) {
|
fun updateState(state: BrowserState) {
|
||||||
view.let {
|
view.let {
|
||||||
|
@ -266,14 +272,16 @@ class TabTrayView(
|
||||||
private fun toggleFabText(private: Boolean) {
|
private fun toggleFabText(private: Boolean) {
|
||||||
if (private) {
|
if (private) {
|
||||||
fabView.new_tab_button.extend()
|
fabView.new_tab_button.extend()
|
||||||
fabView.new_tab_button.contentDescription = view.context.resources.getString(R.string.add_private_tab)
|
fabView.new_tab_button.contentDescription =
|
||||||
|
view.context.resources.getString(R.string.add_private_tab)
|
||||||
} else {
|
} else {
|
||||||
fabView.new_tab_button.shrink()
|
fabView.new_tab_button.shrink()
|
||||||
fabView.new_tab_button.contentDescription = view.context.resources.getString(R.string.add_tab)
|
fabView.new_tab_button.contentDescription =
|
||||||
|
view.context.resources.getString(R.string.add_tab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scrollToSelectedTab() {
|
fun scrollToTab(sessionId: String?) {
|
||||||
(view.tabsTray as? BrowserTabsTray)?.also { tray ->
|
(view.tabsTray as? BrowserTabsTray)?.also { tray ->
|
||||||
val tabs = if (isPrivateModeSelected) {
|
val tabs = if (isPrivateModeSelected) {
|
||||||
view.context.components.core.store.state.privateTabs
|
view.context.components.core.store.state.privateTabs
|
||||||
|
@ -282,7 +290,7 @@ class TabTrayView(
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedBrowserTabIndex = tabs
|
val selectedBrowserTabIndex = tabs
|
||||||
.indexOfFirst { it.id == view.context.components.core.store.state.selectedTabId }
|
.indexOfFirst { it.id == sessionId }
|
||||||
|
|
||||||
tray.layoutManager?.scrollToPosition(selectedBrowserTabIndex)
|
tray.layoutManager?.scrollToPosition(selectedBrowserTabIndex)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
android:pathData="M13.36 11.98l4.38-4.38a0.95 0.95 0 0 0-1.34-1.34l-4.38 4.38-4.38-4.38A0.95 0.95 0 0 0 6.3 7.6l4.38 4.38-4.38 4.38a0.95 0.95 0 1 0 1.34 1.34l4.38-4.38 4.38 4.38a0.95 0.95 0 0 0 1.34-1.34l-4.38-4.38z"
|
android:fillColor="?primaryText"
|
||||||
android:fillColor="?primaryText" />
|
android:pathData="m18.5,17.0962 l-5.1,-5.0962 5.1,-5.0962c0.3905,-0.3905 0.3905,-1.0133 0,-1.4038s-1.0133,-0.3905 -1.4038,0l-5.0962,5.1 -5.0962,-5.1c-0.3905,-0.3905 -1.0133,-0.3905 -1.4038,0s-0.3905,1.0133 0,1.4038l5.1,5.0962 -5.1,5.0962c-0.3905,0.3905 -0.3905,1.0133 0,1.4038s1.0133,0.3905 1.4038,0l5.0962,-5.1 5.0962,5.1c0.3905,0.3905 1.0133,0.3905 1.4038,0s0.3905,-1.0133 0,-1.4038z" />
|
||||||
</vector>
|
</vector>
|
||||||
|
|
|
@ -11,12 +11,15 @@
|
||||||
<string name="content_description_disable_private_browsing_button">عطّل التصفّح الخاص</string>
|
<string name="content_description_disable_private_browsing_button">عطّل التصفّح الخاص</string>
|
||||||
<!-- Placeholder text shown in the search bar before a user enters text -->
|
<!-- Placeholder text shown in the search bar before a user enters text -->
|
||||||
<string name="search_hint">ابحث أو أدخِل عنوانا</string>
|
<string name="search_hint">ابحث أو أدخِل عنوانا</string>
|
||||||
<!-- No Open Tabs Message Header -->
|
|
||||||
<string name="no_open_tabs_header_2">لا ألسنة مفتوحة</string>
|
|
||||||
|
|
||||||
<!-- No Open Tabs Message Description -->
|
<!-- No Open Tabs Message Description -->
|
||||||
<string name="no_open_tabs_description">ستظهر الألسنة المفتوحة هنا.</string>
|
<string name="no_open_tabs_description">ستظهر الألسنة المفتوحة هنا.</string>
|
||||||
|
|
||||||
|
<!-- No Private Tabs Message Description -->
|
||||||
|
<string name="no_private_tabs_description">ستظهر الألسنة الخاصة هنا.</string>
|
||||||
|
<!-- Message announced to the user when tab tray is selected with 1 tab -->
|
||||||
|
<string name="open_tab_tray_single">لسان واحد مفتوح. انقر لتبديل الألسنة.</string>
|
||||||
|
|
||||||
<!-- Private Browsing -->
|
<!-- Private Browsing -->
|
||||||
<!-- Title for private session option -->
|
<!-- Title for private session option -->
|
||||||
<string name="private_browsing_title">أنت في جلسة خاصة</string>
|
<string name="private_browsing_title">أنت في جلسة خاصة</string>
|
||||||
|
@ -28,7 +31,7 @@
|
||||||
<!-- Delete session button to erase your history in a private session -->
|
<!-- Delete session button to erase your history in a private session -->
|
||||||
<string name="private_browsing_delete_session">احذف الجلسة</string>
|
<string name="private_browsing_delete_session">احذف الجلسة</string>
|
||||||
|
|
||||||
<!-- Private mode shortcut "contextual feature recommender" (CFR) -->
|
<!-- Private mode shortcut "contextual feature recommendation" (CFR) -->
|
||||||
<!-- Text for the main message -->
|
<!-- Text for the main message -->
|
||||||
<string name="cfr_message">أضِف اختصارًا لفتح الألسنة الخاصة من الشاشة الرئيسية.</string>
|
<string name="cfr_message">أضِف اختصارًا لفتح الألسنة الخاصة من الشاشة الرئيسية.</string>
|
||||||
<!-- Text for the positive button -->
|
<!-- Text for the positive button -->
|
||||||
|
@ -48,6 +51,10 @@
|
||||||
<!-- Browser Fragment -->
|
<!-- Browser Fragment -->
|
||||||
<!-- Content description (not visible, for screen readers etc.): Navigate to open tabs -->
|
<!-- Content description (not visible, for screen readers etc.): Navigate to open tabs -->
|
||||||
<string name="browser_tabs_button">الألسنة المفتوحة</string>
|
<string name="browser_tabs_button">الألسنة المفتوحة</string>
|
||||||
|
<!-- Content description (not visible, for screen readers etc.): Navigate backward (browsing history) -->
|
||||||
|
<string name="browser_menu_back">السابق</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 -->
|
<!-- Content description (not visible, for screen readers etc.): Refresh current website -->
|
||||||
<string name="browser_menu_refresh">أعِد التحميل</string>
|
<string name="browser_menu_refresh">أعِد التحميل</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Stop loading current website -->
|
<!-- Content description (not visible, for screen readers etc.): Stop loading current website -->
|
||||||
|
@ -82,8 +89,6 @@
|
||||||
<string name="browser_menu_new_tab">لسان جديد</string>
|
<string name="browser_menu_new_tab">لسان جديد</string>
|
||||||
<!-- Browser menu button that saves the current tab to a collection -->
|
<!-- Browser menu button that saves the current tab to a collection -->
|
||||||
<string name="browser_menu_save_to_collection_2">احفظ في التجميعة</string>
|
<string name="browser_menu_save_to_collection_2">احفظ في التجميعة</string>
|
||||||
<!-- Browser menu button that opens a dialog to report issues with the current site -->
|
|
||||||
<string name="browser_menu_report_issue">أبلِغ عن مشكلة بالموقع</string>
|
|
||||||
<!-- Browser menu button that open a share menu to share the current site -->
|
<!-- Browser menu button that open a share menu to share the current site -->
|
||||||
<string name="browser_menu_share">شارِك</string>
|
<string name="browser_menu_share">شارِك</string>
|
||||||
<!-- Share menu title, displayed when a user is sharing their current site -->
|
<!-- Share menu title, displayed when a user is sharing their current site -->
|
||||||
|
@ -97,13 +102,17 @@
|
||||||
<!-- Browser menu text shown in custom tabs to indicate this is a Fenix tab
|
<!-- 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) -->
|
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
|
||||||
<string name="browser_menu_powered_by2">تدعمها %1$s</string>
|
<string name="browser_menu_powered_by2">تدعمها %1$s</string>
|
||||||
<!-- Browser menu button to put the the current page in reader mode -->
|
<!-- Browser menu button to put the current page in reader mode -->
|
||||||
<string name="browser_menu_read">منظور القارئ</string>
|
<string name="browser_menu_read">منظور القارئ</string>
|
||||||
<!-- Browser menu button to open the current page in an external app -->
|
<!-- Browser menu button to open the current page in an external app -->
|
||||||
<string name="browser_menu_open_app_link">افتح في التطبيق</string>
|
<string name="browser_menu_open_app_link">افتح في التطبيق</string>
|
||||||
<!-- Browser menu button to configure reader mode appearance e.g. the used font type and size -->
|
<!-- Browser menu button to configure reader mode appearance e.g. the used font type and size -->
|
||||||
<string name="browser_menu_read_appearance">المظهر</string>
|
<string name="browser_menu_read_appearance">المظهر</string>
|
||||||
|
|
||||||
|
<!-- Error message to show when the user tries to access a scheme not
|
||||||
|
handled by the app (Ex: blob, tel etc) -->
|
||||||
|
<string name="unknown_scheme_error_message">تعذّر الاتصال، لم أتعرّف على مخطّط المسار.</string>
|
||||||
|
|
||||||
<!-- Locale Settings Fragment -->
|
<!-- Locale Settings Fragment -->
|
||||||
<!-- Content description for tick mark on selected language -->
|
<!-- Content description for tick mark on selected language -->
|
||||||
<string name="a11y_selected_locale_content_description">اللغة المحددة</string>
|
<string name="a11y_selected_locale_content_description">اللغة المحددة</string>
|
||||||
|
@ -335,6 +344,11 @@
|
||||||
<!-- Preference for using bottom toolbar -->
|
<!-- Preference for using bottom toolbar -->
|
||||||
<string name="preference_bottom_toolbar">بالأسفل</string>
|
<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 -->
|
<!-- Preference for using using dark or light theme automatically set by battery -->
|
||||||
<string name="preference_auto_battery_theme">حسب وضع توفير الطاقة</string>
|
<string name="preference_auto_battery_theme">حسب وضع توفير الطاقة</string>
|
||||||
<!-- Preference for using following device theme -->
|
<!-- Preference for using following device theme -->
|
||||||
|
|
|
@ -489,6 +489,11 @@
|
||||||
<!-- Text shown when no history exists -->
|
<!-- Text shown when no history exists -->
|
||||||
<string name="history_empty_message">Няма гісторыі</string>
|
<string name="history_empty_message">Няма гісторыі</string>
|
||||||
|
|
||||||
|
<!-- Crashes -->
|
||||||
|
<!-- Title text displayed on the tab crash page. This first parameter is the name of the application (For example: Fenix) -->
|
||||||
|
<string name="tab_crash_title_2">Выбачайце. %1$s не можа загрузіць гэтую старонку.</string>
|
||||||
|
<!-- Description text displayed on the tab crash page -->
|
||||||
|
<string name="tab_crash_description">Вы можаце паспрабаваць аднавіць ці закрыць гэтую картку ніжэй.</string>
|
||||||
<!-- Send crash report checkbox text on the tab crash page -->
|
<!-- Send crash report checkbox text on the tab crash page -->
|
||||||
<string name="tab_crash_send_report">Адправіць справаздачу аб краху ў Mozilla</string>
|
<string name="tab_crash_send_report">Адправіць справаздачу аб краху ў Mozilla</string>
|
||||||
<!-- Close tab button text on the tab crash page -->
|
<!-- Close tab button text on the tab crash page -->
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
<!-- No Private Tabs Message Description -->
|
<!-- No Private Tabs Message Description -->
|
||||||
<string name="no_private_tabs_description">Tus pestañas privadas aparecerán aquí.</string>
|
<string name="no_private_tabs_description">Tus pestañas privadas aparecerán aquí.</string>
|
||||||
|
|
||||||
|
<!-- Message announced to the user when tab tray is selected with 1 tab -->
|
||||||
|
<string name="open_tab_tray_single">1 pestaña abierta. Tocar para cambiar de pestaña.</string>
|
||||||
|
<!-- Message announced to the user when tab tray is selected with 0 or 2+ tabs -->
|
||||||
|
<string name="open_tab_tray_plural">%1$s pestañas abiertas. Tocar para cambiar de pestaña.</string>
|
||||||
|
|
||||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||||
<string name="about_content">%1$s es producido por Mozilla.</string>
|
<string name="about_content">%1$s es producido por Mozilla.</string>
|
||||||
|
|
||||||
|
@ -116,6 +121,8 @@
|
||||||
<string name="browser_menu_powered_by2">Patrocinado por %1$s</string>
|
<string name="browser_menu_powered_by2">Patrocinado por %1$s</string>
|
||||||
<!-- Browser menu button to put the current page in reader mode -->
|
<!-- Browser menu button to put the current page in reader mode -->
|
||||||
<string name="browser_menu_read">Vista de lectura</string>
|
<string name="browser_menu_read">Vista de lectura</string>
|
||||||
|
<!-- Browser menu button content description to close reader mode and return the user to the regular browser -->
|
||||||
|
<string name="browser_menu_read_close">Salir de vista de lectura</string>
|
||||||
<!-- Browser menu button to open the current page in an external app -->
|
<!-- Browser menu button to open the current page in an external app -->
|
||||||
<string name="browser_menu_open_app_link">Abrir en la aplicación</string>
|
<string name="browser_menu_open_app_link">Abrir en la aplicación</string>
|
||||||
|
|
||||||
|
@ -288,6 +295,8 @@
|
||||||
<string name="preferences_sync_bookmarks">Marcadores</string>
|
<string name="preferences_sync_bookmarks">Marcadores</string>
|
||||||
<!-- Preference for syncing logins -->
|
<!-- Preference for syncing logins -->
|
||||||
<string name="preferences_sync_logins">Inicios de sesión</string>
|
<string name="preferences_sync_logins">Inicios de sesión</string>
|
||||||
|
<!-- Preference for syncing tabs -->
|
||||||
|
<string name="preferences_sync_tabs_2">Pestañas abiertas</string>
|
||||||
<!-- Preference for signing out -->
|
<!-- Preference for signing out -->
|
||||||
<string name="preferences_sign_out">Cerrar sesión</string>
|
<string name="preferences_sign_out">Cerrar sesión</string>
|
||||||
<!-- Preference displays and allows changing current FxA device name -->
|
<!-- Preference displays and allows changing current FxA device name -->
|
||||||
|
@ -442,6 +451,24 @@
|
||||||
<string name="tabs_header_private_tabs_title">Pestañas privadas</string>
|
<string name="tabs_header_private_tabs_title">Pestañas privadas</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
|
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
|
||||||
<string name="add_tab">Agregar pestaña</string>
|
<string name="add_tab">Agregar pestaña</string>
|
||||||
|
<!-- Content description (not visible, for screen readers etc.): Add tab button. Adds a news tab when pressed -->
|
||||||
|
<string name="add_private_tab">Agregar pestaña privada</string>
|
||||||
|
<!-- Text for the new tab button to indicate adding a new private tab in the tab -->
|
||||||
|
<string name="tab_drawer_fab_content">Privada</string>
|
||||||
|
<!-- Text shown as the title of the open tab tray -->
|
||||||
|
<string name="tab_tray_title">Pestañas abiertas</string>
|
||||||
|
<!-- Text shown in the menu for saving tabs to a collection -->
|
||||||
|
<string name="tab_tray_menu_item_save">Guardar en colección</string>
|
||||||
|
<!-- Text shown in the menu for sharing all tabs -->
|
||||||
|
<string name="tab_tray_menu_item_share">Compartir todas las pestañas</string>
|
||||||
|
<!-- Text shown in the menu for closing all tabs -->
|
||||||
|
<string name="tab_tray_menu_item_close">Cerrar todas las pestañas</string>
|
||||||
|
<!-- Shortcut action to open new tab -->
|
||||||
|
<string name="tab_tray_menu_open_new_tab">Nueva pestaña</string>
|
||||||
|
<!-- Shortcut action to open the home screen -->
|
||||||
|
<string name="tab_tray_menu_home">Ir a Inicio</string>
|
||||||
|
<!-- Shortcut action to toggle private mode -->
|
||||||
|
<string name="tab_tray_menu_toggle">Alternar modo de pestaña</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Removes tab from collection button. Removes the selected tab from collection when pressed -->
|
<!-- Content description (not visible, for screen readers etc.): Removes tab from collection button. Removes the selected tab from collection when pressed -->
|
||||||
<string name="remove_tab_from_collection">Eliminar la pestaña de la colección</string>
|
<string name="remove_tab_from_collection">Eliminar la pestaña de la colección</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
|
<!-- Content description (not visible, for screen readers etc.): Close tab button. Closes the current session when pressed -->
|
||||||
|
@ -454,6 +481,8 @@
|
||||||
<string name="tabs_menu_close_all_tabs">Cerrar todas las pestañas</string>
|
<string name="tabs_menu_close_all_tabs">Cerrar todas las pestañas</string>
|
||||||
<!-- Open tabs menu item to share all tabs -->
|
<!-- Open tabs menu item to share all tabs -->
|
||||||
<string name="tabs_menu_share_tabs">Compartir pestañas</string>
|
<string name="tabs_menu_share_tabs">Compartir pestañas</string>
|
||||||
|
<!-- Open tabs menu item to save tabs to collection -->
|
||||||
|
<string name="tabs_menu_save_to_collection1">Guardar pestañas en la colección</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Opens the tab menu when pressed -->
|
<!-- Content description (not visible, for screen readers etc.): Opens the tab menu when pressed -->
|
||||||
<string name="tab_menu">Menú de pestaña</string>
|
<string name="tab_menu">Menú de pestaña</string>
|
||||||
<!-- Tab menu item to share the tab -->
|
<!-- Tab menu item to share the tab -->
|
||||||
|
@ -668,6 +697,10 @@
|
||||||
<string name="collections_header">Colecciones</string>
|
<string name="collections_header">Colecciones</string>
|
||||||
<!-- Content description (not visible, for screen readers etc.): Opens the collection menu when pressed -->
|
<!-- Content description (not visible, for screen readers etc.): Opens the collection menu when pressed -->
|
||||||
<string name="collection_menu_button_content_description">Menú de la colección</string>
|
<string name="collection_menu_button_content_description">Menú de la colección</string>
|
||||||
|
<!-- No Open Tabs Message Header -->
|
||||||
|
<string name="no_collections_header1">Colecciona las cosas que te importan</string>
|
||||||
|
<!-- Label to describe what collections are to a new user without any collections -->
|
||||||
|
<string name="no_collections_description1">Agrupa búsquedas, sitios y pestañas similares para un acceso rápido después.</string>
|
||||||
<!-- Title for the "select tabs" step of the collection creator -->
|
<!-- Title for the "select tabs" step of the collection creator -->
|
||||||
<string name="create_collection_select_tabs">Seleccionar pestañas</string>
|
<string name="create_collection_select_tabs">Seleccionar pestañas</string>
|
||||||
<!-- Title for the "select collection" step of the collection creator -->
|
<!-- Title for the "select collection" step of the collection creator -->
|
||||||
|
@ -697,6 +730,9 @@
|
||||||
<!-- Button to save currently selected tabs in the "select tabs" step of the collection creator-->
|
<!-- Button to save currently selected tabs in the "select tabs" step of the collection creator-->
|
||||||
<string name="create_collection_save">Guardar</string>
|
<string name="create_collection_save">Guardar</string>
|
||||||
|
|
||||||
|
<!-- Snackbar action to view the collection the user just created or updated -->
|
||||||
|
<string name="create_collection_view">Ver</string>
|
||||||
|
|
||||||
<!-- Default name for a new collection in "name new collection" step of the collection creator. %d is a placeholder for the number of collections-->
|
<!-- Default name for a new collection in "name new collection" step of the collection creator. %d is a placeholder for the number of collections-->
|
||||||
<string name="create_collection_default_name">Colección %d</string>
|
<string name="create_collection_default_name">Colección %d</string>
|
||||||
|
|
||||||
|
@ -845,8 +881,6 @@
|
||||||
<string name="preference_summary_delete_browsing_data_on_quit">Eliminar automáticamente los datos de navegación cuando selecciones "Salir" en el menú principal</string>
|
<string name="preference_summary_delete_browsing_data_on_quit">Eliminar automáticamente los datos de navegación cuando selecciones "Salir" 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. -->
|
<!-- 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">Eliminar automáticamente los datos de navegación cuando selecciones \"Salir\" en el menú principal</string>
|
<string name="preference_summary_delete_browsing_data_on_quit_2">Eliminar automáticamente los datos de navegación cuando selecciones \"Salir\" 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 -->
|
<!-- Action item in menu for the Delete browsing data on quit feature -->
|
||||||
<string name="delete_browsing_data_on_quit_action">Salir</string>
|
<string name="delete_browsing_data_on_quit_action">Salir</string>
|
||||||
|
|
||||||
|
@ -872,9 +906,26 @@
|
||||||
|
|
||||||
Sin embargo, puede ser menos estable. Descarga nuestro navegador beta para una experiencia más estable.</string>
|
Sin embargo, puede ser menos estable. Descarga nuestro navegador beta para una experiencia 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">Obtener Firefox para Android Beta</string>
|
||||||
|
|
||||||
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
|
<!-- text for firefox preview moving tip header. "Firefox Nightly" is intentionally hardcoded -->
|
||||||
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly se movió</string>
|
<string name="tip_firefox_preview_moved_header_preview_installed">Firefox Nightly se movió</string>
|
||||||
|
|
||||||
|
<!-- text for firefox preview moving tip description -->
|
||||||
|
<string name="tip_firefox_preview_moved_description_preview_installed">Esta aplicación ya no recibirá actualizaciones de seguridad. Deja de usarla y cambia al nuevo Nightly.
|
||||||
|
\n\nPara transferir tus marcadores, inicios de sesión e 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_installed">Cambia 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 ha trasladado</string>
|
||||||
|
<!-- text for firefox preview moving tip description -->
|
||||||
|
<string name="tip_firefox_preview_moved_description_preview_not_installed">Esta aplicación ya no recibirá actualizaciones de seguridad. Obtén el nuevo Nightly y deja de usar esta aplicación.
|
||||||
|
\n\nPara transferir tus marcadores, inicios de sesión e 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">Obtén el nuevo Nightly</string>
|
||||||
|
|
||||||
<!-- Onboarding -->
|
<!-- Onboarding -->
|
||||||
<!-- Text for onboarding welcome message
|
<!-- Text for onboarding welcome message
|
||||||
The first parameter is the name of the app (e.g. Firefox Preview) -->
|
The first parameter is the name of the app (e.g. Firefox Preview) -->
|
||||||
|
@ -910,11 +961,22 @@
|
||||||
<string name="onboarding_firefox_account_sync_is_on">Sync está activado</string>
|
<string name="onboarding_firefox_account_sync_is_on">Sync está activado</string>
|
||||||
<!-- text to display in the snackbar if automatic sign-in fails. user may try again -->
|
<!-- text to display in the snackbar if automatic sign-in fails. user may try again -->
|
||||||
<string name="onboarding_firefox_account_automatic_signin_failed">Error al iniciar sesión</string>
|
<string name="onboarding_firefox_account_automatic_signin_failed">Error al iniciar sesión</string>
|
||||||
|
<!-- text for the tracking protection onboarding card header -->
|
||||||
|
<string name="onboarding_tracking_protection_header_2">Privacidad automática</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">La configuración de privacidad y seguridad bloquea los rastreadores, el malware y las compañías que te siguen.</string>
|
||||||
|
<!-- text for tracking protection radio button option for standard level of blocking -->
|
||||||
|
<string name="onboarding_tracking_protection_standard_button_2">Estándar (predeterminado)</string>
|
||||||
|
<!-- text for standard blocking option button description -->
|
||||||
|
<string name="onboarding_tracking_protection_standard_button_description_2">Bloquea menos rastreadores. Las páginas se cargarán normalmente.</string>
|
||||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||||
<string name="onboarding_tracking_protection_strict_button">Estricta (recomendada)</string>
|
<string name="onboarding_tracking_protection_strict_button">Estricta (recomendada)</string>
|
||||||
|
|
||||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||||
<string name="onboarding_tracking_protection_strict_option">Estricto</string>
|
<string name="onboarding_tracking_protection_strict_option">Estricto</string>
|
||||||
|
<!-- text for strict blocking option button description -->
|
||||||
|
<string name="onboarding_tracking_protection_strict_button_description_2">Bloquear más rastreadores, publicidad y ventanas emergentes. Las páginas cargan más rápido, pero pueden tener problemas de funcionalidad.</string>
|
||||||
<!-- text for the toolbar position card header
|
<!-- text for the toolbar position card header
|
||||||
In English this is an idiom for "choose a side as in an argument or fight"
|
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 -->
|
but it is ok to make this more literally about "choosing a position in a physical space -->
|
||||||
|
@ -999,14 +1061,22 @@
|
||||||
<string name="preference_enhanced_tracking_protection_explanation">Protege tus datos. %s te protege de muchos de los rastreadores más comunes que siguen lo que haces en línea.</string>
|
<string name="preference_enhanced_tracking_protection_explanation">Protege tus datos. %s te protege de muchos de los rastreadores más comunes que siguen lo que haces en línea.</string>
|
||||||
<!-- Text displayed that links to website about enhanced tracking protection -->
|
<!-- Text displayed that links to website about enhanced tracking protection -->
|
||||||
<string name="preference_enhanced_tracking_protection_explanation_learn_more">Saber más</string>
|
<string name="preference_enhanced_tracking_protection_explanation_learn_more">Saber más</string>
|
||||||
|
<!-- Preference for enhanced tracking protection for the standard protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_standard_default_1">Estándar (predeterminado)</string>
|
||||||
|
<!-- Preference description for enhanced tracking protection for the standard protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_standard_description_3">Bloquea menos rastreadores. Las páginas se cargarán normalmente.</string>
|
||||||
<!-- Accessibility text for the Standard protection information icon -->
|
<!-- Accessibility text for the Standard protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_standard_info_button">Qué es lo que está bloqueado por la protección estándar contra el rastreo</string>
|
<string name="preference_enhanced_tracking_protection_standard_info_button">Qué es lo que está bloqueado por la protección estándar contra el rastreo</string>
|
||||||
<!-- Preference for enhanced tracking protection for the strict protection settings -->
|
<!-- Preference for enhanced tracking protection for the strict protection settings -->
|
||||||
<string name="preference_enhanced_tracking_protection_strict">Estricto</string>
|
<string name="preference_enhanced_tracking_protection_strict">Estricto</string>
|
||||||
|
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_strict_description_2">Bloquear más rastreadores, publicidad y ventanas emergentes. Las páginas cargan más rápido, pero pueden tener problemas de funcionalidad.</string>
|
||||||
<!-- Accessibility text for the Strict protection information icon -->
|
<!-- Accessibility text for the Strict protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_strict_info_button">Qué es lo que está bloqueado por la protección estricta contra el rastreo</string>
|
<string name="preference_enhanced_tracking_protection_strict_info_button">Qué es lo que está bloqueado por la protección estricta contra el rastreo</string>
|
||||||
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
||||||
<string name="preference_enhanced_tracking_protection_custom">Personalizado</string>
|
<string name="preference_enhanced_tracking_protection_custom">Personalizado</string>
|
||||||
|
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_custom_description_2">Elige qué rastreadores y secuencias de comandos bloquear</string>
|
||||||
<!-- Accessibility text for the Strict protection information icon -->
|
<!-- Accessibility text for the Strict protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_custom_info_button">Esto es lo que está bloqueado por la protección de rastreo estándar</string>
|
<string name="preference_enhanced_tracking_protection_custom_info_button">Esto es lo que está bloqueado por la protección de rastreo estándar</string>
|
||||||
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
|
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
|
||||||
|
@ -1057,6 +1127,8 @@
|
||||||
<!-- Description of tracking content that can be blocked by Enhanced Tracking Protection -->
|
<!-- Description of tracking content that can be blocked by Enhanced Tracking Protection -->
|
||||||
<string name="etp_tracking_content_description">Bloquea la carga de anuncios externos, vídeos y contenido que contenga código de rastreo. Puede afectar a la funcionalidad del sitio web.</string>
|
<string name="etp_tracking_content_description">Bloquea la carga de anuncios externos, vídeos y contenido que contenga código de rastreo. Puede afectar a la funcionalidad del sitio web.</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">Cada vez que el escudo es morado, %s bloqueó rastreadores en un sitio. Toca para más información.</string>
|
||||||
<!-- Enhanced Tracking Protection message that protection is currently on for this site -->
|
<!-- Enhanced Tracking Protection message that protection is currently on for this site -->
|
||||||
<string name="etp_panel_on">Las protecciones están ACTIVAS para este sitio</string>
|
<string name="etp_panel_on">Las protecciones están ACTIVAS para este sitio</string>
|
||||||
|
|
||||||
|
@ -1065,4 +1137,305 @@
|
||||||
<!-- Header for exceptions list for which sites enhanced tracking protection is always off -->
|
<!-- Header for exceptions list for which sites enhanced tracking protection is always off -->
|
||||||
<string name="enhanced_tracking_protection_exceptions">La protección de rastreo mejorada está desactivada para estos sitios</string>
|
<string name="enhanced_tracking_protection_exceptions">La protección de rastreo mejorada está desactivada para estos sitios</string>
|
||||||
|
|
||||||
</resources>
|
<!-- Content description (not visible, for screen readers etc.): Navigate
|
||||||
|
back from ETP details (Ex: Tracking content) -->
|
||||||
|
<string name="etp_back_button_content_description">Regresar</string>
|
||||||
|
<!-- About page Your rights link text -->
|
||||||
|
<string name="about_your_rights">Tus derechos</string>
|
||||||
|
<!-- About page link text to open open source licenses screen -->
|
||||||
|
<string name="about_open_source_licenses">Bibliotecas de código abierto que utilizamos</string>
|
||||||
|
<!-- About page link text to open what's new link -->
|
||||||
|
<string name="about_whats_new">Novedades de %s</string>
|
||||||
|
<!-- Open source licenses page title
|
||||||
|
The first parameter is the app name -->
|
||||||
|
<string name="open_source_licenses_title">%s | Bibliotecas OSS</string>
|
||||||
|
|
||||||
|
<!-- About page link text to open support link -->
|
||||||
|
<string name="about_support">Ayuda</string>
|
||||||
|
<!-- About page link text to list of past crashes (like about:crashes on desktop) -->
|
||||||
|
<string name="about_crashes">Fallos</string>
|
||||||
|
<!-- About page link text to open privacy notice link -->
|
||||||
|
<string name="about_privacy_notice">Aviso de privacidad</string>
|
||||||
|
<!-- About page link text to open know your rights link -->
|
||||||
|
<string name="about_know_your_rights">Conoce tus derechos</string>
|
||||||
|
<!-- About page link text to open licensing information link -->
|
||||||
|
<string name="about_licensing_information">Información de licencia</string>
|
||||||
|
<!-- About page link text to open a screen with libraries that are used -->
|
||||||
|
<string name="about_other_open_source_libraries">Bibliotecas que usamos</string>
|
||||||
|
<!-- Toast shown to the user when they are activating the secret dev menu
|
||||||
|
The first parameter is number of long clicks left to enable the menu -->
|
||||||
|
<string name="about_debug_menu_toast_progress">Menú de depuración: quedan %1$d click(s) para habilitarlo</string>
|
||||||
|
<string name="about_debug_menu_toast_done">Menú de depuración habilitado</string>
|
||||||
|
|
||||||
|
<!-- Content description of the tab counter toolbar button when one tab is open -->
|
||||||
|
<string name="tab_counter_content_description_one_tab">1 pestaña</string>
|
||||||
|
<!-- Content description of the tab counter toolbar button when multiple tabs are open. First parameter will be replaced with the number of tabs (always more than one) -->
|
||||||
|
<string name="tab_counter_content_description_multi_tab">%d pestañas</string>
|
||||||
|
|
||||||
|
<!-- Browser long press popup menu -->
|
||||||
|
<!-- Copy the current url -->
|
||||||
|
<string name="browser_toolbar_long_press_popup_copy">Copiar</string>
|
||||||
|
<!-- Paste & go the text in the clipboard. '&' is replaced with the ampersand symbol: & -->
|
||||||
|
<string name="browser_toolbar_long_press_popup_paste_and_go">Pegar e ir</string>
|
||||||
|
<!-- Paste the text in the clipboard -->
|
||||||
|
<string name="browser_toolbar_long_press_popup_paste">Pegar</string>
|
||||||
|
<!-- Snackbar message shown after an URL has been copied to clipboard. -->
|
||||||
|
<string name="browser_toolbar_url_copied_to_clipboard_snackbar">URL copiada al portapapeles</string>
|
||||||
|
|
||||||
|
<!-- Title text for the Add To Homescreen dialog -->
|
||||||
|
<string name="add_to_homescreen_title">Agregar a la pantalla de inicio</string>
|
||||||
|
<!-- Cancel button text for the Add to Homescreen dialog -->
|
||||||
|
<string name="add_to_homescreen_cancel">Cancelar</string>
|
||||||
|
<!-- Add button text for the Add to Homescreen dialog -->
|
||||||
|
<string name="add_to_homescreen_add">Agregar</string>
|
||||||
|
<!-- Continue to website button text for the first-time Add to Homescreen dialog -->
|
||||||
|
<string name="add_to_homescreen_continue">Continuar al sitio web</string>
|
||||||
|
<!-- Placeholder text for the TextView in the Add to Homescreen dialog -->
|
||||||
|
<string name="add_to_homescreen_text_placeholder">Nombre del acceso directo</string>
|
||||||
|
<!-- Describes the add to homescreen functionality -->
|
||||||
|
<string name="add_to_homescreen_description">Puedes agregar fácilmente este sitio web a la página de inicio de tu teléfono para navegar más rápido con una experiencia similar a una app.</string>
|
||||||
|
|
||||||
|
<!-- Preference for managing the settings for logins and passwords in Fenix -->
|
||||||
|
<string name="preferences_passwords_logins_and_passwords">Inicios de sesión y contraseñas</string>
|
||||||
|
<!-- Preference for managing the saving of logins and passwords in Fenix -->
|
||||||
|
<string name="preferences_passwords_save_logins">Guardar inicios de sesión y contraseñas</string>
|
||||||
|
<!-- Preference option for asking to save passwords in Fenix -->
|
||||||
|
<string name="preferences_passwords_save_logins_ask_to_save">Preguntar para guardar</string>
|
||||||
|
<!-- Preference option for never saving passwords in Fenix -->
|
||||||
|
<string name="preferences_passwords_save_logins_never_save">Nunca guardar</string>
|
||||||
|
<!-- Preference for autofilling saved logins in Fenix -->
|
||||||
|
<string name="preferences_passwords_autofill">Autocompletar</string>
|
||||||
|
<!-- Preference for syncing saved logins in Fenix -->
|
||||||
|
<string name="preferences_passwords_sync_logins">Sincronizar inicios de sesión</string>
|
||||||
|
<!-- Syncing saved logins in Fenix is on -->
|
||||||
|
<string name="preferences_passwords_sync_logins_on">Habilitado</string>
|
||||||
|
<!-- Syncing saved logins in Fenix is off -->
|
||||||
|
<string name="preferences_passwords_sync_logins_off">Deshabilitado</string>
|
||||||
|
<!-- Syncing saved logins in Fenix needs reconnect to sync -->
|
||||||
|
<string name="preferences_passwords_sync_logins_reconnect">Reconectar</string>
|
||||||
|
<!-- Syncing saved logins in Fenix needs login -->
|
||||||
|
<string name="preferences_passwords_sync_logins_sign_in">Iniciar sesión en Sync</string>
|
||||||
|
<!-- Preference to access list of saved logins -->
|
||||||
|
<string name="preferences_passwords_saved_logins">Inicios de sesión guardados</string>
|
||||||
|
<!-- Description of empty list of saved passwords. Placeholder is replaced with app name. -->
|
||||||
|
<string name="preferences_passwords_saved_logins_description_empty_text">Los inicios de sesión que guardes o sincronices en %s se mostrarán aquí</string>
|
||||||
|
<!-- Preference to access list of saved logins -->
|
||||||
|
<string name="preferences_passwords_saved_logins_description_empty_learn_more_link">Saber más acerca de Sync.</string>
|
||||||
|
<!-- Preference to access list of login exceptions that we never save logins for -->
|
||||||
|
<string name="preferences_passwords_exceptions">Excepciones</string>
|
||||||
|
<!-- Empty description of list of login exceptions that we never save logins for -->
|
||||||
|
<string name="preferences_passwords_exceptions_description_empty">Los inicios de sesión y contraseñas no guardados se mostrarán aquí.</string>
|
||||||
|
|
||||||
|
<!-- Description of list of login exceptions that we never save logins for -->
|
||||||
|
<string name="preferences_passwords_exceptions_description">Los inicios de sesión y contraseñas no serán guardados para estos sitios.</string>
|
||||||
|
<!-- Hint for search box in logins list -->
|
||||||
|
<string name="preferences_passwords_saved_logins_search">Buscar inicios de sesión</string>
|
||||||
|
<!-- Option to sort logins list A-Z, alphabetically -->
|
||||||
|
<string name="preferences_passwords_saved_logins_alphabetically">Alfabéticamente</string>
|
||||||
|
<!-- Option to sort logins list by most recently used -->
|
||||||
|
<string name="preferences_passwords_saved_logins_recently_used">Usados recientemente</string>
|
||||||
|
<!-- The header for the site that a login is for -->
|
||||||
|
<string name="preferences_passwords_saved_logins_site">Sitio</string>
|
||||||
|
<!-- The header for the username for a login -->
|
||||||
|
<string name="preferences_passwords_saved_logins_username">Nombre de usuario</string>
|
||||||
|
<!-- The header for the password for a login -->
|
||||||
|
<string name="preferences_passwords_saved_logins_password">Contraseña</string>
|
||||||
|
<!-- Message displayed in security prompt to reenter a secret pin to access saved logins -->
|
||||||
|
<string name="preferences_passwords_saved_logins_enter_pin">Vuelve a ingresar tu PIN</string>
|
||||||
|
<!-- Message displayed in security prompt to access saved logins -->
|
||||||
|
<string name="preferences_passwords_saved_logins_enter_pin_description">Desbloquear para ver los inicios de sesión guardados</string>
|
||||||
|
<!-- Message displayed when a connection is insecure and we detect the user is entering a password -->
|
||||||
|
<string name="logins_insecure_connection_warning">Esta conexión no es segura. Los inicios de sesión ingresados aquí pueden verse comprometidos.</string>
|
||||||
|
<!-- Learn more link that will link to a page with more information displayed when a connection is insecure and we detect the user is entering a password -->
|
||||||
|
<string name="logins_insecure_connection_warning_learn_more">Saber más</string>
|
||||||
|
<!-- Prompt message displayed when Fenix detects a user has entered a password and user decides if Fenix should save it. The first parameter is the name of the application (For example: Fenix) -->
|
||||||
|
<string name="logins_doorhanger_save">¿Quieres que %s guarde este inicio de sesión?</string>
|
||||||
|
<!-- Positive confirmation that Fenix should save the new or updated login -->
|
||||||
|
<string name="logins_doorhanger_save_confirmation">Guardar</string>
|
||||||
|
<!-- Negative confirmation that Fenix should not save the new or updated login -->
|
||||||
|
<string name="logins_doorhanger_save_dont_save">No guardar</string>
|
||||||
|
<!-- Shown in snackbar to tell user that the password has been copied -->
|
||||||
|
<string name="logins_password_copied">Contraseña copiada al portapapeles</string>
|
||||||
|
<!-- Shown in snackbar to tell user that the username has been copied -->
|
||||||
|
<string name="logins_username_copied">Nombre de usuario copiado al portapapeles</string>
|
||||||
|
<!-- Shown in snackbar to tell user that the site has been copied -->
|
||||||
|
<string name="logins_site_copied">Sitio copiado al portapapeles</string>
|
||||||
|
<!-- Content Description (for screenreaders etc) read for the button to copy a password in logins-->
|
||||||
|
<string name="saved_logins_copy_password">Copiar contraseña</string>
|
||||||
|
<!-- Content Description (for screenreaders etc) read for the button to copy a username in logins -->
|
||||||
|
<string name="saved_login_copy_username">Copiar nombre de usuario</string>
|
||||||
|
<!-- Content Description (for screenreaders etc) read for the button to copy a site in logins -->
|
||||||
|
<string name="saved_login_copy_site">Copiar sitio</string>
|
||||||
|
<!-- Content Description (for screenreaders etc) read for the button to reveal a password in logins -->
|
||||||
|
<string name="saved_login_reveal_password">Mostrar contraseña</string>
|
||||||
|
<!-- Content Description (for screenreaders etc) read for the button to hide a password in logins -->
|
||||||
|
<string name="saved_login_hide_password">Ocultar contraseña</string>
|
||||||
|
<!-- Message displayed in biometric prompt displayed for authentication before allowing users to view their logins -->
|
||||||
|
<string name="logins_biometric_prompt_message">Desbloquear para ver tus inicios de sesión guardados</string>
|
||||||
|
|
||||||
|
<!-- Title of warning dialog if users have no device authentication set up -->
|
||||||
|
<string name="logins_warning_dialog_title">Asegurar tus usuarios y contraseñas</string>
|
||||||
|
<!-- Message of warning dialog if users have no device authentication set up -->
|
||||||
|
<string name="logins_warning_dialog_message">Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger el acceso a tus inicios de sesión y contraseñas guardadas si alguien más tiene tu dispositivo.</string>
|
||||||
|
<!-- Negative button to ignore warning dialog if users have no device authentication set up -->
|
||||||
|
<string name="logins_warning_dialog_later">Más tarde</string>
|
||||||
|
<!-- Positive button to send users to set up a pin of warning dialog if users have no device authentication set up -->
|
||||||
|
<string name="logins_warning_dialog_set_up_now">Configurar ahora</string>
|
||||||
|
<!-- Title of PIN verification dialog to direct users to re-enter their device credentials to access their logins -->
|
||||||
|
<string name="logins_biometric_prompt_message_pin">Desbloquear tu dispositivo</string>
|
||||||
|
<!-- Title for Accessibility Force Enable Zoom Preference -->
|
||||||
|
<string name="preference_accessibility_force_enable_zoom">Zoom en todos los sitios</string>
|
||||||
|
<!-- Summary for Accessibility Force Enable Zoom Preference -->
|
||||||
|
<string name="preference_accessibility_force_enable_zoom_summary">Habilitar para permitir pellizcar y hacer zoom, incluso en sitios web que previenen este gesto.</string>
|
||||||
|
<!-- Saved logins sorting strategy menu item -by name- (if selected, it will sort saved logins alphabetically) -->
|
||||||
|
<string name="saved_logins_sort_strategy_alphabetically">Nombre (A-Z)</string>
|
||||||
|
<!-- Saved logins sorting strategy menu item -by last used- (if selected, it will sort saved logins by last used) -->
|
||||||
|
<string name="saved_logins_sort_strategy_last_used">Último uso</string>
|
||||||
|
<!-- Content description (not visible, for screen readers etc.): Sort saved logins dropdown menu chevron icon -->
|
||||||
|
<string name="saved_logins_menu_dropdown_chevron_icon_content_description">Ordenar menú de inicios de sesión</string>
|
||||||
|
|
||||||
|
<!-- Title of the Add search engine screen -->
|
||||||
|
<string name="search_engine_add_custom_search_engine_title">Agregar motor de búsqueda</string>
|
||||||
|
<!-- Title of the Edit search engine screen -->
|
||||||
|
<string name="search_engine_edit_custom_search_engine_title">Editar motor de búsqueda</string>
|
||||||
|
<!-- Content description (not visible, for screen readers etc.): Title for the button to add a search engine in the action bar -->
|
||||||
|
<string name="search_engine_add_button_content_description">Agregar</string>
|
||||||
|
<!-- Content description (not visible, for screen readers etc.): Title for the button to save a search engine in the action bar -->
|
||||||
|
<string name="search_engine_add_custom_search_engine_edit_button_content_description">Guardar</string>
|
||||||
|
<!-- Text for the menu button to edit a search engine -->
|
||||||
|
<string name="search_engine_edit">Editar</string>
|
||||||
|
<!-- Text for the menu button to delete a search engine -->
|
||||||
|
<string name="search_engine_delete">Eliminar</string>
|
||||||
|
|
||||||
|
<!-- Text for the button to create a custom search engine on the Add search engine screen -->
|
||||||
|
<string name="search_add_custom_engine_label_other">Otro</string>
|
||||||
|
<!-- Placeholder text shown in the Search Engine Name TextField before a user enters text -->
|
||||||
|
<string name="search_add_custom_engine_name_hint">Nombre</string>
|
||||||
|
<!-- Placeholder text shown in the Search String TextField before a user enters text -->
|
||||||
|
<string name="search_add_custom_engine_search_string_hint">Cadena de búsqueda a usar</string>
|
||||||
|
<!-- Description text for the Search String TextField. The %s is part of the string -->
|
||||||
|
<string name="search_add_custom_engine_search_string_example">Reemplazar la consulta con “%s”. Ejemplo:\n https://www.google.com/search?q=%s</string>
|
||||||
|
<!-- Text for the button to learn more about adding a custom search engine -->
|
||||||
|
<string name="search_add_custom_engine_learn_more_label">Saber más</string>
|
||||||
|
<!-- Accessibility description for the form in which details about the custom search engine are entered -->
|
||||||
|
<string name="search_add_custom_engine_form_description">Detalles del motor de búsqueda personalizado</string>
|
||||||
|
<!-- Accessibility description for the 'Learn more' link -->
|
||||||
|
<string name="search_add_custom_engine_learn_more_description">Enlace para saber más</string>
|
||||||
|
|
||||||
|
<!-- Text shown when a user leaves the name field empty -->
|
||||||
|
<string name="search_add_custom_engine_error_empty_name">Introducir nombre de motor de búsqueda</string>
|
||||||
|
<!-- Text shown when a user tries to add a search engine that already exists -->
|
||||||
|
<string name="search_add_custom_engine_error_existing_name">Ya existe un motor de búsqueda con nombre “%s”.</string>
|
||||||
|
<!-- Text shown when a user leaves the search string field empty -->
|
||||||
|
<string name="search_add_custom_engine_error_empty_search_string">Ingresa una cadena de búsqueda</string>
|
||||||
|
<!-- Text shown when a user leaves out the required template string -->
|
||||||
|
<string name="search_add_custom_engine_error_missing_template">Verifica que la cadena de búsqueda corresponde con el formato de ejemplo</string>
|
||||||
|
<!-- Text shown when we aren't able to validate the custom search query. The first parameter is the url of the custom search engine -->
|
||||||
|
<string name="search_add_custom_engine_error_cannot_reach">Error al conectarse a “%s”</string>
|
||||||
|
<!-- Text shown when a user creates a new search engine -->
|
||||||
|
<string name="search_add_custom_engine_success_message">Se creó %s</string>
|
||||||
|
<!-- Text shown when a user successfully edits a custom search engine -->
|
||||||
|
<string name="search_edit_custom_engine_success_message">Se guardó %s</string>
|
||||||
|
<!-- Text shown when a user successfully deletes a custom search engine -->
|
||||||
|
<string name="search_delete_search_engine_success_message">Se eliminó %s</string>
|
||||||
|
|
||||||
|
<!-- Title text shown for the migration screen to the new browser. Placeholder replaced with app name -->
|
||||||
|
<string name="migration_title">Bienvenido a un %s completamente nuevo</string>
|
||||||
|
<!-- Description text followed by a list of things migrating (e.g. Bookmarks, History). Placeholder replaced with app name-->
|
||||||
|
<string name="migration_description">Un navegador completamente re-diseñado te espera, con un mejor desempeño y funciones que te ayudarán a hacer más en línea.\n\nPor favor espera mientras actualizamos %s con tus</string>
|
||||||
|
<!-- Text on the disabled button while in progress. Placeholder replaced with app name -->
|
||||||
|
<string name="migration_updating_app_button_text">Actualizando %s…</string>
|
||||||
|
<!-- Text on the enabled button. Placeholder replaced with app name-->
|
||||||
|
<string name="migration_update_app_button">Iniciar %s</string>
|
||||||
|
<!-- Accessibility description text for a completed migration item -->
|
||||||
|
<string name="migration_icon_description">Migración completada</string>
|
||||||
|
<!--Text on list of migrated items (e.g. Settings, History, etc.)-->
|
||||||
|
<string name="migration_text_passwords">Contraseñas</string>
|
||||||
|
|
||||||
|
<!-- Heading for the instructions to allow a permission -->
|
||||||
|
<string name="phone_feature_blocked_intro">Para permitirlo:</string>
|
||||||
|
<!-- First step for the allowing a permission -->
|
||||||
|
<string name="phone_feature_blocked_step_settings">1. Ve a los ajustes de Android</string>
|
||||||
|
<!-- Second step for the allowing a permission -->
|
||||||
|
<string name="phone_feature_blocked_step_permissions"><![CDATA[2. Toca en <b>Permisos</b>]]></string>
|
||||||
|
<!-- Third step for the allowing a permission (Fore example: Camera) -->
|
||||||
|
<string name="phone_feature_blocked_step_feature"><![CDATA[3. Cambia <b>%1$s</b> a activado]]></string>
|
||||||
|
|
||||||
|
<!-- Label that indicates a site is using a secure connection -->
|
||||||
|
<string name="quick_settings_sheet_secure_connection">Conexión segura</string>
|
||||||
|
|
||||||
|
<!-- Label that indicates a site is using a insecure connection -->
|
||||||
|
<string name="quick_settings_sheet_insecure_connection">Conexión insegura</string>
|
||||||
|
<!-- Confirmation message for a dialog confirming if the user wants to delete all the permissions for all sites-->
|
||||||
|
<string name="confirm_clear_permissions_on_all_sites">¿Seguro que quieres borrar todos los permisos de todos los sitios?</string>
|
||||||
|
<!-- Confirmation message for a dialog confirming if the user wants to delete all the permissions for a site-->
|
||||||
|
<string name="confirm_clear_permissions_site">¿Seguro que quieres eliminar todos los permisos para este sitio?</string>
|
||||||
|
<!-- Confirmation message for a dialog confirming if the user wants to set default value a permission for a site-->
|
||||||
|
<string name="confirm_clear_permission_site">¿Seguro que quieres eliminar este permiso para este sitio?</string>
|
||||||
|
<!-- label shown when there are not site exceptions to show in the site exception settings -->
|
||||||
|
<string name="no_site_exceptions">Sin excepciones de sitio</string>
|
||||||
|
<!-- Label for the Pocket default top site -->
|
||||||
|
<string name="pocket_top_articles">Artículos principales</string>
|
||||||
|
<!-- Bookmark deletion confirmation -->
|
||||||
|
<string name="bookmark_deletion_confirmation">¿Seguro que quiere eliminar este marcador?</string>
|
||||||
|
<!-- Browser menu button that adds a top site to the home fragment -->
|
||||||
|
<string name="browser_menu_add_to_top_sites">Agregar a los sitios principales</string>
|
||||||
|
<!-- text shown before the issuer name to indicate who its verified by, parameter is the name of
|
||||||
|
the certificate authority that verified the ticket-->
|
||||||
|
<string name="certificate_info_verified_by">Verificado por: %1$s</string>
|
||||||
|
<!-- Login overflow menu delete button -->
|
||||||
|
<string name="login_menu_delete_button">Eliminar</string>
|
||||||
|
<!-- Login overflow menu edit button -->
|
||||||
|
<string name="login_menu_edit_button">Editar</string>
|
||||||
|
<!-- Message in delete confirmation dialog for logins -->
|
||||||
|
<string name="login_deletion_confirmation">¿Seguro que quieres eliminar este inicio de sesión?</string>
|
||||||
|
<!-- Positive action of a dialog asking to delete -->
|
||||||
|
<string name="dialog_delete_positive">Eliminar</string>
|
||||||
|
<!-- The saved login options menu description. -->
|
||||||
|
<string name="login_options_menu">Opciones de inicio de sesión</string>
|
||||||
|
<!-- The editable text field for a login's web address. -->
|
||||||
|
<string name="saved_login_hostname_description">El campo de texto editable para la dirección web del inicio de sesión.</string>
|
||||||
|
<!-- The editable text field for a login's username. -->
|
||||||
|
<string name="saved_login_username_description">El campo de texto editable para el nombre de usuario del inicio de sesión.</string>
|
||||||
|
<!-- The editable text field for a login's password. -->
|
||||||
|
<string name="saved_login_password_description">El campo de texto editable para la contraseña del inicio de sesión.</string>
|
||||||
|
<!-- The button description to save changes to an edited login. -->
|
||||||
|
<string name="save_changes_to_login">Guardar cambios al inicio de sesión.</string>
|
||||||
|
<!-- The button description to discard changes to an edited login. -->
|
||||||
|
<string name="discard_changes">Descartar cambios</string>
|
||||||
|
<!-- The page title for editing a saved login. -->
|
||||||
|
<string name="edit">Editar</string>
|
||||||
|
<!-- The error message in edit login view when password field is blank. -->
|
||||||
|
<string name="saved_login_password_required">Se requiere contraseña</string>
|
||||||
|
<!-- Voice search button content description -->
|
||||||
|
<string name="voice_search_content_description">Búsqueda por voz</string>
|
||||||
|
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||||
|
<string name="voice_search_explainer">Habla ahora</string>
|
||||||
|
<!-- The error message in edit login view when a duplicate username exists. -->
|
||||||
|
<string name="saved_login_duplicate">Ya existe un inicio de sesión con ese nombre de usuario</string>
|
||||||
|
|
||||||
|
<!-- Synced Tabs -->
|
||||||
|
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||||
|
<string name="synced_tabs_connect_to_sync_account">Conectar con una cuenta de Firefox.</string>
|
||||||
|
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||||
|
<string name="synced_tabs_connect_another_device">Conectar otro dispositivo.</string>
|
||||||
|
<!-- Text displayed asking user to re-authenticate -->
|
||||||
|
<string name="synced_tabs_reauth">Por favor, vuelve a autenticarte.</string>
|
||||||
|
<!-- Text displayed when user has disabled tab syncing in Firefox Sync Account -->
|
||||||
|
<string name="synced_tabs_enable_tab_syncing">Por favor habilita la sincronización de pestañas.</string>
|
||||||
|
<!-- Text displayed when user has no tabs that have been synced -->
|
||||||
|
<string name="synced_tabs_no_tabs">No tienes ninguna pestaña abierta en Firefox en tus otros dispositivos.</string>
|
||||||
|
<!-- Text displayed in the synced tabs screen when a user is not signed in to Firefox Sync describing Synced Tabs -->
|
||||||
|
<string name="synced_tabs_sign_in_message">Ver una lista de pestañas de tus otros dispositivos.</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">Iniciar sesión para sincronizar</string>
|
||||||
|
|
||||||
|
<!-- Top Sites -->
|
||||||
|
<!-- Title text displayed in the dialog when top sites limit is reached. -->
|
||||||
|
<string name="top_sites_max_limit_title">Límite de sitios frecuentes alcanzado</string>
|
||||||
|
<!-- Content description text displayed in the dialog when top sites limit is reached. -->
|
||||||
|
<string name="top_sites_max_limit_content">Para agregar un nuevo sitio frecuente, elimina uno. Mantén presionado el sitio y selecciona eliminar.</string>
|
||||||
|
<!-- Confirmation dialog button text when top sites limit is reached. -->
|
||||||
|
<string name="top_sites_max_limit_confirmation_button">Vale, entendido</string>
|
||||||
|
|
||||||
|
</resources>
|
||||||
|
|
|
@ -370,7 +370,7 @@
|
||||||
<!-- Title for experiments preferences -->
|
<!-- Title for experiments preferences -->
|
||||||
<string name="preference_experiments">Eksperymenty</string>
|
<string name="preference_experiments">Eksperymenty</string>
|
||||||
<!-- Summary for experiments preferences -->
|
<!-- Summary for experiments preferences -->
|
||||||
<string name="preference_experiments_summary">Pozwala Mozilli instalować i zbierać dane dla funkcji eksperymentalnych</string>
|
<string name="preference_experiments_summary">Pozwala Mozilli instalować i zbierać dane dla funkcji eksperymentalnych.</string>
|
||||||
<!-- Preference switch for crash reporter -->
|
<!-- Preference switch for crash reporter -->
|
||||||
<string name="preferences_crash_reporter">Zgłaszanie awarii</string>
|
<string name="preferences_crash_reporter">Zgłaszanie awarii</string>
|
||||||
<!-- Preference switch for Mozilla location service -->
|
<!-- Preference switch for Mozilla location service -->
|
||||||
|
@ -892,8 +892,6 @@
|
||||||
<string name="preference_summary_delete_browsing_data_on_quit">Automatycznie usuwa dane przeglądania po wybraniu „Zakończ” z głównego menu</string>
|
<string name="preference_summary_delete_browsing_data_on_quit">Automatycznie usuwa dane przeglądania po wybraniu „Zakończ” z głównego menu</string>
|
||||||
<!-- Summary for the Delete browsing data on quit preference. "Quit" translation should match delete_browsing_data_on_quit_action translation. -->
|
<!-- 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">Automatycznie usuwa dane przeglądania po wybraniu „Zakończ” z głównego menu</string>
|
<string name="preference_summary_delete_browsing_data_on_quit_2">Automatycznie usuwa dane przeglądania po wybraniu „Zakończ” z głównego menu</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">Historia przeglądania</string>
|
|
||||||
<!-- Action item in menu for the Delete browsing data on quit feature -->
|
<!-- Action item in menu for the Delete browsing data on quit feature -->
|
||||||
<string name="delete_browsing_data_on_quit_action">Zakończ</string>
|
<string name="delete_browsing_data_on_quit_action">Zakończ</string>
|
||||||
|
|
||||||
|
|
|
@ -954,10 +954,14 @@
|
||||||
<string name="onboarding_firefox_account_automatic_signin_failed">ไม่สามารถเข้าสู่ระบบ</string>
|
<string name="onboarding_firefox_account_automatic_signin_failed">ไม่สามารถเข้าสู่ระบบ</string>
|
||||||
<!-- text for the tracking protection onboarding card header -->
|
<!-- text for the tracking protection onboarding card header -->
|
||||||
<string name="onboarding_tracking_protection_header_2">ความเป็นส่วนตัวอัตโนมัติ</string>
|
<string name="onboarding_tracking_protection_header_2">ความเป็นส่วนตัวอัตโนมัติ</string>
|
||||||
|
<!-- text for tracking protection radio button option for standard level of blocking -->
|
||||||
|
<string name="onboarding_tracking_protection_standard_button_2">มาตรฐาน (ค่าเริ่มต้น)</string>
|
||||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||||
<string name="onboarding_tracking_protection_strict_button">เข้มงวด (แนะนำ)</string>
|
<string name="onboarding_tracking_protection_strict_button">เข้มงวด (แนะนำ)</string>
|
||||||
<!-- text for tracking protection radio button option for strict level of blocking -->
|
<!-- text for tracking protection radio button option for strict level of blocking -->
|
||||||
<string name="onboarding_tracking_protection_strict_option">เข้มงวด</string>
|
<string name="onboarding_tracking_protection_strict_option">เข้มงวด</string>
|
||||||
|
<!-- text for strict blocking option button description -->
|
||||||
|
<string name="onboarding_tracking_protection_strict_button_description_2">ปิดกั้นตัวติดตาม โฆษณา และป๊อปอัปมากขึ้น เว็บโหลดเร็วขึ้น แต่ฟังก์ชั่นบางอย่างอาจไม่ทำงาน</string>
|
||||||
<!-- text for the toolbar position card header
|
<!-- text for the toolbar position card header
|
||||||
In English this is an idiom for "choose a side as in an argument or fight"
|
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 -->
|
but it is ok to make this more literally about "choosing a position in a physical space -->
|
||||||
|
@ -1043,14 +1047,20 @@
|
||||||
<string name="preference_enhanced_tracking_protection_explanation">เก็บข้อมูลของคุณไว้กับตัวคุณเอง %s ปกป้องคุณจากตัวติดตามที่พบบ่อยที่สุดซึ่งติดตามสิ่งที่คุณทำทางออนไลน์</string>
|
<string name="preference_enhanced_tracking_protection_explanation">เก็บข้อมูลของคุณไว้กับตัวคุณเอง %s ปกป้องคุณจากตัวติดตามที่พบบ่อยที่สุดซึ่งติดตามสิ่งที่คุณทำทางออนไลน์</string>
|
||||||
<!-- Text displayed that links to website about enhanced tracking protection -->
|
<!-- Text displayed that links to website about enhanced tracking protection -->
|
||||||
<string name="preference_enhanced_tracking_protection_explanation_learn_more">เรียนรู้เพิ่มเติม</string>
|
<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>
|
||||||
<!-- Accessibility text for the Standard protection information icon -->
|
<!-- Accessibility text for the Standard protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_standard_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบมาตรฐาน</string>
|
<string name="preference_enhanced_tracking_protection_standard_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบมาตรฐาน</string>
|
||||||
<!-- Preference for enhanced tracking protection for the strict protection settings -->
|
<!-- Preference for enhanced tracking protection for the strict protection settings -->
|
||||||
<string name="preference_enhanced_tracking_protection_strict">เข้มงวด</string>
|
<string name="preference_enhanced_tracking_protection_strict">เข้มงวด</string>
|
||||||
|
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_strict_description_2">ปิดกั้นตัวติดตาม โฆษณา และป๊อปอัปมากขึ้น เว็บโหลดเร็วขึ้น แต่ฟังก์ชั่นบางอย่างอาจไม่ทำงาน</string>
|
||||||
<!-- Accessibility text for the Strict protection information icon -->
|
<!-- Accessibility text for the Strict protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_strict_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบเข้มงวด</string>
|
<string name="preference_enhanced_tracking_protection_strict_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบเข้มงวด</string>
|
||||||
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
||||||
<string name="preference_enhanced_tracking_protection_custom">กำหนดเอง</string>
|
<string name="preference_enhanced_tracking_protection_custom">กำหนดเอง</string>
|
||||||
|
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||||
|
<string name="preference_enhanced_tracking_protection_custom_description_2">เลือกตัวติดตามหรือสคริปต์ที่ต้องการปิดกั้น</string>
|
||||||
<!-- Accessibility text for the Strict protection information icon -->
|
<!-- Accessibility text for the Strict protection information icon -->
|
||||||
<string name="preference_enhanced_tracking_protection_custom_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบกำหนดเอง</string>
|
<string name="preference_enhanced_tracking_protection_custom_info_button">สิ่งที่ถูกปิดกั้นโดยการป้องกันการติดตามแบบกำหนดเอง</string>
|
||||||
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
|
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
|
||||||
|
@ -1365,6 +1375,8 @@
|
||||||
<string name="dialog_delete_positive">ลบ</string>
|
<string name="dialog_delete_positive">ลบ</string>
|
||||||
<!-- The saved login options menu description. -->
|
<!-- The saved login options menu description. -->
|
||||||
<string name="login_options_menu">ตัวเลือกการเข้าสู่ระบบ</string>
|
<string name="login_options_menu">ตัวเลือกการเข้าสู่ระบบ</string>
|
||||||
|
<!-- The button description to save changes to an edited login. -->
|
||||||
|
<string name="save_changes_to_login">บันทึกการเปลี่ยนแปลงเพื่อเข้าสู่ระบบ</string>
|
||||||
<!-- The button description to discard changes to an edited login. -->
|
<!-- The button description to discard changes to an edited login. -->
|
||||||
<string name="discard_changes">ละทิ้งการเปลี่ยนแปลง</string>
|
<string name="discard_changes">ละทิ้งการเปลี่ยนแปลง</string>
|
||||||
<!-- The page title for editing a saved login. -->
|
<!-- The page title for editing a saved login. -->
|
||||||
|
@ -1376,12 +1388,19 @@
|
||||||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||||
<string name="voice_search_explainer">พูดเลย</string>
|
<string name="voice_search_explainer">พูดเลย</string>
|
||||||
|
|
||||||
|
<!-- The error message in edit login view when a duplicate username exists. -->
|
||||||
|
<string name="saved_login_duplicate">การเข้าสู่ระบบที่มีชื่อผู้ใช้นี้มีอยู่แล้ว</string>
|
||||||
|
|
||||||
<!-- Synced Tabs -->
|
<!-- Synced Tabs -->
|
||||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||||
<string name="synced_tabs_connect_to_sync_account">เชื่อมต่อกับบัญชี Firefox</string>
|
<string name="synced_tabs_connect_to_sync_account">เชื่อมต่อกับบัญชี Firefox</string>
|
||||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||||
<string name="synced_tabs_connect_another_device">เชื่อมต่ออุปกรณ์อื่น</string>
|
<string name="synced_tabs_connect_another_device">เชื่อมต่ออุปกรณ์อื่น</string>
|
||||||
|
|
||||||
|
<!-- Text displayed when user has no tabs that have been synced -->
|
||||||
|
<string name="synced_tabs_no_tabs">คุณไม่มีแท็บใด ๆ ที่เปิดอยู่ใน Firefox บนอุปกรณ์อื่น ๆ ของคุณ</string>
|
||||||
|
<!-- Text displayed in the synced tabs screen when a user is not signed in to Firefox Sync describing Synced Tabs -->
|
||||||
|
<string name="synced_tabs_sign_in_message">ดูรายการแท็บจากอุปกรณ์อื่น ๆ ของคุณ</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 -->
|
<!-- 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>
|
<string name="synced_tabs_sign_in_button">ลงชื่อเข้าใช้เพื่อซิงค์</string>
|
||||||
|
|
||||||
|
|
|
@ -940,7 +940,9 @@
|
||||||
<!-- text for firefox preview moving tip header "Firefox Preview" and "Firefox Nightly" are intentionally hardcoded -->
|
<!-- 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 -->
|
<!-- text for firefox preview moving tip description -->
|
||||||
<string name="tip_firefox_preview_moved_description">Firefox Nightly 每天都會更新,當中包含實驗中的新功能,然而這些新功能可能會較不穩定。\n\n若想要有較穩定的使用體驗,請下載我們的 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 -->
|
<!-- 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>
|
<string name="tip_firefox_preview_moved_button_2">下載 Firefox for Android Beta 測試版</string>
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/* 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.browser
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import io.mockk.MockKAnnotations
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.impl.annotations.MockK
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkObject
|
||||||
|
import io.mockk.unmockkObject
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.components.FenixSnackbar
|
||||||
|
import org.mozilla.fenix.components.FenixSnackbar.Companion.LENGTH_SHORT
|
||||||
|
|
||||||
|
class FenixSnackbarDelegateTest {
|
||||||
|
|
||||||
|
@MockK private lateinit var view: View
|
||||||
|
@MockK(relaxed = true) private lateinit var snackbar: FenixSnackbar
|
||||||
|
private lateinit var delegate: FenixSnackbarDelegate
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
MockKAnnotations.init(this)
|
||||||
|
mockkObject(FenixSnackbar.Companion)
|
||||||
|
|
||||||
|
delegate = FenixSnackbarDelegate(view)
|
||||||
|
every {
|
||||||
|
FenixSnackbar.make(view, LENGTH_SHORT, isDisplayedWithBrowserToolbar = true)
|
||||||
|
} returns snackbar
|
||||||
|
every { snackbar.setText(any()) } returns snackbar
|
||||||
|
every { snackbar.setAction(any(), any()) } returns snackbar
|
||||||
|
every { view.context.getString(R.string.app_name) } returns "Firefox"
|
||||||
|
every { view.context.getString(R.string.edit) } returns "Edit"
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
unmockkObject(FenixSnackbar.Companion)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show with no listener nor action`() {
|
||||||
|
delegate.show(
|
||||||
|
snackBarParentView = mockk(),
|
||||||
|
text = R.string.app_name,
|
||||||
|
duration = 0,
|
||||||
|
action = 0,
|
||||||
|
listener = null
|
||||||
|
)
|
||||||
|
|
||||||
|
verify { snackbar.setText("Firefox") }
|
||||||
|
verify(exactly = 0) { snackbar.setAction(any(), any()) }
|
||||||
|
verify { snackbar.show() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show with listener but no action`() {
|
||||||
|
delegate.show(
|
||||||
|
snackBarParentView = mockk(),
|
||||||
|
text = R.string.app_name,
|
||||||
|
duration = 0,
|
||||||
|
action = 0,
|
||||||
|
listener = {}
|
||||||
|
)
|
||||||
|
|
||||||
|
verify { snackbar.setText("Firefox") }
|
||||||
|
verify(exactly = 0) { snackbar.setAction(any(), any()) }
|
||||||
|
verify { snackbar.show() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show with action but no listener`() {
|
||||||
|
delegate.show(
|
||||||
|
snackBarParentView = mockk(),
|
||||||
|
text = R.string.app_name,
|
||||||
|
duration = 0,
|
||||||
|
action = R.string.edit,
|
||||||
|
listener = null
|
||||||
|
)
|
||||||
|
|
||||||
|
verify { snackbar.setText("Firefox") }
|
||||||
|
verify(exactly = 0) { snackbar.setAction(any(), any()) }
|
||||||
|
verify { snackbar.show() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show with listener and action`() {
|
||||||
|
val listener = mockk<(View) -> Unit>(relaxed = true)
|
||||||
|
delegate.show(
|
||||||
|
snackBarParentView = mockk(),
|
||||||
|
text = R.string.app_name,
|
||||||
|
duration = 0,
|
||||||
|
action = R.string.edit,
|
||||||
|
listener = listener
|
||||||
|
)
|
||||||
|
|
||||||
|
verify { snackbar.setText("Firefox") }
|
||||||
|
verify { snackbar.setAction("Edit", withArg {
|
||||||
|
verify(exactly = 0) { listener(view) }
|
||||||
|
it.invoke()
|
||||||
|
verify { listener(view) }
|
||||||
|
}) }
|
||||||
|
verify { snackbar.show() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,8 @@ import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
import mozilla.components.browser.session.SessionManager
|
import mozilla.components.browser.session.SessionManager
|
||||||
import org.junit.Assert
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertNull
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
@ -59,8 +60,8 @@ class TelemetrySessionObserverTest {
|
||||||
triggeredByRedirect = false,
|
triggeredByRedirect = false,
|
||||||
triggeredByWebContent = false
|
triggeredByWebContent = false
|
||||||
)
|
)
|
||||||
Assert.assertEquals(sessionUrl, singleSessionObserver.originSessionUrl)
|
assertEquals(sessionUrl, singleSessionObserver.originSessionUrl)
|
||||||
Assert.assertEquals(url, singleSessionObserver.redirectChain[0])
|
assertEquals(url, singleSessionObserver.redirectChain[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -77,9 +78,9 @@ class TelemetrySessionObserverTest {
|
||||||
triggeredByRedirect = false,
|
triggeredByRedirect = false,
|
||||||
triggeredByWebContent = false
|
triggeredByWebContent = false
|
||||||
)
|
)
|
||||||
Assert.assertEquals(url, singleSessionObserver.originSessionUrl)
|
assertEquals(url, singleSessionObserver.originSessionUrl)
|
||||||
Assert.assertEquals(url, singleSessionObserver.redirectChain[0])
|
assertEquals(url, singleSessionObserver.redirectChain[0])
|
||||||
Assert.assertEquals(newUrl, singleSessionObserver.redirectChain[1])
|
assertEquals(newUrl, singleSessionObserver.redirectChain[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -93,8 +94,8 @@ class TelemetrySessionObserverTest {
|
||||||
triggeredByRedirect = false,
|
triggeredByRedirect = false,
|
||||||
triggeredByWebContent = false
|
triggeredByWebContent = false
|
||||||
)
|
)
|
||||||
Assert.assertNull(singleSessionObserver.originSessionUrl)
|
assertNull(singleSessionObserver.originSessionUrl)
|
||||||
Assert.assertEquals(0, singleSessionObserver.redirectChain.size)
|
assertEquals(0, singleSessionObserver.redirectChain.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -116,7 +117,7 @@ class TelemetrySessionObserverTest {
|
||||||
redirectChain
|
redirectChain
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Assert.assertNull(singleSessionObserver.originSessionUrl)
|
assertNull(singleSessionObserver.originSessionUrl)
|
||||||
Assert.assertEquals(0, singleSessionObserver.redirectChain.size)
|
assertEquals(0, singleSessionObserver.redirectChain.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package org.mozilla.fenix.browser
|
package org.mozilla.fenix.browser
|
||||||
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import mozilla.components.browser.session.Session
|
import mozilla.components.browser.session.Session
|
||||||
|
@ -41,7 +42,34 @@ class UriOpenedObserverTest {
|
||||||
observer.onSessionAdded(session)
|
observer.onSessionAdded(session)
|
||||||
verify { session.register(observer.singleSessionObserver, owner) }
|
verify { session.register(observer.singleSessionObserver, owner) }
|
||||||
|
|
||||||
|
observer.onSessionSelected(session)
|
||||||
|
verify { session.register(observer.singleSessionObserver, owner) }
|
||||||
|
|
||||||
observer.onSessionRemoved(session)
|
observer.onSessionRemoved(session)
|
||||||
verify { session.unregister(observer.singleSessionObserver) }
|
verify { session.unregister(observer.singleSessionObserver) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `registers when all sessions are restored`() {
|
||||||
|
val session1: Session = mockk(relaxed = true)
|
||||||
|
val session2: Session = mockk(relaxed = true)
|
||||||
|
every { sessionManager.sessions } returns listOf(session1, session2)
|
||||||
|
|
||||||
|
observer.onSessionsRestored()
|
||||||
|
|
||||||
|
verify { session1.register(observer.singleSessionObserver, owner) }
|
||||||
|
verify { session2.register(observer.singleSessionObserver, owner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unregisters when all sessions are removed`() {
|
||||||
|
val session1: Session = mockk(relaxed = true)
|
||||||
|
val session2: Session = mockk(relaxed = true)
|
||||||
|
every { sessionManager.sessions } returns listOf(session1, session2)
|
||||||
|
|
||||||
|
observer.onAllSessionsRemoved()
|
||||||
|
|
||||||
|
verify { session1.unregister(observer.singleSessionObserver) }
|
||||||
|
verify { session2.unregister(observer.singleSessionObserver) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import mozilla.components.feature.pwa.WebAppShortcutManager
|
||||||
class TestCore(context: Context) : Core(context) {
|
class TestCore(context: Context) : Core(context) {
|
||||||
|
|
||||||
override val engine = mockk<Engine>(relaxed = true) {
|
override val engine = mockk<Engine>(relaxed = true) {
|
||||||
every { this@mockk getProperty "settings" } returns mockk<Settings>()
|
every { this@mockk getProperty "settings" } returns mockk<Settings>(relaxed = true)
|
||||||
}
|
}
|
||||||
override val sessionManager = SessionManager(engine)
|
override val sessionManager = SessionManager(engine)
|
||||||
override val store = mockk<BrowserStore>()
|
override val store = mockk<BrowserStore>()
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* 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.components.toolbar
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import mozilla.components.browser.session.Session
|
||||||
|
import mozilla.components.browser.state.state.BrowserState
|
||||||
|
import mozilla.components.browser.state.state.ReaderState
|
||||||
|
import mozilla.components.browser.state.state.createTab
|
||||||
|
import mozilla.components.browser.state.store.BrowserStore
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.components.toolbar.BrowserToolbarView.Companion.getUrlForClipboard
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class BrowserToolbarViewTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getUrlForClipboard() {
|
||||||
|
val customTabSession: Session = mockk()
|
||||||
|
every { customTabSession.url } returns "https://mozilla.org"
|
||||||
|
|
||||||
|
// Custom tab
|
||||||
|
assertEquals("https://mozilla.org", getUrlForClipboard(mockk(), customTabSession))
|
||||||
|
|
||||||
|
// Regular tab
|
||||||
|
val regularTab = createTab(url = "http://firefox.com")
|
||||||
|
var store = BrowserStore(BrowserState(tabs = listOf(regularTab), selectedTabId = regularTab.id))
|
||||||
|
assertEquals(regularTab.content.url, getUrlForClipboard(store))
|
||||||
|
|
||||||
|
// Reader Tab
|
||||||
|
val readerTab = createTab(url = "moz-extension://1234",
|
||||||
|
readerState = ReaderState(active = true, activeUrl = "https://blog.mozilla.org/123")
|
||||||
|
)
|
||||||
|
store = BrowserStore(BrowserState(tabs = listOf(readerTab), selectedTabId = readerTab.id))
|
||||||
|
assertEquals(readerTab.readerState.activeUrl, getUrlForClipboard(store))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* 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.exceptions
|
||||||
|
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.exceptions.viewholders.ExceptionsDeleteButtonViewHolder
|
||||||
|
import org.mozilla.fenix.exceptions.viewholders.ExceptionsHeaderViewHolder
|
||||||
|
import org.mozilla.fenix.exceptions.viewholders.ExceptionsListItemViewHolder
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class ExceptionsAdapterTest {
|
||||||
|
|
||||||
|
private lateinit var interactor: ExceptionsInteractor
|
||||||
|
private lateinit var adapter: ExceptionsAdapter
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
interactor = mockk()
|
||||||
|
adapter = ExceptionsAdapter(interactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `binds header and delete button with other adapter items`() = runBlockingTest {
|
||||||
|
adapter.updateData(listOf(mockk(), mockk()))
|
||||||
|
|
||||||
|
assertEquals(4, adapter.itemCount)
|
||||||
|
assertEquals(ExceptionsHeaderViewHolder.LAYOUT_ID, adapter.getItemViewType(0))
|
||||||
|
assertEquals(ExceptionsListItemViewHolder.LAYOUT_ID, adapter.getItemViewType(1))
|
||||||
|
assertEquals(ExceptionsListItemViewHolder.LAYOUT_ID, adapter.getItemViewType(2))
|
||||||
|
assertEquals(ExceptionsDeleteButtonViewHolder.LAYOUT_ID, adapter.getItemViewType(3))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* 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.exceptions
|
||||||
|
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.method.LinkMovementMethod
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import io.mockk.Runs
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkConstructor
|
||||||
|
import io.mockk.unmockkConstructor
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.component_exceptions.*
|
||||||
|
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class ExceptionsViewTest {
|
||||||
|
|
||||||
|
private lateinit var container: ViewGroup
|
||||||
|
private lateinit var interactor: ExceptionsInteractor
|
||||||
|
private lateinit var exceptionsView: ExceptionsView
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
mockkConstructor(ExceptionsAdapter::class)
|
||||||
|
container = FrameLayout(testContext)
|
||||||
|
interactor = mockk()
|
||||||
|
|
||||||
|
exceptionsView = ExceptionsView(container, interactor)
|
||||||
|
every { anyConstructed<ExceptionsAdapter>().updateData(any()) } just Runs
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
unmockkConstructor(ExceptionsAdapter::class)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `binds exception text`() {
|
||||||
|
assertTrue(exceptionsView.exceptions_learn_more.movementMethod is LinkMovementMethod)
|
||||||
|
assertTrue(exceptionsView.exceptions_learn_more.text is Spannable)
|
||||||
|
assertEquals("Learn more", exceptionsView.exceptions_learn_more.text.toString())
|
||||||
|
|
||||||
|
every { interactor.onLearnMore() } just Runs
|
||||||
|
exceptionsView.exceptions_learn_more.performClick()
|
||||||
|
verify { interactor.onLearnMore() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `binds empty list to adapter`() {
|
||||||
|
exceptionsView.update(ExceptionsFragmentState(emptyList()))
|
||||||
|
|
||||||
|
assertTrue(exceptionsView.exceptions_empty_view.isVisible)
|
||||||
|
assertFalse(exceptionsView.exceptions_list.isVisible)
|
||||||
|
verify { anyConstructed<ExceptionsAdapter>().updateData(emptyList()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `binds list with items to adapter`() {
|
||||||
|
val items = listOf<TrackingProtectionException>(mockk(), mockk())
|
||||||
|
exceptionsView.update(ExceptionsFragmentState(items))
|
||||||
|
|
||||||
|
assertFalse(exceptionsView.exceptions_empty_view.isVisible)
|
||||||
|
assertTrue(exceptionsView.exceptions_list.isVisible)
|
||||||
|
verify { anyConstructed<ExceptionsAdapter>().updateData(items) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* 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.exceptions.viewholders
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.delete_exceptions_button.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.exceptions.ExceptionsInteractor
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class ExceptionsDeleteButtonViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var interactor: ExceptionsInteractor
|
||||||
|
private lateinit var viewHolder: ExceptionsDeleteButtonViewHolder
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
val appCompatContext = ContextThemeWrapper(testContext, R.style.NormalTheme)
|
||||||
|
view = LayoutInflater.from(appCompatContext)
|
||||||
|
.inflate(ExceptionsDeleteButtonViewHolder.LAYOUT_ID, null)
|
||||||
|
interactor = mockk(relaxed = true)
|
||||||
|
viewHolder = ExceptionsDeleteButtonViewHolder(view, interactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `calls onDeleteAll on click`() {
|
||||||
|
view.removeAllExceptions.performClick()
|
||||||
|
|
||||||
|
verify { interactor.onDeleteAll() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* 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.exceptions.viewholders
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.exception_item.view.*
|
||||||
|
import mozilla.components.concept.engine.content.blocking.TrackingProtectionException
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.exceptions.ExceptionsInteractor
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class ExceptionsListItemViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var interactor: ExceptionsInteractor
|
||||||
|
private lateinit var viewHolder: ExceptionsListItemViewHolder
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(ExceptionsListItemViewHolder.LAYOUT_ID, null)
|
||||||
|
interactor = mockk(relaxed = true)
|
||||||
|
viewHolder = ExceptionsListItemViewHolder(view, interactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bind url and icon`() {
|
||||||
|
val exception = object : TrackingProtectionException {
|
||||||
|
override val url = "https://example.com/icon.svg"
|
||||||
|
}
|
||||||
|
viewHolder.bind(exception)
|
||||||
|
|
||||||
|
assertEquals(exception.url, view.webAddressView.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `calls onDeleteOne on click`() {
|
||||||
|
val exception = object : TrackingProtectionException {
|
||||||
|
override val url = "https://example.com/icon.svg"
|
||||||
|
}
|
||||||
|
viewHolder.bind(exception)
|
||||||
|
view.delete_exception.performClick()
|
||||||
|
|
||||||
|
verify { interactor.onDeleteOne(exception) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkObject
|
||||||
|
import io.mockk.unmockkObject
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.*
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.test.runBlockingTest
|
||||||
|
import mozilla.components.service.fxa.manager.SignInWithShareableAccountResult
|
||||||
|
import mozilla.components.service.fxa.sharing.ShareableAccount
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.components.BackgroundServices
|
||||||
|
import org.mozilla.fenix.components.FenixSnackbar
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingAutomaticSignInViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var backgroundServices: BackgroundServices
|
||||||
|
private lateinit var snackbar: FenixSnackbar
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingAutomaticSignInViewHolder.LAYOUT_ID, null)
|
||||||
|
snackbar = mockk(relaxed = true)
|
||||||
|
mockkObject(FenixSnackbar.Companion)
|
||||||
|
|
||||||
|
backgroundServices = testContext.components.backgroundServices
|
||||||
|
every { FenixSnackbar.make(any(), any(), any(), any()) } returns snackbar
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
unmockkObject(FenixSnackbar.Companion)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bind updates header text`() {
|
||||||
|
val holder = OnboardingAutomaticSignInViewHolder(view)
|
||||||
|
holder.bind(mockk {
|
||||||
|
every { email } returns "email@example.com"
|
||||||
|
})
|
||||||
|
assertEquals(
|
||||||
|
"You are signed in as email@example.com on another Firefox browser on this phone. Would you like to sign in with this account?",
|
||||||
|
view.header_text.text
|
||||||
|
)
|
||||||
|
assertTrue(view.turn_on_sync_button.isEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `sign in on click`() = runBlocking {
|
||||||
|
val account = mockk<ShareableAccount> {
|
||||||
|
every { email } returns "email@example.com"
|
||||||
|
}
|
||||||
|
every {
|
||||||
|
backgroundServices.accountManager.signInWithShareableAccountAsync(account)
|
||||||
|
} returns CompletableDeferred(SignInWithShareableAccountResult.Success)
|
||||||
|
|
||||||
|
val holder = OnboardingAutomaticSignInViewHolder(view, scope = this)
|
||||||
|
holder.bind(account)
|
||||||
|
holder.onClick(view.turn_on_sync_button)
|
||||||
|
|
||||||
|
assertEquals("Signing in…", view.turn_on_sync_button.text)
|
||||||
|
assertFalse(view.turn_on_sync_button.isEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show error if sign in fails`() = runBlockingTest {
|
||||||
|
val account = mockk<ShareableAccount> {
|
||||||
|
every { email } returns "email@example.com"
|
||||||
|
}
|
||||||
|
every {
|
||||||
|
backgroundServices.accountManager.signInWithShareableAccountAsync(account)
|
||||||
|
} returns CompletableDeferred(SignInWithShareableAccountResult.Failure)
|
||||||
|
|
||||||
|
val holder = OnboardingAutomaticSignInViewHolder(view, scope = this)
|
||||||
|
holder.bind(account)
|
||||||
|
holder.onClick(view.turn_on_sync_button)
|
||||||
|
|
||||||
|
assertEquals("Yes, sign me in", view.turn_on_sync_button.text)
|
||||||
|
assertTrue(view.turn_on_sync_button.isEnabled)
|
||||||
|
verify { snackbar.setText("Failed to sign-in") }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_finish.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
import org.mozilla.fenix.home.sessioncontrol.OnboardingInteractor
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingFinishViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var interactor: OnboardingInteractor
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingFinishViewHolder.LAYOUT_ID, null)
|
||||||
|
interactor = mockk(relaxed = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `call interactor on click`() {
|
||||||
|
OnboardingFinishViewHolder(view, interactor)
|
||||||
|
|
||||||
|
view.finish_button.performClick()
|
||||||
|
verify { interactor.onStartBrowsingClicked() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_header.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingHeaderViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingHeaderViewHolder.LAYOUT_ID, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bind header text`() {
|
||||||
|
OnboardingHeaderViewHolder(view)
|
||||||
|
|
||||||
|
assertEquals("Welcome to Firefox Preview!", view.header_text.text)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.Navigation
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.unmockkStatic
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_manual_signin.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingManualSignInViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var navController: NavController
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingManualSignInViewHolder.LAYOUT_ID, null)
|
||||||
|
navController = mockk(relaxed = true)
|
||||||
|
|
||||||
|
mockkStatic(Navigation::class)
|
||||||
|
every { Navigation.findNavController(view) } returns navController
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
unmockkStatic(Navigation::class)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bind header text`() {
|
||||||
|
OnboardingManualSignInViewHolder(view).bind()
|
||||||
|
|
||||||
|
assertEquals("Get the most out of Firefox Preview.", view.header_text.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `navigate on click`() {
|
||||||
|
OnboardingManualSignInViewHolder(view)
|
||||||
|
view.turn_on_sync_button.performClick()
|
||||||
|
|
||||||
|
verify { navController.navigate(HomeFragmentDirections.actionGlobalTurnOnSync()) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_section_header.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingSectionHeaderViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingSectionHeaderViewHolder.LAYOUT_ID, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bind text`() {
|
||||||
|
val holder = OnboardingSectionHeaderViewHolder(view)
|
||||||
|
holder.bind { "Hello world" }
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
"Hello world",
|
||||||
|
view.section_header_text.text
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* 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.home.sessioncontrol.viewholders.onboarding
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.android.synthetic.main.onboarding_toolbar_position_picker.view.*
|
||||||
|
import mozilla.components.support.test.robolectric.testContext
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
@RunWith(FenixRobolectricTestRunner::class)
|
||||||
|
class OnboardingToolbarPositionPickerViewHolderTest {
|
||||||
|
|
||||||
|
private lateinit var view: View
|
||||||
|
private lateinit var settings: Settings
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
view = LayoutInflater.from(testContext)
|
||||||
|
.inflate(OnboardingToolbarPositionPickerViewHolder.LAYOUT_ID, null)
|
||||||
|
settings = mockk(relaxed = true)
|
||||||
|
|
||||||
|
Settings.instance = settings
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
Settings.instance = null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bottom illustration should select corresponding radio button`() {
|
||||||
|
every { settings.shouldUseBottomToolbar } returns false
|
||||||
|
OnboardingToolbarPositionPickerViewHolder(view)
|
||||||
|
assertTrue(view.toolbar_top_radio_button.isChecked)
|
||||||
|
assertFalse(view.toolbar_bottom_radio_button.isChecked)
|
||||||
|
|
||||||
|
view.toolbar_bottom_image.performClick()
|
||||||
|
assertFalse(view.toolbar_top_radio_button.isChecked)
|
||||||
|
assertTrue(view.toolbar_bottom_radio_button.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `top illustration should select corresponding radio button`() {
|
||||||
|
every { settings.shouldUseBottomToolbar } returns true
|
||||||
|
OnboardingToolbarPositionPickerViewHolder(view)
|
||||||
|
assertFalse(view.toolbar_top_radio_button.isChecked)
|
||||||
|
assertTrue(view.toolbar_bottom_radio_button.isChecked)
|
||||||
|
|
||||||
|
view.toolbar_top_image.performClick()
|
||||||
|
assertTrue(view.toolbar_top_radio_button.isChecked)
|
||||||
|
assertFalse(view.toolbar_bottom_radio_button.isChecked)
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,6 @@ class BaseSearchTelemetryTest {
|
||||||
engine.installWebExtension(
|
engine.installWebExtension(
|
||||||
id = id,
|
id = id,
|
||||||
url = resourceUrl,
|
url = resourceUrl,
|
||||||
allowContentMessaging = true,
|
|
||||||
onSuccess = any(),
|
onSuccess = any(),
|
||||||
onError = any()
|
onError = any()
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
object AndroidComponents {
|
object AndroidComponents {
|
||||||
const val VERSION = "49.0.20200707131055"
|
const val VERSION = "50.0.20200708130551"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue