Closes #2593: FxA automatic sign-in integration
parent
210864186b
commit
ae33234bbc
|
@ -5,6 +5,7 @@
|
|||
package org.mozilla.fenix.home
|
||||
|
||||
import android.animation.Animator
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.res.Resources
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
|
@ -158,7 +159,7 @@ class HomeFragment : Fragment(), AccountObserver {
|
|||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_home, container, false)
|
||||
|
||||
val mode = currentMode()
|
||||
val mode = currentMode(view.context)
|
||||
|
||||
sessionControlComponent = SessionControlComponent(
|
||||
view.homeLayout,
|
||||
|
@ -300,7 +301,7 @@ class HomeFragment : Fragment(), AccountObserver {
|
|||
getManagedEmitter<SessionControlChange>().onNext(
|
||||
SessionControlChange.Change(
|
||||
tabs = getListOfSessions().toTabs(),
|
||||
mode = currentMode(),
|
||||
mode = currentMode(context!!),
|
||||
collections = requireComponents.core.tabCollectionStorage.cachedTabCollections
|
||||
)
|
||||
)
|
||||
|
@ -325,7 +326,7 @@ class HomeFragment : Fragment(), AccountObserver {
|
|||
is OnboardingAction.Finish -> {
|
||||
onboarding.finish()
|
||||
|
||||
val mode = currentMode()
|
||||
val mode = currentMode(context!!)
|
||||
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode))
|
||||
}
|
||||
}
|
||||
|
@ -705,12 +706,18 @@ class HomeFragment : Fragment(), AccountObserver {
|
|||
nav(R.id.homeFragment, directions)
|
||||
}
|
||||
|
||||
private fun currentMode(): Mode = if (!onboarding.userHasBeenOnboarded()) {
|
||||
val account = requireComponents.backgroundServices.accountManager.authenticatedAccount()
|
||||
if (account == null) {
|
||||
Mode.Onboarding(OnboardingState.SignedOut)
|
||||
private fun currentMode(context: Context): Mode = if (!onboarding.userHasBeenOnboarded()) {
|
||||
val accountManager = requireComponents.backgroundServices.accountManager
|
||||
val account = accountManager.authenticatedAccount()
|
||||
if (account != null) {
|
||||
Mode.Onboarding(OnboardingState.SignedIn)
|
||||
} else {
|
||||
Mode.Onboarding(OnboardingState.ManuallySignedIn)
|
||||
val availableAccounts = accountManager.shareableAccounts(context)
|
||||
if (availableAccounts.isEmpty()) {
|
||||
Mode.Onboarding(OnboardingState.SignedOutNoAutoSignIn)
|
||||
} else {
|
||||
Mode.Onboarding(OnboardingState.SignedOutCanAutoSignIn(availableAccounts[0]))
|
||||
}
|
||||
}
|
||||
} else if ((activity as HomeActivity).browsingModeManager.isPrivate) {
|
||||
Mode.Private
|
||||
|
@ -719,12 +726,22 @@ class HomeFragment : Fragment(), AccountObserver {
|
|||
}
|
||||
|
||||
private fun emitAccountChanges() {
|
||||
val mode = currentMode()
|
||||
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode))
|
||||
context?.let {
|
||||
val mode = currentMode(it)
|
||||
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAuthenticated(account: OAuthAccount) {
|
||||
view?.let {
|
||||
FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText(
|
||||
it.context.getString(R.string.onboarding_firefox_account_sync_is_on)
|
||||
).show()
|
||||
}
|
||||
emitAccountChanges()
|
||||
}
|
||||
|
||||
override fun onAuthenticationProblems() = emitAccountChanges()
|
||||
override fun onAuthenticated(account: OAuthAccount) = emitAccountChanges()
|
||||
override fun onLoggedOut() = emitAccountChanges()
|
||||
override fun onProfileUpdated(profile: Profile) = emitAccountChanges()
|
||||
|
||||
|
|
|
@ -22,9 +22,10 @@ import org.mozilla.fenix.home.sessioncontrol.viewholders.SaveTabGroupViewHolder
|
|||
import org.mozilla.fenix.home.sessioncontrol.viewholders.TabHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.TabInCollectionViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.TabViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingAutomaticSignInViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingFinishViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingFirefoxAccountViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingHeaderViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingManualSignInViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingPrivacyNoticeViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingPrivateBrowsingViewHolder
|
||||
import org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding.OnboardingSectionHeaderViewHolder
|
||||
|
@ -67,9 +68,12 @@ sealed class AdapterItem(@LayoutRes val viewType: Int) {
|
|||
) : AdapterItem(OnboardingSectionHeaderViewHolder.LAYOUT_ID) {
|
||||
override fun sameAs(other: AdapterItem) = other is OnboardingSectionHeader && labelBuilder == other.labelBuilder
|
||||
}
|
||||
data class OnboardingFirefoxAccount(
|
||||
data class OnboardingManualSignIn(
|
||||
val state: OnboardingState
|
||||
) : AdapterItem(OnboardingFirefoxAccountViewHolder.LAYOUT_ID)
|
||||
) : AdapterItem(OnboardingManualSignInViewHolder.LAYOUT_ID)
|
||||
data class OnboardingAutomaticSignIn(
|
||||
val state: OnboardingState
|
||||
) : AdapterItem(OnboardingAutomaticSignInViewHolder.LAYOUT_ID)
|
||||
object OnboardingThemePicker : AdapterItem(OnboardingThemePickerViewHolder.LAYOUT_ID)
|
||||
object OnboardingTrackingProtection : AdapterItem(OnboardingTrackingProtectionViewHolder.LAYOUT_ID)
|
||||
object OnboardingPrivateBrowsing : AdapterItem(OnboardingPrivateBrowsingViewHolder.LAYOUT_ID)
|
||||
|
@ -108,7 +112,8 @@ class SessionControlAdapter(
|
|||
TabInCollectionViewHolder.LAYOUT_ID -> TabInCollectionViewHolder(view, actionEmitter)
|
||||
OnboardingHeaderViewHolder.LAYOUT_ID -> OnboardingHeaderViewHolder(view)
|
||||
OnboardingSectionHeaderViewHolder.LAYOUT_ID -> OnboardingSectionHeaderViewHolder(view)
|
||||
OnboardingFirefoxAccountViewHolder.LAYOUT_ID -> OnboardingFirefoxAccountViewHolder(view)
|
||||
OnboardingAutomaticSignInViewHolder.LAYOUT_ID -> OnboardingAutomaticSignInViewHolder(view)
|
||||
OnboardingManualSignInViewHolder.LAYOUT_ID -> OnboardingManualSignInViewHolder(view)
|
||||
OnboardingThemePickerViewHolder.LAYOUT_ID -> OnboardingThemePickerViewHolder(view)
|
||||
OnboardingTrackingProtectionViewHolder.LAYOUT_ID -> OnboardingTrackingProtectionViewHolder(view)
|
||||
OnboardingPrivateBrowsingViewHolder.LAYOUT_ID -> OnboardingPrivateBrowsingViewHolder(view)
|
||||
|
@ -145,8 +150,13 @@ class SessionControlAdapter(
|
|||
is OnboardingSectionHeaderViewHolder -> holder.bind(
|
||||
(item as AdapterItem.OnboardingSectionHeader).labelBuilder
|
||||
)
|
||||
is OnboardingFirefoxAccountViewHolder -> holder.bind(
|
||||
(item as AdapterItem.OnboardingFirefoxAccount).state == OnboardingState.AutoSignedIn
|
||||
is OnboardingManualSignInViewHolder -> holder.bind()
|
||||
is OnboardingAutomaticSignInViewHolder -> holder.bind(
|
||||
(
|
||||
(
|
||||
item as AdapterItem.OnboardingAutomaticSignIn
|
||||
).state as OnboardingState.SignedOutCanAutoSignIn
|
||||
).withAccount
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import io.reactivex.Observer
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.service.fxa.sharing.ShareableAccount
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.mvi.ViewState
|
||||
import org.mozilla.fenix.mvi.Change
|
||||
|
@ -69,13 +70,13 @@ fun List<Tab>.toSessionBundle(context: Context): MutableList<Session> {
|
|||
/**
|
||||
* Describes various onboarding states.
|
||||
*/
|
||||
enum class OnboardingState {
|
||||
// Signed out, no account carried over from Fennec.
|
||||
SignedOut,
|
||||
// Auto-signed in, via a Fennec account.
|
||||
AutoSignedIn,
|
||||
// Manually signed in while in onboarding.
|
||||
ManuallySignedIn
|
||||
sealed class OnboardingState {
|
||||
// Signed out, without an option to auto-login using a shared FxA account.
|
||||
object SignedOutNoAutoSignIn : OnboardingState()
|
||||
// Signed out, with an option to auto-login into a shared FxA account.
|
||||
data class SignedOutCanAutoSignIn(val withAccount: ShareableAccount) : OnboardingState()
|
||||
// Signed in.
|
||||
object SignedIn : OnboardingState()
|
||||
}
|
||||
|
||||
sealed class Mode {
|
||||
|
|
|
@ -79,17 +79,17 @@ private fun onboardingAdapterItems(onboardingState: OnboardingState): List<Adapt
|
|||
|
||||
// Customize FxA items based on where we are with the account state:
|
||||
items.addAll(when (onboardingState) {
|
||||
OnboardingState.SignedOut -> {
|
||||
OnboardingState.SignedOutNoAutoSignIn -> {
|
||||
listOf(
|
||||
AdapterItem.OnboardingFirefoxAccount(onboardingState)
|
||||
AdapterItem.OnboardingManualSignIn(onboardingState)
|
||||
)
|
||||
}
|
||||
OnboardingState.AutoSignedIn -> {
|
||||
is OnboardingState.SignedOutCanAutoSignIn -> {
|
||||
listOf(
|
||||
AdapterItem.OnboardingFirefoxAccount(onboardingState)
|
||||
AdapterItem.OnboardingAutomaticSignIn(onboardingState)
|
||||
)
|
||||
}
|
||||
else -> listOf()
|
||||
OnboardingState.SignedIn -> listOf()
|
||||
})
|
||||
|
||||
items.addAll(listOf(
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.turn_on_sync_button
|
||||
import kotlinx.android.synthetic.main.onboarding_automatic_signin.view.header_text
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.service.fxa.sharing.ShareableAccount
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.ext.components
|
||||
|
||||
class OnboardingAutomaticSignInViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||
private lateinit var shareableAccount: ShareableAccount
|
||||
|
||||
init {
|
||||
view.turn_on_sync_button.setOnClickListener {
|
||||
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()
|
||||
if (result) {
|
||||
// Success.
|
||||
} else {
|
||||
// Failed to sign-in (either network problem, or 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(it, Snackbar.LENGTH_SHORT).setText(
|
||||
it.context.getString(R.string.onboarding_firefox_account_automatic_signin_failed)
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(account: ShareableAccount) {
|
||||
shareableAccount = account
|
||||
view.header_text.text = view.context.getString(
|
||||
R.string.onboarding_firefox_account_auto_signin_header_2, account.email
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.onboarding_automatic_signin
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
|
||||
|
||||
import android.view.View
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.onboarding_firefox_account.view.*
|
||||
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
|
||||
class OnboardingFirefoxAccountViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||
private val avatarAnonymousDrawable by lazy {
|
||||
AppCompatResources.getDrawable(view.context, R.drawable.ic_onboarding_avatar_anonymous)
|
||||
}
|
||||
private val firefoxAccountsDrawable by lazy {
|
||||
AppCompatResources.getDrawable(view.context, R.drawable.ic_onboarding_firefox_accounts)
|
||||
}
|
||||
|
||||
init {
|
||||
view.turn_on_sync_button.setOnClickListener {
|
||||
val directions = HomeFragmentDirections.actionHomeFragmentToTurnOnSyncFragment()
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(autoSignedIn: Boolean) {
|
||||
updateHeaderText(autoSignedIn)
|
||||
updateButtonVisibility(autoSignedIn)
|
||||
}
|
||||
|
||||
private fun updateButtonVisibility(autoSignedIn: Boolean) {
|
||||
view.turn_on_sync_button.visibility = if (autoSignedIn) View.GONE else View.VISIBLE
|
||||
view.stay_signed_in_button.visibility = if (autoSignedIn) View.VISIBLE else View.GONE
|
||||
view.sign_out_button.visibility = if (autoSignedIn) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun updateHeaderText(autoSignedIn: Boolean) {
|
||||
val icon = if (autoSignedIn) avatarAnonymousDrawable else firefoxAccountsDrawable
|
||||
view.header_text.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon)
|
||||
|
||||
val appName = view.context.getString(R.string.app_name)
|
||||
view.header_text.text =
|
||||
if (autoSignedIn) view.context.getString(R.string.onboarding_firefox_account_auto_signin_header)
|
||||
else view.context.getString(R.string.onboarding_firefox_account_header, appName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.onboarding_firefox_account
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* 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.View
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.onboarding_manual_signin.view.*
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.home.HomeFragmentDirections
|
||||
|
||||
class OnboardingManualSignInViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||
init {
|
||||
view.turn_on_sync_button.setOnClickListener {
|
||||
val directions = HomeFragmentDirections.actionHomeFragmentToTurnOnSyncFragment()
|
||||
Navigation.findNavController(view).navigate(directions)
|
||||
}
|
||||
}
|
||||
|
||||
fun bind() {
|
||||
val appName = view.context.getString(R.string.app_name)
|
||||
view.header_text.text = view.context.getString(R.string.onboarding_firefox_account_header, appName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val LAYOUT_ID = R.layout.onboarding_manual_signin
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/OnboardingCardDark"
|
||||
android:id="@+id/onboarding_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/header_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="14dp"
|
||||
tools:text="@string/onboarding_firefox_account_auto_signin_header_2"
|
||||
android:drawableStart="@drawable/ic_onboarding_avatar_anonymous"
|
||||
android:drawablePadding="12dp"
|
||||
android:textAppearance="@style/Header16TextStyle"
|
||||
android:textColor="@color/onboarding_card_primary_text_dark" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/turn_on_sync_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/button_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:text="@string/onboarding_firefox_account_auto_signin_confirm"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?neutral"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:backgroundTint="@color/onboarding_card_button_background_dark" />
|
||||
|
||||
</LinearLayout>
|
|
@ -18,7 +18,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="14dp"
|
||||
tools:text="@string/onboarding_firefox_account_header"
|
||||
tools:drawableStart="@drawable/ic_onboarding_firefox_accounts"
|
||||
android:drawableStart="@drawable/ic_onboarding_firefox_accounts"
|
||||
android:drawablePadding="12dp"
|
||||
android:textAppearance="@style/Header16TextStyle"
|
||||
android:textColor="@color/onboarding_card_primary_text_dark" />
|
||||
|
@ -39,38 +39,4 @@
|
|||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:backgroundTint="@color/onboarding_card_button_background_dark" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/stay_signed_in_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/button_background"
|
||||
android:backgroundTint="@color/onboarding_card_button_background_dark"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:gravity="center"
|
||||
android:padding="10dp"
|
||||
android:text="@string/onboarding_firefox_account_stay_signed_in"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?neutral"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/sign_out_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/button_background"
|
||||
android:backgroundTint="@color/onboarding_card_button_background_dark"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="10dp"
|
||||
android:text="@string/onboarding_firefox_account_sign_out"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?neutral"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
|
@ -641,13 +641,19 @@
|
|||
<string name="onboarding_firefox_account_header">Get the most out of %s.</string>
|
||||
<!-- text for the firefox account onboarding card header when we detect you're already signed in to
|
||||
another Firefox browser. (The word `Firefox` should not be translated -->
|
||||
<string name="onboarding_firefox_account_auto_signin_header">You are signed in to another Firefox browser on this phone.</string>
|
||||
<!-- text for the button to sign into your Firefox account. The word "Firefox" should not be translated -->
|
||||
<string name="onboarding_firefox_account_auto_signin_header_2">You are signed in as %s on another Firefox browser on this phone. Would you like to sign in with this account?</string>
|
||||
<!-- text for the button to confirm automatic sign-in -->
|
||||
<string name="onboarding_firefox_account_auto_signin_confirm">Yes, sign me in</string>
|
||||
<!-- text for the automatic sign-in button while signing in is in process -->
|
||||
<string name="onboarding_firefox_account_signing_in">Signing in…</string>
|
||||
<!-- text for the button to manually sign into Firefox account. The word "Firefox" should not be translated -->
|
||||
<string name="onboarding_firefox_account_sign_in">Sign in to Firefox</string>
|
||||
<!-- text for the button to stay signed into your Firefox account. -->
|
||||
<string name="onboarding_firefox_account_stay_signed_in">Stay signed in</string>
|
||||
<!-- text for the button to sign out of your Firefox account. -->
|
||||
<string name="onboarding_firefox_account_sign_out">Sign out</string>
|
||||
<!-- text for the button to stay signed out when presented with an option to automatically sign-in. -->
|
||||
<string name="onboarding_firefox_account_stay_signed_out">Stay signed out</string>
|
||||
<!-- text to display in the snackbar once account is signed-in -->
|
||||
<string name="onboarding_firefox_account_sync_is_on">Sync is on</string>
|
||||
<!-- text to display in the snackbar if automatic sign-in fails. user may try again -->
|
||||
<string name="onboarding_firefox_account_automatic_signin_failed">Failed to sign-in</string>
|
||||
<!-- text for the tracking protection onboarding card header -->
|
||||
<string name="onboarding_tracking_protection_header">Protect yourself</string>
|
||||
<!-- text for the tracking protection card description
|
||||
|
|
Loading…
Reference in New Issue