For #2327: Adds error state syncing
parent
caa36c31cd
commit
fe50e88fc8
|
@ -36,6 +36,7 @@ import org.mozilla.fenix.library.history.HistoryFragmentDirections
|
||||||
import org.mozilla.fenix.search.SearchFragmentDirections
|
import org.mozilla.fenix.search.SearchFragmentDirections
|
||||||
import org.mozilla.fenix.settings.PairFragmentDirections
|
import org.mozilla.fenix.settings.PairFragmentDirections
|
||||||
import org.mozilla.fenix.settings.SettingsFragmentDirections
|
import org.mozilla.fenix.settings.SettingsFragmentDirections
|
||||||
|
import org.mozilla.fenix.settings.SyncProblemFragmentDirections
|
||||||
import org.mozilla.fenix.settings.TurnOnSyncFragmentDirections
|
import org.mozilla.fenix.settings.TurnOnSyncFragmentDirections
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
@ -200,6 +201,8 @@ open class HomeActivity : AppCompatActivity() {
|
||||||
BrowserDirection.FromTurnOnSync -> TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToBrowserFragment(
|
BrowserDirection.FromTurnOnSync -> TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToBrowserFragment(
|
||||||
customTabSessionId
|
customTabSessionId
|
||||||
)
|
)
|
||||||
|
BrowserDirection.FromSyncProblem ->
|
||||||
|
SyncProblemFragmentDirections.actionSyncProblemFragmentToBrowserFragment(customTabSessionId)
|
||||||
}
|
}
|
||||||
if (sessionObserver == null)
|
if (sessionObserver == null)
|
||||||
sessionObserver = subscribeToSessions()
|
sessionObserver = subscribeToSessions()
|
||||||
|
@ -288,5 +291,6 @@ open class HomeActivity : AppCompatActivity() {
|
||||||
|
|
||||||
enum class BrowserDirection {
|
enum class BrowserDirection {
|
||||||
FromGlobal, FromHome, FromSearch, FromSettings, FromBookmarks,
|
FromGlobal, FromHome, FromSearch, FromSettings, FromBookmarks,
|
||||||
FromBookmarksFolderSelect, FromHistory, FromPair, FromTurnOnSync
|
FromBookmarksFolderSelect, FromHistory, FromPair, FromTurnOnSync,
|
||||||
|
FromSyncProblem
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.fenix.components.toolbar
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import mozilla.components.browser.menu.BrowserMenuBuilder
|
import mozilla.components.browser.menu.BrowserMenuBuilder
|
||||||
import mozilla.components.browser.menu.item.BrowserMenuDivider
|
import mozilla.components.browser.menu.item.BrowserMenuDivider
|
||||||
|
import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem
|
||||||
import mozilla.components.browser.menu.item.BrowserMenuImageText
|
import mozilla.components.browser.menu.item.BrowserMenuImageText
|
||||||
import mozilla.components.browser.menu.item.BrowserMenuItemToolbar
|
import mozilla.components.browser.menu.item.BrowserMenuItemToolbar
|
||||||
import mozilla.components.browser.menu.item.BrowserMenuSwitch
|
import mozilla.components.browser.menu.item.BrowserMenuSwitch
|
||||||
|
@ -18,7 +19,7 @@ import org.mozilla.fenix.ext.components
|
||||||
|
|
||||||
class DefaultToolbarMenu(
|
class DefaultToolbarMenu(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val sessionId: String?,
|
private val hasSyncError: Boolean = false,
|
||||||
private val requestDesktopStateProvider: () -> Boolean = { false },
|
private val requestDesktopStateProvider: () -> Boolean = { false },
|
||||||
private val onItemTapped: (ToolbarMenu.Item) -> Unit = {}
|
private val onItemTapped: (ToolbarMenu.Item) -> Unit = {}
|
||||||
) : ToolbarMenu {
|
) : ToolbarMenu {
|
||||||
|
@ -103,10 +104,21 @@ class DefaultToolbarMenu(
|
||||||
onItemTapped.invoke(ToolbarMenu.Item.Help)
|
onItemTapped.invoke(ToolbarMenu.Item.Help)
|
||||||
},
|
},
|
||||||
|
|
||||||
BrowserMenuImageText(
|
BrowserMenuHighlightableItem(
|
||||||
context.getString(R.string.browser_menu_settings),
|
label = context.getString(R.string.browser_menu_settings),
|
||||||
R.drawable.ic_settings,
|
imageResource = R.drawable.ic_settings,
|
||||||
DefaultThemeManager.resolveAttribute(R.attr.primaryText, context)
|
iconTintColorResource = if (hasSyncError)
|
||||||
|
R.color.sync_error_text_color else
|
||||||
|
DefaultThemeManager.resolveAttribute(R.attr.primaryText, context),
|
||||||
|
textColorResource = if (hasSyncError)
|
||||||
|
R.color.sync_error_text_color else
|
||||||
|
DefaultThemeManager.resolveAttribute(R.attr.primaryText, context),
|
||||||
|
highlight = if (hasSyncError) {
|
||||||
|
BrowserMenuHighlightableItem.Highlight(
|
||||||
|
imageResource = R.drawable.ic_alert,
|
||||||
|
backgroundResource = R.color.sync_error_color
|
||||||
|
)
|
||||||
|
} else null
|
||||||
) {
|
) {
|
||||||
onItemTapped.invoke(ToolbarMenu.Item.Settings)
|
onItemTapped.invoke(ToolbarMenu.Item.Settings)
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.customtabs.CustomTabToolbarMenu
|
import org.mozilla.fenix.customtabs.CustomTabToolbarMenu
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.mvi.UIView
|
import org.mozilla.fenix.mvi.UIView
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
class ToolbarUIView(
|
class ToolbarUIView(
|
||||||
sessionId: String?,
|
sessionId: String?,
|
||||||
|
@ -104,7 +105,7 @@ class ToolbarUIView(
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
DefaultToolbarMenu(this,
|
DefaultToolbarMenu(this,
|
||||||
sessionId = sessionId,
|
hasSyncError = Settings.getInstance(this).hasSyncProblem,
|
||||||
requestDesktopStateProvider = { session?.desktopMode ?: false },
|
requestDesktopStateProvider = { session?.desktopMode ?: false },
|
||||||
onItemTapped = { actionEmitter.onNext(SearchAction.ToolbarMenuItemTapped(it)) }
|
onItemTapped = { actionEmitter.onNext(SearchAction.ToolbarMenuItemTapped(it)) }
|
||||||
)
|
)
|
||||||
|
|
|
@ -77,6 +77,7 @@ import org.mozilla.fenix.onboarding.FenixOnboarding
|
||||||
import org.mozilla.fenix.settings.SupportUtils
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
import org.mozilla.fenix.share.ShareTab
|
import org.mozilla.fenix.share.ShareTab
|
||||||
import org.mozilla.fenix.utils.allowUndo
|
import org.mozilla.fenix.utils.allowUndo
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
@ -682,6 +683,10 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
|
||||||
Mode.Normal
|
Mode.Normal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationProblems() {
|
||||||
|
Settings.getInstance(context!!).setHasAuthenticationProblem(true)
|
||||||
|
emitAccountChanges()
|
||||||
|
}
|
||||||
override fun onAuthenticated(account: OAuthAccount) { emitAccountChanges() }
|
override fun onAuthenticated(account: OAuthAccount) { emitAccountChanges() }
|
||||||
override fun onError(error: Exception) { emitAccountChanges() }
|
override fun onError(error: Exception) { emitAccountChanges() }
|
||||||
override fun onLoggedOut() { emitAccountChanges() }
|
override fun onLoggedOut() { emitAccountChanges() }
|
||||||
|
|
|
@ -50,6 +50,7 @@ import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||||
import org.mozilla.fenix.mvi.getManagedEmitter
|
import org.mozilla.fenix.mvi.getManagedEmitter
|
||||||
import org.mozilla.fenix.utils.allowUndo
|
import org.mozilla.fenix.utils.allowUndo
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions", "LargeClass")
|
@SuppressWarnings("TooManyFunctions", "LargeClass")
|
||||||
|
@ -363,6 +364,10 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
|
||||||
getManagedEmitter<SignInChange>().onNext(SignInChange.SignedOut)
|
getManagedEmitter<SignInChange>().onNext(SignInChange.SignedOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationProblems() {
|
||||||
|
Settings.getInstance(context!!).setHasAuthenticationProblem(true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProfileUpdated(profile: Profile) {
|
override fun onProfileUpdated(profile: Profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.mozilla.fenix.library.bookmarks.SignInViewModel
|
||||||
import org.mozilla.fenix.mvi.ActionBusFactory
|
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
import org.mozilla.fenix.mvi.getAutoDisposeObservable
|
||||||
import org.mozilla.fenix.mvi.getManagedEmitter
|
import org.mozilla.fenix.mvi.getManagedEmitter
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions")
|
@SuppressWarnings("TooManyFunctions")
|
||||||
|
@ -156,6 +157,10 @@ class SelectBookmarkFolderFragment : Fragment(), CoroutineScope, AccountObserver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationProblems() {
|
||||||
|
Settings.getInstance(context!!).setHasAuthenticationProblem(true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onAuthenticated(account: OAuthAccount) {
|
override fun onAuthenticated(account: OAuthAccount) {
|
||||||
getManagedEmitter<SignInChange>().onNext(SignInChange.SignedIn)
|
getManagedEmitter<SignInChange>().onNext(SignInChange.SignedIn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.settings
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceViewHolder
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
|
||||||
|
class AccountPreference : Preference {
|
||||||
|
|
||||||
|
var title: TextView? = null
|
||||||
|
var summary: TextView? = null
|
||||||
|
var errorIcon: ImageView? = null
|
||||||
|
var background: View? = null
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, attributeSetId: Int) : super(
|
||||||
|
context,
|
||||||
|
attrs,
|
||||||
|
attributeSetId
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
layoutResource = R.layout.account_preference
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||||
|
super.onBindViewHolder(holder)
|
||||||
|
title = holder.findViewById(R.id.title) as TextView
|
||||||
|
summary = holder.findViewById(R.id.summary) as TextView
|
||||||
|
errorIcon = holder.findViewById(R.id.error_icon) as ImageView
|
||||||
|
background = holder.itemView
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,8 +9,10 @@ import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.Preference.OnPreferenceClickListener
|
import androidx.preference.Preference.OnPreferenceClickListener
|
||||||
|
@ -50,6 +52,7 @@ import org.mozilla.fenix.R.string.pref_key_tracking_protection_settings
|
||||||
import org.mozilla.fenix.R.string.pref_key_your_rights
|
import org.mozilla.fenix.R.string.pref_key_your_rights
|
||||||
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
|
||||||
|
import org.mozilla.fenix.ext.getColorFromAttr
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
import org.mozilla.fenix.utils.ItsNotBrokenSnack
|
import org.mozilla.fenix.utils.ItsNotBrokenSnack
|
||||||
|
@ -66,12 +69,15 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
job = Job()
|
job = Job()
|
||||||
setupAccountUI()
|
setupAccountUI()
|
||||||
updateSignInVisibility()
|
updateSignInVisibility()
|
||||||
|
displayAccountErrorIfNecessary()
|
||||||
|
|
||||||
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener { sharedPreferences, key ->
|
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
try {
|
try {
|
||||||
context?.let {
|
context?.let {
|
||||||
it.components.analytics.metrics.track(Event.PreferenceToggled
|
it.components.analytics.metrics.track(
|
||||||
(key, sharedPreferences.getBoolean(key, false), it))
|
Event.PreferenceToggled
|
||||||
|
(key, sharedPreferences.getBoolean(key, false), it)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} catch (e: IllegalArgumentException) {
|
} catch (e: IllegalArgumentException) {
|
||||||
// The event is not tracked
|
// The event is not tracked
|
||||||
|
@ -123,6 +129,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
setupPreferences()
|
setupPreferences()
|
||||||
setupAccountUI()
|
setupAccountUI()
|
||||||
updateSignInVisibility()
|
updateSignInVisibility()
|
||||||
|
displayAccountErrorIfNecessary()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ComplexMethod")
|
@Suppress("ComplexMethod")
|
||||||
|
@ -171,7 +178,12 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
navigateToAbout()
|
navigateToAbout()
|
||||||
}
|
}
|
||||||
resources.getString(pref_key_account) -> {
|
resources.getString(pref_key_account) -> {
|
||||||
navigateToAccountSettings()
|
if (org.mozilla.fenix.utils.Settings.getInstance(preference.context).preferences
|
||||||
|
.getBoolean(context!!.getPreferenceKey(R.string.pref_key_sync_problem), false)) {
|
||||||
|
navigateToSyncProblem()
|
||||||
|
} else {
|
||||||
|
navigateToAccountSettings()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resources.getString(pref_key_delete_browsing_data) -> {
|
resources.getString(pref_key_delete_browsing_data) -> {
|
||||||
navigateToDeleteBrowsingData()
|
navigateToDeleteBrowsingData()
|
||||||
|
@ -302,6 +314,11 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
Navigation.findNavController(view!!).navigate(directions)
|
Navigation.findNavController(view!!).navigate(directions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun navigateToSyncProblem() {
|
||||||
|
val directions = SettingsFragmentDirections.actionSettingsFragmentToSyncProblemFragment()
|
||||||
|
Navigation.findNavController(view!!).navigate(directions)
|
||||||
|
}
|
||||||
|
|
||||||
private fun navigateToAccountSettings() {
|
private fun navigateToAccountSettings() {
|
||||||
val directions =
|
val directions =
|
||||||
SettingsFragmentDirections.actionSettingsFragmentToAccountSettingsFragment()
|
SettingsFragmentDirections.actionSettingsFragmentToAccountSettingsFragment()
|
||||||
|
@ -316,6 +333,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
override fun onAuthenticated(account: OAuthAccount) {
|
override fun onAuthenticated(account: OAuthAccount) {
|
||||||
updateAuthState(account)
|
updateAuthState(account)
|
||||||
updateSignInVisibility()
|
updateSignInVisibility()
|
||||||
|
displayAccountErrorIfNecessary()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(error: Exception) {
|
override fun onError(error: Exception) {
|
||||||
|
@ -329,16 +347,25 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
override fun onLoggedOut() {
|
override fun onLoggedOut() {
|
||||||
updateAuthState()
|
updateAuthState()
|
||||||
updateSignInVisibility()
|
updateSignInVisibility()
|
||||||
|
displayAccountErrorIfNecessary()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onProfileUpdated(profile: Profile) {
|
override fun onProfileUpdated(profile: Profile) {
|
||||||
updateAccountProfile(profile)
|
updateAccountProfile(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationProblems() {
|
||||||
|
org.mozilla.fenix.utils.Settings.getInstance(context!!).setHasAuthenticationProblem(true)
|
||||||
|
displayAccountErrorIfNecessary()
|
||||||
|
}
|
||||||
|
|
||||||
// --- Account UI helpers ---
|
// --- Account UI helpers ---
|
||||||
private fun updateAuthState(account: OAuthAccount? = null) {
|
private fun updateAuthState(account: OAuthAccount? = null) {
|
||||||
// Cache the user's auth state to improve performance of sign in visibility
|
// Cache the user's auth state to improve performance of sign in visibility
|
||||||
org.mozilla.fenix.utils.Settings.getInstance(context!!).setHasCachedAccount(account != null)
|
org.mozilla.fenix.utils.Settings.getInstance(context!!).setHasCachedAccount(account != null)
|
||||||
|
|
||||||
|
// Unset sync problems
|
||||||
|
org.mozilla.fenix.utils.Settings.getInstance(context!!).setHasAuthenticationProblem(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSignInVisibility() {
|
private fun updateSignInVisibility() {
|
||||||
|
@ -363,12 +390,59 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAccountProfile(profile: Profile) {
|
private fun updateAccountProfile(profile: Profile, error: Boolean = false) {
|
||||||
launch {
|
launch {
|
||||||
val preferenceFirefoxAccount =
|
val preferenceFirefoxAccount =
|
||||||
findPreference<Preference>(context!!.getPreferenceKey(pref_key_account))
|
findPreference<AccountPreference>(context!!.getPreferenceKey(pref_key_account))
|
||||||
preferenceFirefoxAccount?.title = profile.displayName.orEmpty()
|
|
||||||
preferenceFirefoxAccount?.summary = profile.email.orEmpty()
|
preferenceFirefoxAccount?.title?.setTextColor(
|
||||||
|
R.attr.primaryText.getColorFromAttr(context!!)
|
||||||
|
)
|
||||||
|
preferenceFirefoxAccount?.title?.text = profile.displayName.orEmpty()
|
||||||
|
preferenceFirefoxAccount?.title?.visibility =
|
||||||
|
if (preferenceFirefoxAccount?.title?.text.isNullOrEmpty()) View.GONE else View.VISIBLE
|
||||||
|
|
||||||
|
preferenceFirefoxAccount?.summary?.setTextColor(
|
||||||
|
R.attr.primaryText.getColorFromAttr(context!!)
|
||||||
|
)
|
||||||
|
preferenceFirefoxAccount?.summary?.text = profile.email.orEmpty()
|
||||||
|
|
||||||
|
preferenceFirefoxAccount?.icon = ContextCompat.getDrawable(context!!, R.drawable.ic_shortcuts)
|
||||||
|
preferenceFirefoxAccount?.errorIcon?.visibility = View.GONE
|
||||||
|
preferenceFirefoxAccount?.background?.background = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun displayAccountErrorIfNecessary() {
|
||||||
|
if (!org.mozilla.fenix.utils.Settings.getInstance(context!!).hasSyncProblem) { return }
|
||||||
|
|
||||||
|
launch {
|
||||||
|
val preferenceFirefoxAccount =
|
||||||
|
findPreference<AccountPreference>(context!!.getPreferenceKey(pref_key_account))
|
||||||
|
|
||||||
|
preferenceFirefoxAccount?.title?.setTextColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
context!!,
|
||||||
|
R.color.sync_error_text_color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
preferenceFirefoxAccount?.title?.text = context!!.getString(R.string.preferences_account_sync_error)
|
||||||
|
preferenceFirefoxAccount?.title?.visibility =
|
||||||
|
if (preferenceFirefoxAccount?.title?.text.isNullOrEmpty()) View.GONE else View.VISIBLE
|
||||||
|
|
||||||
|
preferenceFirefoxAccount?.summary?.setTextColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
context!!,
|
||||||
|
R.color.sync_error_text_color
|
||||||
|
)
|
||||||
|
)
|
||||||
|
preferenceFirefoxAccount?.summary?.text =
|
||||||
|
requireComponents.backgroundServices.accountManager.accountProfile()?.email.orEmpty()
|
||||||
|
|
||||||
|
preferenceFirefoxAccount?.icon = ContextCompat.getDrawable(context!!, R.drawable.ic_account_warning)
|
||||||
|
preferenceFirefoxAccount?.errorIcon?.visibility = View.VISIBLE
|
||||||
|
preferenceFirefoxAccount?.background?.background =
|
||||||
|
ContextCompat.getDrawable(context!!, R.color.sync_error_color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* 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.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.navigation.Navigation
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import org.mozilla.fenix.BrowserDirection
|
||||||
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
|
|
||||||
|
class SyncProblemFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
(activity as AppCompatActivity).title = getString(R.string.sync_reconnect)
|
||||||
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setPreferencesFromResource(R.xml.sync_problem, rootKey)
|
||||||
|
|
||||||
|
val preferenceSignIn =
|
||||||
|
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_sign_in))
|
||||||
|
val preferenceNewAccount =
|
||||||
|
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_create_account))
|
||||||
|
val preferencePairSignIn =
|
||||||
|
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_pair))
|
||||||
|
preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn()
|
||||||
|
preferenceNewAccount?.onPreferenceClickListener = getClickListenerForSignIn()
|
||||||
|
preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClickListenerForSignIn(): Preference.OnPreferenceClickListener {
|
||||||
|
return Preference.OnPreferenceClickListener {
|
||||||
|
requireComponents.services.accountsAuthFeature.beginAuthentication()
|
||||||
|
// TODO The sign-in web content populates session history,
|
||||||
|
// so pressing "back" after signing in won't take us back into the settings screen, but rather up the
|
||||||
|
// session history stack.
|
||||||
|
// We could auto-close this tab once we get to the end of the authentication process?
|
||||||
|
// Via an interceptor, perhaps.
|
||||||
|
view?.let {
|
||||||
|
(activity as HomeActivity).openToBrowser(BrowserDirection.FromSyncProblem)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClickListenerForPairing(): Preference.OnPreferenceClickListener {
|
||||||
|
return Preference.OnPreferenceClickListener {
|
||||||
|
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment()
|
||||||
|
Navigation.findNavController(view!!).navigate(directions)
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,6 @@ import android.content.Intent.ACTION_SEND
|
||||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -109,7 +108,6 @@ class AppShareItemViewHolder(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
itemView.setOnClickListener {
|
itemView.setOnClickListener {
|
||||||
Log.d("Jonathan", "${shareItem?.name} clicked.")
|
|
||||||
shareItem?.let {
|
shareItem?.let {
|
||||||
actionEmitter.onNext(ShareAction.ShareAppClicked(it))
|
actionEmitter.onNext(ShareAction.ShareAppClicked(it))
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,9 @@ class Settings private constructor(context: Context) {
|
||||||
val hasCachedAccount: Boolean
|
val hasCachedAccount: Boolean
|
||||||
get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_cached_account), false)
|
get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_cached_account), false)
|
||||||
|
|
||||||
|
val hasSyncProblem: Boolean
|
||||||
|
get() = preferences.getBoolean(appContext.getPreferenceKey(R.string.pref_key_sync_problem), false)
|
||||||
|
|
||||||
private val autoBounceQuickActionSheetCount: Int
|
private val autoBounceQuickActionSheetCount: Int
|
||||||
get() = (preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_bounce_quick_action), 0))
|
get() = (preferences.getInt(appContext.getPreferenceKey(R.string.pref_key_bounce_quick_action), 0))
|
||||||
|
|
||||||
|
@ -235,6 +238,12 @@ class Settings private constructor(context: Context) {
|
||||||
.apply()
|
.apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setHasAuthenticationProblem(hasProblem: Boolean) {
|
||||||
|
preferences.edit()
|
||||||
|
.putBoolean(appContext.getPreferenceKey(R.string.pref_key_sync_problem), hasProblem)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
private val SitePermissionsRules.Action.id: Int
|
private val SitePermissionsRules.Action.id: Int
|
||||||
get() {
|
get() {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:pathData="M12,2C6.477,2 2,6.477 2,12s4.477,10 10,10 10,-4.477 10,-10c-0.006,-5.52 -4.48,-9.994 -10,-10zM12,20c-4.418,0 -8,-3.582 -8,-8s3.582,-8 8,-8 8,3.582 8,8c-0.005,4.416 -3.584,7.995 -8,8zM12,13c0.552,0 1,-0.448 1,-1L13,8c0,-0.552 -0.448,-1 -1,-1s-1,0.448 -1,1v4c0,0.552 0.448,1 1,1zM12,17c0.552,0 1,-0.448 1,-1s-0.448,-1 -1,-1 -1,0.448 -1,1 0.448,1 1,1z"
|
||||||
|
android:fillColor="@color/sync_error_text_color"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?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"
|
||||||
|
android:id="@+id/account_preference_background"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/icon_frame"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<androidx.preference.internal.PreferenceImageView
|
||||||
|
android:id="@android:id/icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:maxWidth="48dp"
|
||||||
|
app:maxHeight="48dp"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:layout_marginEnd="6dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<TextView android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?primaryText"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fadingEdge="horizontal"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:layout_alignStart="@id/title"
|
||||||
|
android:textColor="?primaryText"
|
||||||
|
android:text="@string/preferences_account_default_name"
|
||||||
|
android:maxLines="4"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout android:id="@android:id/widget_frame"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/error_icon"
|
||||||
|
android:src="@drawable/ic_alert"
|
||||||
|
android:padding="16dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -290,6 +290,8 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_settingsFragment_to_deleteBrowsingDataFragment"
|
android:id="@+id/action_settingsFragment_to_deleteBrowsingDataFragment"
|
||||||
app:destination="@id/deleteBrowsingDataFragment" />
|
app:destination="@id/deleteBrowsingDataFragment" />
|
||||||
|
<action android:id="@+id/action_settingsFragment_to_syncProblemFragment"
|
||||||
|
app:destination="@id/syncProblemFragment"/>
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/dataChoicesFragment"
|
android:id="@+id/dataChoicesFragment"
|
||||||
|
@ -455,4 +457,8 @@
|
||||||
app:popUpTo="@id/quickSettingsSheetDialogFragment"
|
app:popUpTo="@id/quickSettingsSheetDialogFragment"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
</dialog>
|
</dialog>
|
||||||
|
<fragment android:id="@+id/syncProblemFragment" android:name="org.mozilla.fenix.settings.SyncProblemFragment"
|
||||||
|
android:label="SyncProblemFragment">
|
||||||
|
<action android:id="@+id/action_syncProblemFragment_to_browserFragment" app:destination="@id/browserFragment"/>
|
||||||
|
</fragment>
|
||||||
</navigation>
|
</navigation>
|
|
@ -139,6 +139,8 @@
|
||||||
<color name="disabled_text">#cccccc</color>
|
<color name="disabled_text">#cccccc</color>
|
||||||
<color name="violet_05">#E7DFFF</color>
|
<color name="violet_05">#E7DFFF</color>
|
||||||
<color name="text_scale_example_text_color">#232749</color>
|
<color name="text_scale_example_text_color">#232749</color>
|
||||||
|
<color name="sync_error_color">#FFF36E</color>
|
||||||
|
<color name="sync_error_text_color">#960E18</color>
|
||||||
|
|
||||||
<!-- Reader View colors -->
|
<!-- Reader View colors -->
|
||||||
<color name="mozac_feature_readerview_text_color">@color/primary_text_light_theme</color>
|
<color name="mozac_feature_readerview_text_color">@color/primary_text_light_theme</color>
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
<string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string>
|
<string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string>
|
||||||
<string name="pref_key_sync_create_account" translatable="false">pref_key_sync_create_account</string>
|
<string name="pref_key_sync_create_account" translatable="false">pref_key_sync_create_account</string>
|
||||||
<string name="pref_key_sync_syncing_items" translatable="false">pref_key_sync_syncing_items</string>
|
<string name="pref_key_sync_syncing_items" translatable="false">pref_key_sync_syncing_items</string>
|
||||||
|
<string name="pref_key_sync_problem" translatable="false">pref_key_sync_problem</string>
|
||||||
|
|
||||||
<!-- Search Settings -->
|
<!-- Search Settings -->
|
||||||
<string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string>
|
<string name="pref_key_show_search_suggestions" translatable="false">pref_key_show_search_suggestions</string>
|
||||||
|
|
|
@ -19,10 +19,9 @@
|
||||||
app:iconSpaceReserved="false"
|
app:iconSpaceReserved="false"
|
||||||
app:isPreferenceVisible="false">
|
app:isPreferenceVisible="false">
|
||||||
|
|
||||||
<androidx.preference.Preference
|
<org.mozilla.fenix.settings.AccountPreference
|
||||||
android:icon="@drawable/ic_shortcuts"
|
android:icon="@drawable/ic_shortcuts"
|
||||||
android:key="@string/pref_key_account"
|
android:key="@string/pref_key_account"/>
|
||||||
android:title="@string/preferences_account_default_name" />
|
|
||||||
</androidx.preference.PreferenceCategory>
|
</androidx.preference.PreferenceCategory>
|
||||||
|
|
||||||
<androidx.preference.PreferenceCategory
|
<androidx.preference.PreferenceCategory
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<androidx.preference.Preference
|
||||||
|
android:key="@string/pref_key_sync_sign_in"
|
||||||
|
android:title="@string/preferences_sync_sign_in_to_reconnect"
|
||||||
|
android:icon="@drawable/ic_sign_in" />
|
||||||
|
<androidx.preference.Preference
|
||||||
|
android:key="@string/pref_key_sign_out"
|
||||||
|
android:title="@string/preferences_sync_remove_account"/>
|
||||||
|
</androidx.preference.PreferenceScreen>
|
|
@ -29,7 +29,7 @@ private object Versions {
|
||||||
const val androidx_transition = "1.1.0-rc01"
|
const val androidx_transition = "1.1.0-rc01"
|
||||||
const val google_material = "1.1.0-alpha06"
|
const val google_material = "1.1.0-alpha06"
|
||||||
|
|
||||||
const val mozilla_android_components = "0.54.0-SNAPSHOT"
|
const val mozilla_android_components = "0.55.0-SNAPSHOT"
|
||||||
// Note that android-components also depends on application-services,
|
// Note that android-components also depends on application-services,
|
||||||
// and in fact is our main source of appservices-related functionality.
|
// and in fact is our main source of appservices-related functionality.
|
||||||
// The version number below tracks the application-services version
|
// The version number below tracks the application-services version
|
||||||
|
|
Loading…
Reference in New Issue