mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-19 09:25:34 +00:00
[fenix] No issue: Clean up preferences code (https://github.com/mozilla-mobile/fenix/pull/4699)
This commit is contained in:
parent
409cea2128
commit
9e9246ada3
@ -5,6 +5,7 @@
|
|||||||
package org.mozilla.fenix.ext
|
package org.mozilla.fenix.ext
|
||||||
|
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
import androidx.navigation.NavOptions
|
import androidx.navigation.NavOptions
|
||||||
@ -29,3 +30,5 @@ fun Fragment.nav(@IdRes id: Int?, directions: NavDirections, extras: Navigator.E
|
|||||||
fun Fragment.nav(@IdRes id: Int?, directions: NavDirections, options: NavOptions) {
|
fun Fragment.nav(@IdRes id: Int?, directions: NavDirections, options: NavOptions) {
|
||||||
findNavController(this).nav(id, directions, options)
|
findNavController(this).nav(id, directions, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Fragment.getPreferenceKey(@StringRes resourceId: Int): String = getString(resourceId)
|
||||||
|
@ -21,12 +21,18 @@ import org.mozilla.fenix.BuildConfig
|
|||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the logo and information about the app, including library versions.
|
||||||
|
*/
|
||||||
class AboutFragment : Fragment() {
|
class AboutFragment : Fragment() {
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
return inflater.inflate(R.layout.fragment_about, container, false)
|
return inflater.inflate(R.layout.fragment_about, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the activity title, displays library version strings, and sets up the [view_licenses_button].
|
||||||
|
*/
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
@ -53,8 +59,8 @@ class AboutFragment : Fragment() {
|
|||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
val buildDate = BuildConfig.BUILD_DATE
|
|
||||||
val content = getString(R.string.about_content, appName)
|
val content = getString(R.string.about_content, appName)
|
||||||
|
val buildDate = BuildConfig.BUILD_DATE
|
||||||
|
|
||||||
about_text.text = aboutText
|
about_text.text = aboutText
|
||||||
about_content.text = content
|
about_content.text = content
|
||||||
@ -62,12 +68,7 @@ class AboutFragment : Fragment() {
|
|||||||
|
|
||||||
view_licenses_button.setOnClickListener {
|
view_licenses_button.setOnClickListener {
|
||||||
startActivity(Intent(context, OssLicensesMenuActivity::class.java))
|
startActivity(Intent(context, OssLicensesMenuActivity::class.java))
|
||||||
OssLicensesMenuActivity.setActivityTitle(
|
OssLicensesMenuActivity.setActivityTitle(getString(R.string.open_source_licenses_title, appName))
|
||||||
getString(
|
|
||||||
R.string.open_source_licenses_title,
|
|
||||||
getString(R.string.app_name)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,44 +6,64 @@ package org.mozilla.fenix.settings
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.preference.Preference
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays font size controls for accessibility.
|
||||||
|
*
|
||||||
|
* Includes an automatic font sizing toggle. When turned on, font sizing follows the Android device settings.
|
||||||
|
* When turned off, the font sizing can be controlled manually within the app.
|
||||||
|
*/
|
||||||
class AccessibilityFragment : PreferenceFragmentCompat() {
|
class AccessibilityFragment : PreferenceFragmentCompat() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
(activity as AppCompatActivity).title = getString(R.string.preferences_accessibility)
|
(activity as AppCompatActivity).title = getString(R.string.preferences_accessibility)
|
||||||
(activity as AppCompatActivity).supportActionBar?.show()
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
val textSizePreference =
|
|
||||||
findPreference<TextPercentageSeekBarPreference>(getString(R.string.pref_key_accessibility_font_scale))
|
|
||||||
textSizePreference?.onPreferenceChangeListener =
|
|
||||||
Preference.OnPreferenceChangeListener { _, newValue ->
|
|
||||||
(newValue as? Int).let {
|
|
||||||
// Value is mapped from 0->30 in steps of 1 so let's convert to float in range 0.5->2.0
|
|
||||||
val newTextScale = ((newValue as Int * STEP_SIZE) + MIN_SCALE_VALUE).toFloat() / PERCENT_TO_DECIMAL
|
|
||||||
Settings.getInstance(context!!).fontSizeFactor = newTextScale
|
|
||||||
requireComponents.core.engine.settings.fontSizeFactor = newTextScale
|
|
||||||
requireComponents.useCases.sessionUseCases.reload.invoke()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
val textSizePreference = findPreference<TextPercentageSeekBarPreference>(
|
||||||
|
getPreferenceKey(R.string.pref_key_accessibility_font_scale)
|
||||||
|
)
|
||||||
|
textSizePreference?.setOnPreferenceChangeListener<Int> { preference, newTextSize ->
|
||||||
|
val settings = Settings.getInstance(preference.context)
|
||||||
|
val components = preference.context.components
|
||||||
|
|
||||||
|
// Value is mapped from 0->30 in steps of 1 so let's convert to float in range 0.5->2.0
|
||||||
|
val newTextScale = ((newTextSize * STEP_SIZE) + MIN_SCALE_VALUE).toFloat() / PERCENT_TO_DECIMAL
|
||||||
|
|
||||||
|
// Save new text scale value. We assume auto sizing is off if this change listener was called.
|
||||||
|
settings.fontSizeFactor = newTextScale
|
||||||
|
components.core.engine.settings.fontSizeFactor = newTextScale
|
||||||
|
|
||||||
|
// Reload the current session to reflect the new text scale
|
||||||
|
components.useCases.sessionUseCases.reload()
|
||||||
|
true
|
||||||
|
}
|
||||||
textSizePreference?.isVisible = !Settings.getInstance(context!!).shouldUseAutoSize
|
textSizePreference?.isVisible = !Settings.getInstance(context!!).shouldUseAutoSize
|
||||||
|
|
||||||
val useAutoSizePreference =
|
val useAutoSizePreference =
|
||||||
findPreference<SwitchPreference>(getString(R.string.pref_key_accessibility_auto_size))
|
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_accessibility_auto_size))
|
||||||
useAutoSizePreference?.setOnPreferenceChangeListener { _, newValue ->
|
useAutoSizePreference?.setOnPreferenceChangeListener<Boolean> { preference, useAutoSize ->
|
||||||
Settings.getInstance(context!!).shouldUseAutoSize = newValue as Boolean
|
val settings = Settings.getInstance(preference.context)
|
||||||
requireComponents.core.engine.settings.automaticFontSizeAdjustment = newValue
|
val components = preference.context.components
|
||||||
if (!newValue) {
|
|
||||||
requireComponents.core.engine.settings.fontSizeFactor = Settings.getInstance(context!!).fontSizeFactor
|
// Save the new setting value
|
||||||
|
settings.shouldUseAutoSize = useAutoSize
|
||||||
|
components.core.engine.settings.automaticFontSizeAdjustment = useAutoSize
|
||||||
|
|
||||||
|
// If using manual sizing, update the engine settings with the local saved setting
|
||||||
|
if (!useAutoSize) {
|
||||||
|
components.core.engine.settings.fontSizeFactor = settings.fontSizeFactor
|
||||||
}
|
}
|
||||||
textSizePreference?.isVisible = !newValue
|
// Show the manual sizing controls if automatic sizing is turned off.
|
||||||
requireComponents.useCases.sessionUseCases.reload.invoke()
|
textSizePreference?.isVisible = !useAutoSize
|
||||||
|
|
||||||
|
// Reload the current session to reflect the new text scale
|
||||||
|
components.useCases.sessionUseCases.reload()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ package org.mozilla.fenix.settings
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isGone
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceViewHolder
|
import androidx.preference.PreferenceViewHolder
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
@ -32,10 +32,7 @@ class AccountAuthErrorPreference @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateEmailView(email: String?) {
|
private fun updateEmailView(email: String?) {
|
||||||
emailView?.text = email.orEmpty()
|
emailView?.text = email
|
||||||
emailView?.visibility = when (email.isNullOrEmpty()) {
|
emailView?.isGone = email.isNullOrEmpty()
|
||||||
true -> View.GONE
|
|
||||||
false -> View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ package org.mozilla.fenix.settings
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.core.view.isGone
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceViewHolder
|
import androidx.preference.PreferenceViewHolder
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
@ -49,10 +49,7 @@ class AccountPreference @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDisplayName(name: String?) {
|
private fun updateDisplayName(name: String?) {
|
||||||
displayNameView?.text = name.orEmpty()
|
displayNameView?.text = name
|
||||||
displayNameView?.visibility = when (displayName.isNullOrEmpty()) {
|
displayNameView?.isGone = displayName.isNullOrEmpty()
|
||||||
true -> View.GONE
|
|
||||||
false -> View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ package org.mozilla.fenix.settings
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -20,66 +20,60 @@ import org.mozilla.fenix.ext.requireComponents
|
|||||||
|
|
||||||
class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver {
|
class AccountProblemFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||||
|
|
||||||
|
private val signInClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())
|
||||||
|
// 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.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val signOutClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
nav(
|
||||||
|
R.id.accountProblemFragment,
|
||||||
|
AccountProblemFragmentDirections.actionAccountProblemFragmentToSignOutFragment()
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
(activity as AppCompatActivity).title = getString(R.string.sync_reconnect)
|
(activity as AppCompatActivity).title = getString(R.string.sync_reconnect)
|
||||||
(activity as AppCompatActivity).supportActionBar?.show()
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
|
|
||||||
|
val accountManager = requireComponents.backgroundServices.accountManager
|
||||||
|
|
||||||
// We may have fixed our auth problem, in which case close this fragment.
|
// We may have fixed our auth problem, in which case close this fragment.
|
||||||
if (requireComponents.backgroundServices.accountManager.authenticatedAccount() != null &&
|
if (accountManager.authenticatedAccount() != null && !accountManager.accountNeedsReauth()) {
|
||||||
!requireComponents.backgroundServices.accountManager.accountNeedsReauth()
|
findNavController().popBackStack()
|
||||||
) {
|
|
||||||
NavHostFragment.findNavController(this).popBackStack()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
requireComponents.backgroundServices.accountManager.register(this, owner = this)
|
accountManager.register(this, owner = this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.sync_problem, rootKey)
|
setPreferencesFromResource(R.xml.sync_problem, rootKey)
|
||||||
|
|
||||||
val preferenceSignIn =
|
val preferenceSignIn =
|
||||||
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_sign_in))
|
findPreference<Preference>(getPreferenceKey(R.string.pref_key_sync_sign_in))
|
||||||
val preferenceSignOut =
|
val preferenceSignOut =
|
||||||
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sign_out))
|
findPreference<Preference>(getPreferenceKey(R.string.pref_key_sign_out))
|
||||||
preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn()
|
preferenceSignIn?.onPreferenceClickListener = signInClickListener
|
||||||
preferenceSignOut?.onPreferenceClickListener = getClickListenerForSignOut()
|
preferenceSignOut?.onPreferenceClickListener = signOutClickListener
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClickListenerForSignIn(): Preference.OnPreferenceClickListener {
|
|
||||||
return Preference.OnPreferenceClickListener {
|
|
||||||
requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())
|
|
||||||
// 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.
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClickListenerForSignOut(): Preference.OnPreferenceClickListener {
|
|
||||||
return Preference.OnPreferenceClickListener {
|
|
||||||
nav(
|
|
||||||
R.id.accountProblemFragment,
|
|
||||||
AccountProblemFragmentDirections.actionAccountProblemFragmentToSignOutFragment()
|
|
||||||
)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're told our auth problems have been fixed; close this fragment.
|
// We're told our auth problems have been fixed; close this fragment.
|
||||||
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) {
|
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) = closeFragment()
|
||||||
lifecycleScope.launch {
|
|
||||||
NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're told there are no more auth problems since there is no more account; close this fragment.
|
// We're told there are no more auth problems since there is no more account; close this fragment.
|
||||||
override fun onLoggedOut() {
|
override fun onLoggedOut() = closeFragment()
|
||||||
|
|
||||||
|
private fun closeFragment() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack()
|
findNavController().popBackStack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,18 @@ import androidx.preference.PreferenceFragmentCompat
|
|||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets the user toggle telemetry on/off.
|
||||||
|
*/
|
||||||
class DataChoicesFragment : PreferenceFragmentCompat() {
|
class DataChoicesFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
private val preferenceChangeListener =
|
private val preferenceChangeListener =
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
when (key) {
|
when (key) {
|
||||||
getString(R.string.pref_key_telemetry) -> {
|
getPreferenceKey(R.string.pref_key_telemetry) -> {
|
||||||
if (sharedPreferences.getBoolean(key, Settings.getInstance(requireContext()).isTelemetryEnabled)) {
|
if (sharedPreferences.getBoolean(key, Settings.getInstance(requireContext()).isTelemetryEnabled)) {
|
||||||
context?.components?.analytics?.metrics?.start()
|
context?.components?.analytics?.metrics?.start()
|
||||||
} else {
|
} else {
|
||||||
@ -51,16 +55,13 @@ class DataChoicesFragment : PreferenceFragmentCompat() {
|
|||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.data_choices_preferences, rootKey)
|
setPreferencesFromResource(R.xml.data_choices_preferences, rootKey)
|
||||||
|
|
||||||
val telemetryPreference = findPreference<SwitchPreference>(getString(R.string.pref_key_telemetry))?.apply {
|
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_telemetry))?.apply {
|
||||||
isChecked = Settings.getInstance(context).isTelemetryEnabled
|
isChecked = Settings.getInstance(context).isTelemetryEnabled
|
||||||
|
|
||||||
val appName = context.getString(R.string.app_name)
|
val appName = context.getString(R.string.app_name)
|
||||||
summary = context.getString(R.string.preferences_usage_data_description, appName)
|
summary = context.getString(R.string.preferences_usage_data_description, appName)
|
||||||
}
|
|
||||||
telemetryPreference?.setOnPreferenceChangeListener { preference, newValue ->
|
onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
|
||||||
.apply()
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,82 +4,22 @@
|
|||||||
|
|
||||||
package org.mozilla.fenix.settings
|
package org.mozilla.fenix.settings
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.RadioButton
|
import android.widget.RadioButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
|
import androidx.preference.Preference
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
|
||||||
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
|
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ThemeManager
|
import org.mozilla.fenix.ThemeManager
|
||||||
|
|
||||||
internal fun SitePermissionsRules.Action.toString(context: Context): String {
|
|
||||||
return when (this) {
|
|
||||||
SitePermissionsRules.Action.ASK_TO_ALLOW -> {
|
|
||||||
context.getString(R.string.preference_option_phone_feature_ask_to_allow)
|
|
||||||
}
|
|
||||||
SitePermissionsRules.Action.BLOCKED -> {
|
|
||||||
context.getString(R.string.preference_option_phone_feature_blocked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun SitePermissions.Status.toString(context: Context): String {
|
|
||||||
return when (this) {
|
|
||||||
SitePermissions.Status.BLOCKED -> {
|
|
||||||
context.getString(R.string.preference_option_phone_feature_blocked)
|
|
||||||
}
|
|
||||||
SitePermissions.Status.NO_DECISION -> {
|
|
||||||
context.getString(R.string.preference_option_phone_feature_ask_to_allow)
|
|
||||||
}
|
|
||||||
SitePermissions.Status.ALLOWED -> {
|
|
||||||
context.getString(R.string.preference_option_phone_feature_allowed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun SitePermissions.toggle(featurePhone: PhoneFeature): SitePermissions {
|
fun SitePermissions.toggle(featurePhone: PhoneFeature): SitePermissions {
|
||||||
return when (featurePhone) {
|
return when (featurePhone) {
|
||||||
PhoneFeature.CAMERA -> {
|
PhoneFeature.CAMERA -> copy(camera = camera.toggle())
|
||||||
copy(
|
PhoneFeature.LOCATION -> copy(location = location.toggle())
|
||||||
camera = camera.toggle()
|
PhoneFeature.MICROPHONE -> copy(microphone = microphone.toggle())
|
||||||
)
|
PhoneFeature.NOTIFICATION -> copy(notification = notification.toggle())
|
||||||
}
|
|
||||||
PhoneFeature.LOCATION -> {
|
|
||||||
copy(
|
|
||||||
location = location.toggle()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
PhoneFeature.MICROPHONE -> {
|
|
||||||
copy(
|
|
||||||
microphone = microphone.toggle()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
PhoneFeature.NOTIFICATION -> {
|
|
||||||
copy(
|
|
||||||
notification = notification.toggle()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun PhoneFeature.getLabel(context: Context): String {
|
|
||||||
return when (this) {
|
|
||||||
PhoneFeature.CAMERA -> context.getString(R.string.preference_phone_feature_camera)
|
|
||||||
PhoneFeature.LOCATION -> context.getString(R.string.preference_phone_feature_location)
|
|
||||||
PhoneFeature.MICROPHONE -> context.getString(R.string.preference_phone_feature_microphone)
|
|
||||||
PhoneFeature.NOTIFICATION -> context.getString(R.string.preference_phone_feature_notification)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun PhoneFeature.getPreferenceKey(context: Context): String {
|
|
||||||
return when (this) {
|
|
||||||
PhoneFeature.CAMERA -> context.getString(R.string.pref_key_phone_feature_camera)
|
|
||||||
PhoneFeature.LOCATION -> context.getString(R.string.pref_key_phone_feature_location)
|
|
||||||
PhoneFeature.MICROPHONE -> context.getString(R.string.pref_key_phone_feature_microphone)
|
|
||||||
PhoneFeature.NOTIFICATION -> context.getString(R.string.pref_key_phone_feature_notification)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,3 +51,18 @@ fun initBlockedByAndroidView(phoneFeature: PhoneFeature, blockedByAndroidView: V
|
|||||||
blockedByAndroidView.visibility = View.GONE
|
blockedByAndroidView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the callback to be invoked when this preference is changed by the user (but before
|
||||||
|
* the internal state has been updated). Allows the type of the preference to be specified.
|
||||||
|
* If the new value doesn't match the preference type the listener isn't called.
|
||||||
|
*
|
||||||
|
* @param onPreferenceChangeListener The callback to be invoked
|
||||||
|
*/
|
||||||
|
inline fun <reified T> Preference.setOnPreferenceChangeListener(
|
||||||
|
crossinline onPreferenceChangeListener: (Preference, T) -> Boolean
|
||||||
|
) {
|
||||||
|
setOnPreferenceChangeListener { preference: Preference, newValue: Any ->
|
||||||
|
(newValue as? T)?.let { onPreferenceChangeListener(preference, it) } ?: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.NavHostFragment.findNavController
|
import androidx.navigation.fragment.NavHostFragment.findNavController
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
import kotlinx.android.synthetic.main.fragment_pair.*
|
import kotlinx.android.synthetic.main.fragment_pair.*
|
||||||
import mozilla.components.feature.qr.QrFeature
|
import mozilla.components.feature.qr.QrFeature
|
||||||
import mozilla.components.support.base.feature.BackHandler
|
import mozilla.components.support.base.feature.BackHandler
|
||||||
@ -68,8 +69,7 @@ class PairFragment : Fragment(), BackHandler {
|
|||||||
|
|
||||||
override fun onBackPressed(): Boolean {
|
override fun onBackPressed(): Boolean {
|
||||||
qrFeature.onBackPressed()
|
qrFeature.onBackPressed()
|
||||||
findNavController(this@PairFragment)
|
findNavController().popBackStack(R.id.turnOnSyncFragment, false)
|
||||||
.popBackStack(R.id.turnOnSyncFragment, false)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,12 @@ import android.Manifest.permission.ACCESS_COARSE_LOCATION
|
|||||||
import android.Manifest.permission.ACCESS_FINE_LOCATION
|
import android.Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
import android.Manifest.permission.RECORD_AUDIO
|
import android.Manifest.permission.RECORD_AUDIO
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||||
|
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||||
import mozilla.components.support.ktx.android.content.isPermissionGranted
|
import mozilla.components.support.ktx.android.content.isPermissionGranted
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
import android.Manifest.permission.CAMERA as CAMERA_PERMISSION
|
import android.Manifest.permission.CAMERA as CAMERA_PERMISSION
|
||||||
|
|
||||||
@ -32,57 +36,50 @@ enum class PhoneFeature(val id: Int, val androidPermissionsList: Array<String>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getActionLabel(context: Context, sitePermissions: SitePermissions? = null, settings: Settings? = null): String {
|
fun getActionLabel(context: Context, sitePermissions: SitePermissions? = null, settings: Settings? = null): String {
|
||||||
val label = when (this) {
|
@StringRes val stringRes = when (getStatus(sitePermissions, settings)) {
|
||||||
CAMERA -> {
|
SitePermissions.Status.BLOCKED -> R.string.preference_option_phone_feature_blocked
|
||||||
sitePermissions?.camera?.toString(context) ?: settings
|
SitePermissions.Status.NO_DECISION -> R.string.preference_option_phone_feature_ask_to_allow
|
||||||
?.sitePermissionsPhoneFeatureCameraAction
|
SitePermissions.Status.ALLOWED -> R.string.preference_option_phone_feature_allowed
|
||||||
?.toString(context)
|
|
||||||
}
|
|
||||||
LOCATION -> {
|
|
||||||
sitePermissions?.location?.toString(context) ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureLocation
|
|
||||||
?.toString(context)
|
|
||||||
}
|
|
||||||
MICROPHONE -> {
|
|
||||||
sitePermissions?.microphone?.toString(context) ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureMicrophoneAction
|
|
||||||
?.toString(context)
|
|
||||||
}
|
|
||||||
NOTIFICATION -> {
|
|
||||||
sitePermissions?.notification?.toString(context) ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureNotificationAction
|
|
||||||
?.toString(context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return requireNotNull(label)
|
return context.getString(stringRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStatus(sitePermissions: SitePermissions? = null, settings: Settings? = null): SitePermissions.Status {
|
fun getStatus(sitePermissions: SitePermissions? = null, settings: Settings? = null): SitePermissions.Status {
|
||||||
val status = when (this) {
|
val status = getStatus(sitePermissions) ?: settings?.let(::getAction)?.toStatus()
|
||||||
CAMERA -> {
|
|
||||||
sitePermissions?.camera ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureCameraAction
|
|
||||||
?.toStatus()
|
|
||||||
}
|
|
||||||
LOCATION -> {
|
|
||||||
sitePermissions?.location ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureLocation
|
|
||||||
?.toStatus()
|
|
||||||
}
|
|
||||||
MICROPHONE -> {
|
|
||||||
sitePermissions?.microphone ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureMicrophoneAction
|
|
||||||
?.toStatus()
|
|
||||||
}
|
|
||||||
NOTIFICATION -> {
|
|
||||||
sitePermissions?.notification ?: settings
|
|
||||||
?.sitePermissionsPhoneFeatureNotificationAction
|
|
||||||
?.toStatus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return requireNotNull(status)
|
return requireNotNull(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getLabel(context: Context): String {
|
||||||
|
return when (this) {
|
||||||
|
CAMERA -> context.getString(R.string.preference_phone_feature_camera)
|
||||||
|
LOCATION -> context.getString(R.string.preference_phone_feature_location)
|
||||||
|
MICROPHONE -> context.getString(R.string.preference_phone_feature_microphone)
|
||||||
|
NOTIFICATION -> context.getString(R.string.preference_phone_feature_notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPreferenceKey(context: Context): String {
|
||||||
|
return when (this) {
|
||||||
|
CAMERA -> context.getPreferenceKey(R.string.pref_key_phone_feature_camera)
|
||||||
|
LOCATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_location)
|
||||||
|
MICROPHONE -> context.getPreferenceKey(R.string.pref_key_phone_feature_microphone)
|
||||||
|
NOTIFICATION -> context.getPreferenceKey(R.string.pref_key_phone_feature_notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAction(settings: Settings): SitePermissionsRules.Action =
|
||||||
|
settings.getSitePermissionsPhoneFeatureAction(this)
|
||||||
|
|
||||||
|
private fun getStatus(sitePermissions: SitePermissions?): SitePermissions.Status? {
|
||||||
|
sitePermissions ?: return null
|
||||||
|
return when (this) {
|
||||||
|
CAMERA -> sitePermissions.camera
|
||||||
|
LOCATION -> sitePermissions.location
|
||||||
|
MICROPHONE -> sitePermissions.microphone
|
||||||
|
NOTIFICATION -> sitePermissions.notification
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun findFeatureBy(permissions: Array<out String>): PhoneFeature? {
|
fun findFeatureBy(permissions: Array<out String>): PhoneFeature? {
|
||||||
return PhoneFeature.values().find { feature ->
|
return PhoneFeature.values().find { feature ->
|
||||||
|
@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
class SearchEngineFragment : PreferenceFragmentCompat() {
|
class SearchEngineFragment : PreferenceFragmentCompat() {
|
||||||
@ -23,25 +24,17 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
|
|||||||
(activity as AppCompatActivity).supportActionBar?.show()
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
|
|
||||||
val searchSuggestionsPreference =
|
val searchSuggestionsPreference =
|
||||||
findPreference<SwitchPreference>(getString(R.string.pref_key_show_search_suggestions))?.apply {
|
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_show_search_suggestions))?.apply {
|
||||||
isChecked = Settings.getInstance(context).showSearchSuggestions
|
isChecked = Settings.getInstance(context).showSearchSuggestions
|
||||||
}
|
}
|
||||||
|
|
||||||
searchSuggestionsPreference?.setOnPreferenceChangeListener { preference, newValue ->
|
searchSuggestionsPreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
|
||||||
.apply()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
val showVisitedSitesBookmarks =
|
val showVisitedSitesBookmarks =
|
||||||
findPreference<SwitchPreference>(getString(R.string.pref_key_show_visited_sites_bookmarks))?.apply {
|
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_show_visited_sites_bookmarks))?.apply {
|
||||||
isChecked = Settings.getInstance(context).shouldShowVisitedSitesBookmarks
|
isChecked = Settings.getInstance(context).shouldShowVisitedSitesBookmarks
|
||||||
}
|
}
|
||||||
|
|
||||||
showVisitedSitesBookmarks?.setOnPreferenceChangeListener { preference, newValue ->
|
showVisitedSitesBookmarks?.onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
|
||||||
.apply()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
|||||||
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
|
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
|
||||||
|
|
||||||
if (SDK_INT <= Build.VERSION_CODES.M) {
|
if (SDK_INT <= Build.VERSION_CODES.M) {
|
||||||
findPreference<DefaultBrowserPreference>(getString(R.string.pref_key_make_default_browser))?.apply {
|
findPreference<DefaultBrowserPreference>(getPreferenceKey(R.string.pref_key_make_default_browser))?.apply {
|
||||||
isVisible = false
|
isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,17 +106,17 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
|||||||
(activity as AppCompatActivity).title = getString(R.string.settings_title)
|
(activity as AppCompatActivity).title = getString(R.string.settings_title)
|
||||||
(activity as AppCompatActivity).supportActionBar?.show()
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
val defaultBrowserPreference =
|
val defaultBrowserPreference =
|
||||||
findPreference<DefaultBrowserPreference>(getString(R.string.pref_key_make_default_browser))
|
findPreference<DefaultBrowserPreference>(getPreferenceKey(R.string.pref_key_make_default_browser))
|
||||||
defaultBrowserPreference?.updateSwitch()
|
defaultBrowserPreference?.updateSwitch()
|
||||||
|
|
||||||
val searchEnginePreference =
|
val searchEnginePreference =
|
||||||
findPreference<Preference>(getString(R.string.pref_key_search_engine_settings))
|
findPreference<Preference>(getPreferenceKey(R.string.pref_key_search_engine_settings))
|
||||||
searchEnginePreference?.summary = context?.let {
|
searchEnginePreference?.summary = context?.let {
|
||||||
requireComponents.search.searchEngineManager.getDefaultSearchEngine(it).name
|
requireComponents.search.searchEngineManager.getDefaultSearchEngine(it).name
|
||||||
}
|
}
|
||||||
|
|
||||||
val trackingProtectionPreference =
|
val trackingProtectionPreference =
|
||||||
findPreference<Preference>(getString(R.string.pref_key_tracking_protection_settings))
|
findPreference<Preference>(getPreferenceKey(R.string.pref_key_tracking_protection_settings))
|
||||||
trackingProtectionPreference?.summary = context?.let {
|
trackingProtectionPreference?.summary = context?.let {
|
||||||
if (org.mozilla.fenix.utils.Settings.getInstance(it).shouldUseTrackingProtection) {
|
if (org.mozilla.fenix.utils.Settings.getInstance(it).shouldUseTrackingProtection) {
|
||||||
getString(R.string.tracking_protection_on)
|
getString(R.string.tracking_protection_on)
|
||||||
@ -126,12 +126,12 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val themesPreference =
|
val themesPreference =
|
||||||
findPreference<Preference>(getString(R.string.pref_key_theme))
|
findPreference<Preference>(getPreferenceKey(R.string.pref_key_theme))
|
||||||
themesPreference?.summary = context?.let {
|
themesPreference?.summary = context?.let {
|
||||||
org.mozilla.fenix.utils.Settings.getInstance(it).themeSettingString
|
org.mozilla.fenix.utils.Settings.getInstance(it).themeSettingString
|
||||||
}
|
}
|
||||||
|
|
||||||
val aboutPreference = findPreference<Preference>(getString(R.string.pref_key_about))
|
val aboutPreference = findPreference<Preference>(getPreferenceKey(R.string.pref_key_about))
|
||||||
val appName = getString(R.string.app_name)
|
val appName = getString(R.string.app_name)
|
||||||
aboutPreference?.title = getString(R.string.preferences_about, appName)
|
aboutPreference?.title = getString(R.string.preferences_about, appName)
|
||||||
|
|
||||||
@ -198,16 +198,16 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
|||||||
navigateToThemeSettings()
|
navigateToThemeSettings()
|
||||||
}
|
}
|
||||||
resources.getString(pref_key_privacy_link) -> {
|
resources.getString(pref_key_privacy_link) -> {
|
||||||
requireContext().apply {
|
requireContext().let { context ->
|
||||||
val intent = SupportUtils.createCustomTabIntent(this, SupportUtils.PRIVACY_NOTICE_URL)
|
val intent = SupportUtils.createCustomTabIntent(context, SupportUtils.PRIVACY_NOTICE_URL)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resources.getString(pref_key_your_rights) -> {
|
resources.getString(pref_key_your_rights) -> {
|
||||||
requireContext().apply {
|
requireContext().let { context ->
|
||||||
val intent = SupportUtils.createCustomTabIntent(
|
val intent = SupportUtils.createCustomTabIntent(
|
||||||
this,
|
context,
|
||||||
SupportUtils.getSumoURLForTopic(context!!, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
||||||
)
|
)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
@ -229,9 +229,9 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupPreferences() {
|
private fun setupPreferences() {
|
||||||
val makeDefaultBrowserKey = context!!.getPreferenceKey(pref_key_make_default_browser)
|
val makeDefaultBrowserKey = getPreferenceKey(pref_key_make_default_browser)
|
||||||
val leakKey = context!!.getPreferenceKey(pref_key_leakcanary)
|
val leakKey = getPreferenceKey(pref_key_leakcanary)
|
||||||
val debuggingKey = context!!.getPreferenceKey(pref_key_remote_debugging)
|
val debuggingKey = getPreferenceKey(pref_key_remote_debugging)
|
||||||
|
|
||||||
val preferenceMakeDefaultBrowser = findPreference<Preference>(makeDefaultBrowserKey)
|
val preferenceMakeDefaultBrowser = findPreference<Preference>(makeDefaultBrowserKey)
|
||||||
val preferenceLeakCanary = findPreference<Preference>(leakKey)
|
val preferenceLeakCanary = findPreference<Preference>(leakKey)
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.mozilla.fenix.settings
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the corresponding [android.content.SharedPreferences] when the boolean [Preference] is changed.
|
||||||
|
* The preference key is used as the shared preference key.
|
||||||
|
*/
|
||||||
|
class SharedPreferenceUpdater : Preference.OnPreferenceChangeListener {
|
||||||
|
|
||||||
|
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
||||||
|
val newBooleanValue = newValue as? Boolean ?: return false
|
||||||
|
Settings.getInstance(preference.context).preferences.edit {
|
||||||
|
putBoolean(preference.key, newBooleanValue)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ import org.jetbrains.anko.noButton
|
|||||||
import org.jetbrains.anko.yesButton
|
import org.jetbrains.anko.yesButton
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.CAMERA
|
import org.mozilla.fenix.settings.PhoneFeature.CAMERA
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.LOCATION
|
import org.mozilla.fenix.settings.PhoneFeature.LOCATION
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
|
import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
|
||||||
@ -83,7 +84,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindClearPermissionsButton() {
|
private fun bindClearPermissionsButton() {
|
||||||
val keyPreference = getString(R.string.pref_key_exceptions_clear_site_permissions)
|
val keyPreference = getPreferenceKey(R.string.pref_key_exceptions_clear_site_permissions)
|
||||||
val button: Preference = requireNotNull(findPreference(keyPreference))
|
val button: Preference = requireNotNull(findPreference(keyPreference))
|
||||||
|
|
||||||
button.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
button.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
@ -11,10 +11,7 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.Preference.OnPreferenceClickListener
|
import androidx.preference.Preference.OnPreferenceClickListener
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.CAMERA
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.LOCATION
|
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
|
|
||||||
import org.mozilla.fenix.settings.PhoneFeature.NOTIFICATION
|
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions")
|
@SuppressWarnings("TooManyFunctions")
|
||||||
@ -36,13 +33,12 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupPreferences() {
|
private fun setupPreferences() {
|
||||||
|
|
||||||
bindCategoryPhoneFeatures()
|
bindCategoryPhoneFeatures()
|
||||||
bindExceptions()
|
bindExceptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindExceptions() {
|
private fun bindExceptions() {
|
||||||
val keyExceptions = getString(R.string.pref_key_show_site_exceptions)
|
val keyExceptions = getPreferenceKey(R.string.pref_key_show_site_exceptions)
|
||||||
val exceptionsCategory = requireNotNull<Preference>(findPreference(keyExceptions))
|
val exceptionsCategory = requireNotNull<Preference>(findPreference(keyExceptions))
|
||||||
|
|
||||||
exceptionsCategory.onPreferenceClickListener = OnPreferenceClickListener {
|
exceptionsCategory.onPreferenceClickListener = OnPreferenceClickListener {
|
||||||
@ -53,33 +49,17 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindCategoryPhoneFeatures() {
|
private fun bindCategoryPhoneFeatures() {
|
||||||
val settings = Settings.getInstance(requireContext())
|
PhoneFeature.values().forEach(::initPhoneFeature)
|
||||||
|
|
||||||
val cameraAction = settings
|
|
||||||
.sitePermissionsPhoneFeatureCameraAction
|
|
||||||
.toString(requireContext())
|
|
||||||
|
|
||||||
val locationAction = settings
|
|
||||||
.sitePermissionsPhoneFeatureLocation
|
|
||||||
.toString(requireContext())
|
|
||||||
|
|
||||||
val microPhoneAction = settings
|
|
||||||
.sitePermissionsPhoneFeatureMicrophoneAction
|
|
||||||
.toString(requireContext())
|
|
||||||
|
|
||||||
val notificationAction = settings
|
|
||||||
.sitePermissionsPhoneFeatureNotificationAction
|
|
||||||
.toString(requireContext())
|
|
||||||
|
|
||||||
initPhoneFeature(CAMERA, cameraAction)
|
|
||||||
initPhoneFeature(LOCATION, locationAction)
|
|
||||||
initPhoneFeature(MICROPHONE, microPhoneAction)
|
|
||||||
initPhoneFeature(NOTIFICATION, notificationAction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initPhoneFeature(phoneFeature: PhoneFeature, summary: String) {
|
private fun initPhoneFeature(phoneFeature: PhoneFeature) {
|
||||||
val keyPreference = phoneFeature.getPreferenceKey(requireContext())
|
val context = requireContext()
|
||||||
val cameraPhoneFeatures: Preference = requireNotNull(findPreference(keyPreference))
|
val settings = Settings.getInstance(context)
|
||||||
|
|
||||||
|
val summary = phoneFeature.getActionLabel(context, settings = settings)
|
||||||
|
val preferenceKey = phoneFeature.getPreferenceKey(context)
|
||||||
|
|
||||||
|
val cameraPhoneFeatures: Preference = requireNotNull(findPreference(preferenceKey))
|
||||||
cameraPhoneFeatures.summary = summary
|
cameraPhoneFeatures.summary = summary
|
||||||
|
|
||||||
cameraPhoneFeatures.onPreferenceClickListener = OnPreferenceClickListener {
|
cameraPhoneFeatures.onPreferenceClickListener = OnPreferenceClickListener {
|
||||||
|
@ -92,7 +92,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
|
private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
|
||||||
if (phoneFeature.action == action) {
|
if (phoneFeature.getAction(settings) == action) {
|
||||||
this.isChecked = true
|
this.isChecked = true
|
||||||
this.setStartCheckedIndicator()
|
this.setStartCheckedIndicator()
|
||||||
}
|
}
|
||||||
@ -119,16 +119,6 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val PhoneFeature.action: SitePermissionsRules.Action
|
|
||||||
get() {
|
|
||||||
return when (phoneFeature) {
|
|
||||||
PhoneFeature.CAMERA -> settings.sitePermissionsPhoneFeatureCameraAction
|
|
||||||
PhoneFeature.LOCATION -> settings.sitePermissionsPhoneFeatureLocation
|
|
||||||
PhoneFeature.MICROPHONE -> settings.sitePermissionsPhoneFeatureMicrophoneAction
|
|
||||||
PhoneFeature.NOTIFICATION -> settings.sitePermissionsPhoneFeatureNotificationAction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initSettingsButton(rootView: View) {
|
private fun initSettingsButton(rootView: View) {
|
||||||
val button = rootView.findViewById<Button>(R.id.settings_button)
|
val button = rootView.findViewById<Button>(R.id.settings_button)
|
||||||
button.setOnClickListener {
|
button.setOnClickListener {
|
||||||
@ -144,11 +134,6 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun saveActionInSettings(action: SitePermissionsRules.Action) {
|
private fun saveActionInSettings(action: SitePermissionsRules.Action) {
|
||||||
when (phoneFeature) {
|
settings.setSitePermissionsPhoneFeatureAction(phoneFeature, action)
|
||||||
PhoneFeature.CAMERA -> settings.sitePermissionsPhoneFeatureCameraAction = action
|
|
||||||
PhoneFeature.LOCATION -> settings.sitePermissionsPhoneFeatureLocation = action
|
|
||||||
PhoneFeature.MICROPHONE -> settings.sitePermissionsPhoneFeatureMicrophoneAction = action
|
|
||||||
PhoneFeature.NOTIFICATION -> settings.sitePermissionsPhoneFeatureNotificationAction = action
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,23 +39,19 @@ import org.mozilla.fenix.R
|
|||||||
import java.text.NumberFormat
|
import java.text.NumberFormat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference based on android.preference.SeekBarPreference but uses support preference as a base
|
* Preference based on android.preference.SeekBarPreference but uses support preference as a base.
|
||||||
* . It contains a title and a [SeekBar] and a SeekBar value [TextView] and an Example [TextView].
|
* It contains a title and a [SeekBar] and a SeekBar value [TextView] and an Example [TextView].
|
||||||
* The actual preference layout is customizable by setting `android:layout` on the
|
* The actual preference layout is customizable by setting `android:layout` on the
|
||||||
* preference widget layout or `seekBarPreferenceStyle` attribute.
|
* preference widget layout or `seekBarPreferenceStyle` attribute.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* The [SeekBar] within the preference can be defined adjustable or not by setting `adjustable` attribute.
|
* The [SeekBar] within the preference can be defined adjustable or not by setting `adjustable` attribute.
|
||||||
* If adjustable, the preference will be responsive to DPAD left/right keys.
|
* If adjustable, the preference will be responsive to DPAD left/right keys.
|
||||||
* Otherwise, it skips those keys.
|
* Otherwise, it skips those keys.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* The [SeekBar] value view can be shown or disabled by setting `showSeekBarValue`
|
* The [SeekBar] value view can be shown or disabled by setting `showSeekBarValue`
|
||||||
* attribute to true or false, respectively.
|
* attribute to true or false, respectively.
|
||||||
*
|
*
|
||||||
*
|
* Other [SeekBar] specific attributes (e.g. `title, summary, defaultValue, min, max`)
|
||||||
* Other [SeekBar] specific attributes (e.g. `title, summary, defaultValue, min,
|
|
||||||
* max`)
|
|
||||||
* can be set directly on the preference widget layout.
|
* can be set directly on the preference widget layout.
|
||||||
*/
|
*/
|
||||||
class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||||
@ -64,21 +60,32 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
defStyleAttr: Int = R.attr.seekBarPreferenceStyle,
|
defStyleAttr: Int = R.attr.seekBarPreferenceStyle,
|
||||||
defStyleRes: Int = 0
|
defStyleRes: Int = 0
|
||||||
) : Preference(context, attrs, defStyleAttr, defStyleRes) {
|
) : Preference(context, attrs, defStyleAttr, defStyleRes) {
|
||||||
internal /* synthetic access */ var mSeekBarValue: Int = 0
|
/* synthetic access */
|
||||||
internal /* synthetic access */ var mMin: Int = 0
|
internal var mSeekBarValue: Int = 0
|
||||||
|
/* synthetic access */
|
||||||
|
internal var mMin: Int = 0
|
||||||
private var mMax: Int = 0
|
private var mMax: Int = 0
|
||||||
private var mSeekBarIncrement: Int = 0
|
private var mSeekBarIncrement: Int = 0
|
||||||
internal /* synthetic access */ var mTrackingTouch: Boolean = false
|
/* synthetic access */
|
||||||
internal /* synthetic access */ var mSeekBar: SeekBar? = null
|
internal var mTrackingTouch: Boolean = false
|
||||||
|
/* synthetic access */
|
||||||
|
internal var mSeekBar: SeekBar? = null
|
||||||
private var mSeekBarValueTextView: TextView? = null
|
private var mSeekBarValueTextView: TextView? = null
|
||||||
private var mExampleTextTextView: TextView? = null
|
private var mExampleTextTextView: TextView? = null
|
||||||
// Whether the SeekBar should respond to the left/right keys
|
/**
|
||||||
/* synthetic access */ var isAdjustable: Boolean = false
|
* Whether the SeekBar should respond to the left/right keys
|
||||||
// Whether to show the SeekBar value TextView next to the bar
|
*/
|
||||||
|
/* synthetic access */
|
||||||
|
var isAdjustable: Boolean = false
|
||||||
|
/**
|
||||||
|
* Whether to show the SeekBar value TextView next to the bar
|
||||||
|
*/
|
||||||
private var mShowSeekBarValue: Boolean = false
|
private var mShowSeekBarValue: Boolean = false
|
||||||
// Whether the SeekBarPreference should continuously save the Seekbar value while it is being
|
/**
|
||||||
// dragged.
|
* Whether the SeekBarPreference should continuously save the Seekbar value while it is being dragged.
|
||||||
/* synthetic access */ var updatesContinuously: Boolean = false
|
*/
|
||||||
|
/* synthetic access */
|
||||||
|
var updatesContinuously: Boolean = false
|
||||||
/**
|
/**
|
||||||
* Listener reacting to the [SeekBar] changing value by the user
|
* Listener reacting to the [SeekBar] changing value by the user
|
||||||
*/
|
*/
|
||||||
@ -111,26 +118,21 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
* to be handled accordingly.
|
* to be handled accordingly.
|
||||||
*/
|
*/
|
||||||
private val mSeekBarKeyListener = View.OnKeyListener { _, keyCode, event ->
|
private val mSeekBarKeyListener = View.OnKeyListener { _, keyCode, event ->
|
||||||
if (event.action != KeyEvent.ACTION_DOWN) {
|
return@OnKeyListener if (event.action != KeyEvent.ACTION_DOWN) {
|
||||||
return@OnKeyListener false
|
false
|
||||||
}
|
} else if (!isAdjustable && (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)) {
|
||||||
|
|
||||||
if (!isAdjustable && (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)) {
|
|
||||||
// Right or left keys are pressed when in non-adjustable mode; Skip the keys.
|
// Right or left keys are pressed when in non-adjustable mode; Skip the keys.
|
||||||
return@OnKeyListener false
|
false
|
||||||
}
|
} else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||||
|
// We don't want to propagate the click keys down to the SeekBar view since it will
|
||||||
// We don't want to propagate the click keys down to the SeekBar view since it will
|
// create the ripple effect for the thumb.
|
||||||
// create the ripple effect for the thumb.
|
false
|
||||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
|
} else if (mSeekBar == null) {
|
||||||
return@OnKeyListener false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSeekBar == null) {
|
|
||||||
Log.e(TAG, "SeekBar view is null and hence cannot be adjusted.")
|
Log.e(TAG, "SeekBar view is null and hence cannot be adjusted.")
|
||||||
return@OnKeyListener false
|
false
|
||||||
|
} else {
|
||||||
|
mSeekBar!!.onKeyDown(keyCode, event)
|
||||||
}
|
}
|
||||||
mSeekBar!!.onKeyDown(keyCode, event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,13 +160,14 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
* from the default mKeyProgressIncrement value in [android.widget.AbsSeekBar].
|
* from the default mKeyProgressIncrement value in [android.widget.AbsSeekBar].
|
||||||
* @return The amount of increment on the [SeekBar] performed after each user's arrow
|
* @return The amount of increment on the [SeekBar] performed after each user's arrow
|
||||||
* key press
|
* key press
|
||||||
*
|
|
||||||
* Sets the increment amount on the [SeekBar] for each arrow key press.
|
|
||||||
* @param seekBarIncrement The amount to increment or decrement when the user presses an
|
|
||||||
* arrow key.
|
|
||||||
*/
|
*/
|
||||||
var seekBarIncrement: Int
|
var seekBarIncrement: Int
|
||||||
get() = mSeekBarIncrement
|
get() = mSeekBarIncrement
|
||||||
|
/**
|
||||||
|
* Sets the increment amount on the [SeekBar] for each arrow key press.
|
||||||
|
* @param seekBarIncrement The amount to increment or decrement when the user presses an
|
||||||
|
* arrow key.
|
||||||
|
*/
|
||||||
set(seekBarIncrement) {
|
set(seekBarIncrement) {
|
||||||
if (seekBarIncrement != mSeekBarIncrement) {
|
if (seekBarIncrement != mSeekBarIncrement) {
|
||||||
mSeekBarIncrement = Math.min(mMax - mMin, Math.abs(seekBarIncrement))
|
mSeekBarIncrement = Math.min(mMax - mMin, Math.abs(seekBarIncrement))
|
||||||
@ -173,10 +176,7 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the upper bound set on the [SeekBar].
|
* Gets/Sets the upper bound set on the [SeekBar].
|
||||||
* @return The upper bound set
|
|
||||||
* Sets the upper bound on the [SeekBar].
|
|
||||||
* @param max The upper bound to set
|
|
||||||
*/
|
*/
|
||||||
var max: Int
|
var max: Int
|
||||||
get() = mMax
|
get() = mMax
|
||||||
@ -195,29 +195,27 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
* Gets whether the current [SeekBar] value is displayed to the user.
|
* Gets whether the current [SeekBar] value is displayed to the user.
|
||||||
* @return Whether the current [SeekBar] value is displayed to the user
|
* @return Whether the current [SeekBar] value is displayed to the user
|
||||||
* @see .setShowSeekBarValue
|
* @see .setShowSeekBarValue
|
||||||
* Sets whether the current [SeekBar] value is displayed to the user.
|
|
||||||
* @param showSeekBarValue Whether the current [SeekBar] value is displayed to the user
|
|
||||||
* @see .getShowSeekBarValue
|
|
||||||
*/
|
*/
|
||||||
var showSeekBarValue: Boolean
|
var showSeekBarValue: Boolean
|
||||||
get() = mShowSeekBarValue
|
get() = mShowSeekBarValue
|
||||||
|
/**
|
||||||
|
* Sets whether the current [SeekBar] value is displayed to the user.
|
||||||
|
* @param showSeekBarValue Whether the current [SeekBar] value is displayed to the user
|
||||||
|
* @see .getShowSeekBarValue
|
||||||
|
*/
|
||||||
set(showSeekBarValue) {
|
set(showSeekBarValue) {
|
||||||
mShowSeekBarValue = showSeekBarValue
|
mShowSeekBarValue = showSeekBarValue
|
||||||
notifyChanged()
|
notifyChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current progress of the [SeekBar].
|
* Gets/Sets the current progress of the [SeekBar].
|
||||||
* @return The current progress of the [SeekBar]
|
|
||||||
* Sets the current progress of the [SeekBar].
|
|
||||||
* @param seekBarValue The current progress of the [SeekBar]
|
|
||||||
*/
|
*/
|
||||||
var value: Int
|
var value: Int
|
||||||
get() = mSeekBarValue
|
get() = mSeekBarValue
|
||||||
set(seekBarValue) = setValueInternal(seekBarValue, true)
|
set(seekBarValue) = setValueInternal(seekBarValue, true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
val a = context.obtainStyledAttributes(
|
val a = context.obtainStyledAttributes(
|
||||||
attrs, R.styleable.SeekBarPreference, defStyleAttr, defStyleRes
|
attrs, R.styleable.SeekBarPreference, defStyleAttr, defStyleRes
|
||||||
)
|
)
|
||||||
@ -308,7 +306,8 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
* Persist the [SeekBar]'s SeekBar value if callChangeListener returns true, otherwise
|
* Persist the [SeekBar]'s SeekBar value if callChangeListener returns true, otherwise
|
||||||
* set the [SeekBar]'s value to the stored value.
|
* set the [SeekBar]'s value to the stored value.
|
||||||
*/
|
*/
|
||||||
internal /* synthetic access */ fun syncValueInternal(seekBar: SeekBar) {
|
/* synthetic access */
|
||||||
|
internal fun syncValueInternal(seekBar: SeekBar) {
|
||||||
val seekBarValue = mMin + seekBar.progress
|
val seekBarValue = mMin + seekBar.progress
|
||||||
if (seekBarValue != mSeekBarValue) {
|
if (seekBarValue != mSeekBarValue) {
|
||||||
if (callChangeListener(seekBarValue)) {
|
if (callChangeListener(seekBarValue)) {
|
||||||
@ -324,9 +323,10 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Attempts to update the TextView label that displays the current value.
|
* Attempts to update the TextView label that displays the current value.
|
||||||
*
|
*
|
||||||
* @param value the value to display next to the [SeekBar]
|
* @param labelValue the value to display next to the [SeekBar]
|
||||||
*/
|
*/
|
||||||
internal /* synthetic access */ fun updateLabelValue(labelValue: Int) {
|
/* synthetic access */
|
||||||
|
internal fun updateLabelValue(labelValue: Int) {
|
||||||
var value = labelValue
|
var value = labelValue
|
||||||
if (mSeekBarValueTextView != null) {
|
if (mSeekBarValueTextView != null) {
|
||||||
value = value * STEP_SIZE + MIN_VALUE
|
value = value * STEP_SIZE + MIN_VALUE
|
||||||
@ -339,9 +339,9 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* Attempts to update the example TextView text with text scale size.
|
* Attempts to update the example TextView text with text scale size.
|
||||||
*
|
*
|
||||||
* @param value the value of text size
|
* @param textValue the value of text size
|
||||||
*/
|
*/
|
||||||
internal /* synthetic access */ fun updateExampleTextValue(textValue: Int) {
|
internal fun updateExampleTextValue(textValue: Int) {
|
||||||
var value = textValue
|
var value = textValue
|
||||||
if (mExampleTextTextView != null) {
|
if (mExampleTextTextView != null) {
|
||||||
value = value * STEP_SIZE + MIN_VALUE
|
value = value * STEP_SIZE + MIN_VALUE
|
||||||
|
@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
|
|
||||||
class ThemeFragment : PreferenceFragmentCompat() {
|
class ThemeFragment : PreferenceFragmentCompat() {
|
||||||
@ -60,7 +61,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindLightTheme() {
|
private fun bindLightTheme() {
|
||||||
val keyLightTheme = getString(R.string.pref_key_light_theme)
|
val keyLightTheme = getPreferenceKey(R.string.pref_key_light_theme)
|
||||||
radioLightTheme = requireNotNull(findPreference(keyLightTheme))
|
radioLightTheme = requireNotNull(findPreference(keyLightTheme))
|
||||||
radioLightTheme.onClickListener {
|
radioLightTheme.onClickListener {
|
||||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_NO)
|
setNewTheme(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
@ -70,7 +71,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
|||||||
@SuppressLint("WrongConstant")
|
@SuppressLint("WrongConstant")
|
||||||
// Suppressing erroneous lint warning about using MODE_NIGHT_AUTO_BATTERY, a likely library bug
|
// Suppressing erroneous lint warning about using MODE_NIGHT_AUTO_BATTERY, a likely library bug
|
||||||
private fun bindAutoBatteryTheme() {
|
private fun bindAutoBatteryTheme() {
|
||||||
val keyBatteryTheme = getString(R.string.pref_key_auto_battery_theme)
|
val keyBatteryTheme = getPreferenceKey(R.string.pref_key_auto_battery_theme)
|
||||||
radioAutoBatteryTheme = requireNotNull(findPreference(keyBatteryTheme))
|
radioAutoBatteryTheme = requireNotNull(findPreference(keyBatteryTheme))
|
||||||
radioAutoBatteryTheme.onClickListener {
|
radioAutoBatteryTheme.onClickListener {
|
||||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
|
setNewTheme(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
|
||||||
@ -78,7 +79,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindDarkTheme() {
|
private fun bindDarkTheme() {
|
||||||
val keyDarkTheme = getString(R.string.pref_key_dark_theme)
|
val keyDarkTheme = getPreferenceKey(R.string.pref_key_dark_theme)
|
||||||
radioDarkTheme = requireNotNull(findPreference(keyDarkTheme))
|
radioDarkTheme = requireNotNull(findPreference(keyDarkTheme))
|
||||||
radioDarkTheme.onClickListener {
|
radioDarkTheme.onClickListener {
|
||||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_YES)
|
setNewTheme(AppCompatDelegate.MODE_NIGHT_YES)
|
||||||
@ -86,7 +87,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun bindFollowDeviceTheme() {
|
private fun bindFollowDeviceTheme() {
|
||||||
val keyDeviceTheme = getString(R.string.pref_key_follow_device_theme)
|
val keyDeviceTheme = getPreferenceKey(R.string.pref_key_follow_device_theme)
|
||||||
radioFollowDeviceTheme = requireNotNull(findPreference(keyDeviceTheme))
|
radioFollowDeviceTheme = requireNotNull(findPreference(keyDeviceTheme))
|
||||||
if (SDK_INT >= Build.VERSION_CODES.P) {
|
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
radioFollowDeviceTheme.onClickListener {
|
radioFollowDeviceTheme.onClickListener {
|
||||||
|
@ -6,16 +6,27 @@ package org.mozilla.fenix.settings
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.findNavController
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
import org.mozilla.fenix.ext.requireComponents
|
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the toggle for tracking protection and a button to open
|
||||||
|
* the tracking protection [org.mozilla.fenix.exceptions.ExceptionsFragment].
|
||||||
|
*/
|
||||||
class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
private val exceptionsClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
val directions = TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
|
||||||
|
view!!.findNavController().navigate(directions)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
setPreferencesFromResource(R.xml.tracking_protection_preferences, rootKey)
|
setPreferencesFromResource(R.xml.tracking_protection_preferences, rootKey)
|
||||||
}
|
}
|
||||||
@ -26,34 +37,22 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
|||||||
(activity as AppCompatActivity).supportActionBar?.show()
|
(activity as AppCompatActivity).supportActionBar?.show()
|
||||||
|
|
||||||
// Tracking Protection Switch
|
// Tracking Protection Switch
|
||||||
val trackingProtectionKey =
|
val trackingProtectionKey = getPreferenceKey(R.string.pref_key_tracking_protection)
|
||||||
context!!.getPreferenceKey(R.string.pref_key_tracking_protection)
|
|
||||||
val preferenceTP = findPreference<SwitchPreference>(trackingProtectionKey)
|
val preferenceTP = findPreference<SwitchPreference>(trackingProtectionKey)
|
||||||
|
|
||||||
preferenceTP?.isChecked = Settings.getInstance(context!!).shouldUseTrackingProtection
|
preferenceTP?.isChecked = Settings.getInstance(context!!).shouldUseTrackingProtection
|
||||||
preferenceTP?.onPreferenceChangeListener =
|
preferenceTP?.setOnPreferenceChangeListener<Boolean> { preference, trackingProtectionOn ->
|
||||||
Preference.OnPreferenceChangeListener { _, newValue ->
|
Settings.getInstance(preference.context).shouldUseTrackingProtection = trackingProtectionOn
|
||||||
Settings.getInstance(requireContext()).shouldUseTrackingProtection = newValue as Boolean
|
with(preference.context.components) {
|
||||||
with(requireComponents) {
|
val policy = core.createTrackingProtectionPolicy(trackingProtectionOn)
|
||||||
val policy = core.createTrackingProtectionPolicy(newValue)
|
useCases.settingsUseCases.updateTrackingProtection(policy)
|
||||||
useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
|
useCases.sessionUseCases.reload()
|
||||||
useCases.sessionUseCases.reload.invoke()
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val exceptions =
|
|
||||||
context!!.getPreferenceKey(R.string.pref_key_tracking_protection_exceptions)
|
|
||||||
val preferenceExceptions = findPreference<Preference>(exceptions)
|
|
||||||
preferenceExceptions?.onPreferenceClickListener = getClickListenerForExceptions()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClickListenerForExceptions(): Preference.OnPreferenceClickListener {
|
|
||||||
return Preference.OnPreferenceClickListener {
|
|
||||||
val directions =
|
|
||||||
TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
|
|
||||||
Navigation.findNavController(view!!).navigate(directions)
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val exceptions = getPreferenceKey(R.string.pref_key_tracking_protection_exceptions)
|
||||||
|
val preferenceExceptions = findPreference<Preference>(exceptions)
|
||||||
|
preferenceExceptions?.onPreferenceClickListener = exceptionsClickListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ import android.view.ViewGroup
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.findNavController
|
||||||
import androidx.navigation.fragment.NavHostFragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.*
|
import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.*
|
||||||
import mozilla.components.concept.sync.AccountObserver
|
import mozilla.components.concept.sync.AccountObserver
|
||||||
import mozilla.components.concept.sync.OAuthAccount
|
import mozilla.components.concept.sync.OAuthAccount
|
||||||
@ -23,6 +23,22 @@ import org.mozilla.fenix.ext.requireComponents
|
|||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions")
|
@SuppressWarnings("TooManyFunctions")
|
||||||
class TurnOnSyncFragment : Fragment(), AccountObserver {
|
class TurnOnSyncFragment : Fragment(), AccountObserver {
|
||||||
|
|
||||||
|
private val signInClickListener = View.OnClickListener {
|
||||||
|
requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())
|
||||||
|
// 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.
|
||||||
|
}
|
||||||
|
|
||||||
|
private val paringClickListener = View.OnClickListener {
|
||||||
|
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairFragment()
|
||||||
|
view!!.findNavController().navigate(directions)
|
||||||
|
requireComponents.analytics.metrics.track(Event.SyncAuthScanPairing)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
requireComponents.analytics.metrics.track(Event.SyncAuthOpened)
|
requireComponents.analytics.metrics.track(Event.SyncAuthOpened)
|
||||||
@ -36,7 +52,7 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (requireComponents.backgroundServices.accountManager.authenticatedAccount() != null) {
|
if (requireComponents.backgroundServices.accountManager.authenticatedAccount() != null) {
|
||||||
findNavController(this).popBackStack()
|
findNavController().popBackStack()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +63,8 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
|||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
val view = inflater.inflate(R.layout.fragment_turn_on_sync, container, false)
|
val view = inflater.inflate(R.layout.fragment_turn_on_sync, container, false)
|
||||||
view.signInScanButton.setOnClickListener(getClickListenerForPairing())
|
view.signInScanButton.setOnClickListener(paringClickListener)
|
||||||
view.signInEmailButton.setOnClickListener(getClickListenerForSignIn())
|
view.signInEmailButton.setOnClickListener(signInClickListener)
|
||||||
view.signInInstructions.text = HtmlCompat.fromHtml(
|
view.signInInstructions.text = HtmlCompat.fromHtml(
|
||||||
getString(R.string.sign_in_instructions),
|
getString(R.string.sign_in_instructions),
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||||
@ -56,25 +72,6 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
|||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getClickListenerForSignIn(): View.OnClickListener {
|
|
||||||
return View.OnClickListener {
|
|
||||||
requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())
|
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getClickListenerForPairing(): View.OnClickListener {
|
|
||||||
return View.OnClickListener {
|
|
||||||
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairFragment()
|
|
||||||
Navigation.findNavController(view!!).navigate(directions)
|
|
||||||
requireComponents.analytics.metrics.track(Event.SyncAuthScanPairing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) {
|
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) {
|
||||||
FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_SHORT)
|
FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_SHORT)
|
||||||
.setText(requireContext().getString(R.string.sync_syncing_in_progress))
|
.setText(requireContext().getString(R.string.sync_syncing_in_progress))
|
||||||
|
@ -113,12 +113,12 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
accountManager.register(accountStateObserver, this, true)
|
accountManager.register(accountStateObserver, this, true)
|
||||||
|
|
||||||
// Sign out
|
// Sign out
|
||||||
val signOut = context!!.getPreferenceKey(R.string.pref_key_sign_out)
|
val signOut = getPreferenceKey(R.string.pref_key_sign_out)
|
||||||
val preferenceSignOut = findPreference<Preference>(signOut)
|
val preferenceSignOut = findPreference<Preference>(signOut)
|
||||||
preferenceSignOut?.onPreferenceClickListener = getClickListenerForSignOut()
|
preferenceSignOut?.onPreferenceClickListener = getClickListenerForSignOut()
|
||||||
|
|
||||||
// Sync now
|
// Sync now
|
||||||
val syncNow = context!!.getPreferenceKey(R.string.pref_key_sync_now)
|
val syncNow = getPreferenceKey(R.string.pref_key_sync_now)
|
||||||
val preferenceSyncNow = findPreference<Preference>(syncNow)
|
val preferenceSyncNow = findPreference<Preference>(syncNow)
|
||||||
preferenceSyncNow?.let {
|
preferenceSyncNow?.let {
|
||||||
it.onPreferenceClickListener = getClickListenerForSyncNow()
|
it.onPreferenceClickListener = getClickListenerForSyncNow()
|
||||||
@ -134,7 +134,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
|
|
||||||
// Device Name
|
// Device Name
|
||||||
val deviceConstellation = accountManager.authenticatedAccount()?.deviceConstellation()
|
val deviceConstellation = accountManager.authenticatedAccount()?.deviceConstellation()
|
||||||
val deviceNameKey = context!!.getPreferenceKey(R.string.pref_key_sync_device_name)
|
val deviceNameKey = getPreferenceKey(R.string.pref_key_sync_device_name)
|
||||||
findPreference<EditTextPreference>(deviceNameKey)?.apply {
|
findPreference<EditTextPreference>(deviceNameKey)?.apply {
|
||||||
onPreferenceChangeListener = getChangeListenerForDeviceName()
|
onPreferenceChangeListener = getChangeListenerForDeviceName()
|
||||||
deviceConstellation?.state()?.currentDevice?.let { device ->
|
deviceConstellation?.state()?.currentDevice?.let { device ->
|
||||||
@ -211,7 +211,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
private val syncStatusObserver = object : SyncStatusObserver {
|
private val syncStatusObserver = object : SyncStatusObserver {
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val pref = findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_now))
|
val pref = findPreference<Preference>(getPreferenceKey(R.string.pref_key_sync_now))
|
||||||
view?.announceForAccessibility(getString(R.string.sync_syncing_in_progress))
|
view?.announceForAccessibility(getString(R.string.sync_syncing_in_progress))
|
||||||
pref?.title = getString(R.string.sync_syncing_in_progress)
|
pref?.title = getString(R.string.sync_syncing_in_progress)
|
||||||
pref?.isEnabled = false
|
pref?.isEnabled = false
|
||||||
@ -221,7 +221,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
// Sync stopped successfully.
|
// Sync stopped successfully.
|
||||||
override fun onIdle() {
|
override fun onIdle() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val pref = findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_now))
|
val pref = findPreference<Preference>(getPreferenceKey(R.string.pref_key_sync_now))
|
||||||
pref?.let {
|
pref?.let {
|
||||||
pref.title = getString(R.string.preferences_sync_now)
|
pref.title = getString(R.string.preferences_sync_now)
|
||||||
pref.isEnabled = true
|
pref.isEnabled = true
|
||||||
@ -235,7 +235,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
// Sync stopped after encountering a problem.
|
// Sync stopped after encountering a problem.
|
||||||
override fun onError(error: Exception?) {
|
override fun onError(error: Exception?) {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val pref = findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_now))
|
val pref = findPreference<Preference>(getPreferenceKey(R.string.pref_key_sync_now))
|
||||||
pref?.let {
|
pref?.let {
|
||||||
pref.title = getString(R.string.preferences_sync_now)
|
pref.title = getString(R.string.preferences_sync_now)
|
||||||
pref.isEnabled = true
|
pref.isEnabled = true
|
||||||
@ -256,7 +256,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateDeviceName(state: AccountSettingsState) {
|
private fun updateDeviceName(state: AccountSettingsState) {
|
||||||
val deviceNameKey = context!!.getPreferenceKey(R.string.pref_key_sync_device_name)
|
val deviceNameKey = getPreferenceKey(R.string.pref_key_sync_device_name)
|
||||||
val preferenceDeviceName = findPreference<Preference>(deviceNameKey)
|
val preferenceDeviceName = findPreference<Preference>(deviceNameKey)
|
||||||
preferenceDeviceName?.summary = state.deviceName
|
preferenceDeviceName?.summary = state.deviceName
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val syncNow = context!!.getPreferenceKey(R.string.pref_key_sync_now)
|
val syncNow = getPreferenceKey(R.string.pref_key_sync_now)
|
||||||
findPreference<Preference>(syncNow)?.summary = value
|
findPreference<Preference>(syncNow)?.summary = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,10 +48,10 @@ class QuickSettingsComponent(
|
|||||||
return if (sitePermissions == null) {
|
return if (sitePermissions == null) {
|
||||||
val settings = Settings.getInstance(context)
|
val settings = Settings.getInstance(context)
|
||||||
val origin = requireNotNull(url.toUri().host)
|
val origin = requireNotNull(url.toUri().host)
|
||||||
var location = settings.sitePermissionsPhoneFeatureLocation.toStatus()
|
var location = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION).toStatus()
|
||||||
var camera = settings.sitePermissionsPhoneFeatureCameraAction.toStatus()
|
var camera = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA).toStatus()
|
||||||
var microphone = settings.sitePermissionsPhoneFeatureMicrophoneAction.toStatus()
|
var microphone = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE).toStatus()
|
||||||
var notification = settings.sitePermissionsPhoneFeatureNotificationAction.toStatus()
|
var notification = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION).toStatus()
|
||||||
|
|
||||||
when (featurePhone) {
|
when (featurePhone) {
|
||||||
PhoneFeature.CAMERA -> camera = camera.toggle()
|
PhoneFeature.CAMERA -> camera = camera.toggle()
|
||||||
|
@ -1,45 +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.settings.sharedpreferences
|
|
||||||
|
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
|
||||||
import java.security.InvalidParameterException
|
|
||||||
import kotlin.properties.ReadWriteProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
private class SitePermissionsRulesActionPreference(
|
|
||||||
private val key: String
|
|
||||||
) : ReadWriteProperty<PreferencesHolder, SitePermissionsRules.Action> {
|
|
||||||
|
|
||||||
override fun getValue(thisRef: PreferencesHolder, property: KProperty<*>): SitePermissionsRules.Action =
|
|
||||||
intToAction(thisRef.preferences.getInt(key, ASK_TO_ALLOW_INT))
|
|
||||||
|
|
||||||
override fun setValue(thisRef: PreferencesHolder, property: KProperty<*>, value: SitePermissionsRules.Action) {
|
|
||||||
thisRef.preferences.edit().putInt(key, actionToInt(value)).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val BLOCKED_INT = 0
|
|
||||||
private const val ASK_TO_ALLOW_INT = 1
|
|
||||||
|
|
||||||
private fun actionToInt(action: SitePermissionsRules.Action) = when (action) {
|
|
||||||
SitePermissionsRules.Action.BLOCKED -> BLOCKED_INT
|
|
||||||
SitePermissionsRules.Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun intToAction(action: Int) = when (action) {
|
|
||||||
BLOCKED_INT -> SitePermissionsRules.Action.BLOCKED
|
|
||||||
ASK_TO_ALLOW_INT -> SitePermissionsRules.Action.ASK_TO_ALLOW
|
|
||||||
else -> throw InvalidParameterException("$action is not a valid SitePermissionsRules.Action")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Property delegate for getting and setting a [SitePermissionsRules.Action] preference.
|
|
||||||
*/
|
|
||||||
fun sitePermissionsRulesActionPreference(
|
|
||||||
key: String
|
|
||||||
): ReadWriteProperty<PreferencesHolder, SitePermissionsRules.Action> = SitePermissionsRulesActionPreference(key)
|
|
@ -14,9 +14,10 @@ import org.mozilla.fenix.BuildConfig
|
|||||||
import org.mozilla.fenix.Config
|
import org.mozilla.fenix.Config
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
|
import org.mozilla.fenix.settings.PhoneFeature
|
||||||
import org.mozilla.fenix.settings.sharedpreferences.PreferencesHolder
|
import org.mozilla.fenix.settings.sharedpreferences.PreferencesHolder
|
||||||
import org.mozilla.fenix.settings.sharedpreferences.booleanPreference
|
import org.mozilla.fenix.settings.sharedpreferences.booleanPreference
|
||||||
import org.mozilla.fenix.settings.sharedpreferences.sitePermissionsRulesActionPreference
|
import java.security.InvalidParameterException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple wrapper for SharedPreferences that makes reading preference a little bit easier.
|
* A simple wrapper for SharedPreferences that makes reading preference a little bit easier.
|
||||||
@ -29,6 +30,19 @@ class Settings private constructor(
|
|||||||
companion object {
|
companion object {
|
||||||
const val autoBounceMaximumCount = 2
|
const val autoBounceMaximumCount = 2
|
||||||
const val FENIX_PREFERENCES = "fenix_preferences"
|
const val FENIX_PREFERENCES = "fenix_preferences"
|
||||||
|
private const val BLOCKED_INT = 0
|
||||||
|
private const val ASK_TO_ALLOW_INT = 1
|
||||||
|
|
||||||
|
private fun actionToInt(action: SitePermissionsRules.Action) = when (action) {
|
||||||
|
SitePermissionsRules.Action.BLOCKED -> BLOCKED_INT
|
||||||
|
SitePermissionsRules.Action.ASK_TO_ALLOW -> ASK_TO_ALLOW_INT
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun intToAction(action: Int) = when (action) {
|
||||||
|
BLOCKED_INT -> SitePermissionsRules.Action.BLOCKED
|
||||||
|
ASK_TO_ALLOW_INT -> SitePermissionsRules.Action.ASK_TO_ALLOW
|
||||||
|
else -> throw InvalidParameterException("$action is not a valid SitePermissionsRules.Action")
|
||||||
|
}
|
||||||
|
|
||||||
var instance: Settings? = null
|
var instance: Settings? = null
|
||||||
|
|
||||||
@ -147,28 +161,19 @@ class Settings private constructor(
|
|||||||
default = true
|
default = true
|
||||||
)
|
)
|
||||||
|
|
||||||
var sitePermissionsPhoneFeatureCameraAction by sitePermissionsRulesActionPreference(
|
fun getSitePermissionsPhoneFeatureAction(feature: PhoneFeature) =
|
||||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera)
|
intToAction(preferences.getInt(feature.getPreferenceKey(appContext), ASK_TO_ALLOW_INT))
|
||||||
)
|
|
||||||
|
|
||||||
var sitePermissionsPhoneFeatureMicrophoneAction by sitePermissionsRulesActionPreference(
|
fun setSitePermissionsPhoneFeatureAction(feature: PhoneFeature, value: SitePermissionsRules.Action) {
|
||||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone)
|
preferences.edit().putInt(feature.getPreferenceKey(appContext), actionToInt(value)).apply()
|
||||||
)
|
}
|
||||||
|
|
||||||
var sitePermissionsPhoneFeatureNotificationAction by sitePermissionsRulesActionPreference(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_notification)
|
|
||||||
)
|
|
||||||
|
|
||||||
var sitePermissionsPhoneFeatureLocation by sitePermissionsRulesActionPreference(
|
|
||||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_location)
|
|
||||||
)
|
|
||||||
|
|
||||||
fun getSitePermissionsCustomSettingsRules(): SitePermissionsRules {
|
fun getSitePermissionsCustomSettingsRules(): SitePermissionsRules {
|
||||||
return SitePermissionsRules(
|
return SitePermissionsRules(
|
||||||
notification = sitePermissionsPhoneFeatureNotificationAction,
|
notification = getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION),
|
||||||
microphone = sitePermissionsPhoneFeatureMicrophoneAction,
|
microphone = getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE),
|
||||||
location = sitePermissionsPhoneFeatureLocation,
|
location = getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION),
|
||||||
camera = sitePermissionsPhoneFeatureCameraAction
|
camera = getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
<!-- 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
|
- 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/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.core.widget.NestedScrollView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:fillViewport="true">
|
android:fillViewport="true">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
@ -45,7 +47,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/sign_in_instructions"
|
tools:text="@string/sign_in_instructions"
|
||||||
android:textColor="?primaryText"
|
android:textColor="?primaryText"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
@ -84,4 +86,4 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/signInScanButton" />
|
app:layout_constraintTop_toBottomOf="@id/signInScanButton" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
@ -1,73 +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.settings.sharedpreferences
|
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import io.mockk.every
|
|
||||||
import io.mockk.just
|
|
||||||
import io.mockk.mockk
|
|
||||||
import io.mockk.runs
|
|
||||||
import io.mockk.verify
|
|
||||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class SitePermissionsRulesActionPreferenceTest {
|
|
||||||
|
|
||||||
private lateinit var sharedPrefs: SharedPreferences
|
|
||||||
private lateinit var editor: SharedPreferences.Editor
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
sharedPrefs = mockk(relaxed = true)
|
|
||||||
editor = mockk()
|
|
||||||
|
|
||||||
every { sharedPrefs.edit() } returns editor
|
|
||||||
every { editor.putInt(any(), any()) } returns editor
|
|
||||||
every { editor.apply() } just runs
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `getter returns action from shared preferences`() {
|
|
||||||
val holder = object : PreferencesHolder {
|
|
||||||
override val preferences = sharedPrefs
|
|
||||||
val test by sitePermissionsRulesActionPreference("test_preference_key")
|
|
||||||
}
|
|
||||||
every { sharedPrefs.getInt("test_preference_key", 1) } returns 0
|
|
||||||
|
|
||||||
assertEquals(SitePermissionsRules.Action.BLOCKED, holder.test)
|
|
||||||
verify { sharedPrefs.getInt("test_preference_key", 1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `setter applies boolean to shared preferences`() {
|
|
||||||
val holder = object : PreferencesHolder {
|
|
||||||
override val preferences = sharedPrefs
|
|
||||||
var test by sitePermissionsRulesActionPreference("pref")
|
|
||||||
}
|
|
||||||
holder.test = SitePermissionsRules.Action.BLOCKED
|
|
||||||
|
|
||||||
verify { editor.putInt("pref", 0) }
|
|
||||||
verify { editor.apply() }
|
|
||||||
|
|
||||||
holder.test = SitePermissionsRules.Action.ASK_TO_ALLOW
|
|
||||||
|
|
||||||
verify { editor.putInt("pref", 1) }
|
|
||||||
verify { editor.apply() }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `getter defaults to ASK_TO_ALLOW`() {
|
|
||||||
every { sharedPrefs.getInt("key", 1) } returns 1
|
|
||||||
val holder = object : PreferencesHolder {
|
|
||||||
override val preferences = sharedPrefs
|
|
||||||
val action by sitePermissionsRulesActionPreference("key")
|
|
||||||
}
|
|
||||||
|
|
||||||
assertEquals(SitePermissionsRules.Action.ASK_TO_ALLOW, holder.action)
|
|
||||||
verify { sharedPrefs.getInt("key", 1) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,6 +18,7 @@ import org.junit.Test
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mozilla.fenix.TestApplication
|
import org.mozilla.fenix.TestApplication
|
||||||
import org.mozilla.fenix.ext.clearAndCommit
|
import org.mozilla.fenix.ext.clearAndCommit
|
||||||
|
import org.mozilla.fenix.settings.PhoneFeature
|
||||||
import org.robolectric.annotation.Config
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
@ObsoleteCoroutinesApi
|
@ObsoleteCoroutinesApi
|
||||||
@ -231,52 +232,52 @@ class SettingsTest {
|
|||||||
fun sitePermissionsPhoneFeatureCameraAction() {
|
fun sitePermissionsPhoneFeatureCameraAction() {
|
||||||
// When just created
|
// When just created
|
||||||
// Then
|
// Then
|
||||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureCameraAction)
|
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA))
|
||||||
|
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureCameraAction)
|
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun sitePermissionsPhoneFeatureMicrophoneAction() {
|
fun sitePermissionsPhoneFeatureMicrophoneAction() {
|
||||||
// When just created
|
// When just created
|
||||||
// Then
|
// Then
|
||||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureMicrophoneAction)
|
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE))
|
||||||
|
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureMicrophoneAction)
|
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun sitePermissionsPhoneFeatureNotificationAction() {
|
fun sitePermissionsPhoneFeatureNotificationAction() {
|
||||||
// When just created
|
// When just created
|
||||||
// Then
|
// Then
|
||||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureNotificationAction)
|
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION))
|
||||||
|
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureNotificationAction)
|
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun sitePermissionsPhoneFeatureLocation() {
|
fun sitePermissionsPhoneFeatureLocation() {
|
||||||
// When just created
|
// When just created
|
||||||
// Then
|
// Then
|
||||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureLocation)
|
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION))
|
||||||
|
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureLocation = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureLocation)
|
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -292,7 +293,7 @@ class SettingsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun getSitePermissionsCustomSettingsRules_camera() {
|
fun getSitePermissionsCustomSettingsRules_camera() {
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -304,7 +305,7 @@ class SettingsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun getSitePermissionsCustomSettingsRules_notification() {
|
fun getSitePermissionsCustomSettingsRules_notification() {
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -316,7 +317,7 @@ class SettingsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun getSitePermissionsCustomSettingsRules_location() {
|
fun getSitePermissionsCustomSettingsRules_location() {
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureLocation = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(
|
assertEquals(
|
||||||
@ -328,7 +329,7 @@ class SettingsTest {
|
|||||||
@Test
|
@Test
|
||||||
fun getSitePermissionsCustomSettingsRules_microphone() {
|
fun getSitePermissionsCustomSettingsRules_microphone() {
|
||||||
// When
|
// When
|
||||||
settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED
|
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE, BLOCKED)
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
Loading…
Reference in New Issue
Block a user