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
|
||||
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.NavDirections
|
||||
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) {
|
||||
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.geckoview.BuildConfig as GeckoViewBuildConfig
|
||||
|
||||
/**
|
||||
* Displays the logo and information about the app, including library versions.
|
||||
*/
|
||||
class AboutFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
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?) {
|
||||
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 buildDate = BuildConfig.BUILD_DATE
|
||||
|
||||
about_text.text = aboutText
|
||||
about_content.text = content
|
||||
@ -62,12 +68,7 @@ class AboutFragment : Fragment() {
|
||||
|
||||
view_licenses_button.setOnClickListener {
|
||||
startActivity(Intent(context, OssLicensesMenuActivity::class.java))
|
||||
OssLicensesMenuActivity.setActivityTitle(
|
||||
getString(
|
||||
R.string.open_source_licenses_title,
|
||||
getString(R.string.app_name)
|
||||
)
|
||||
)
|
||||
OssLicensesMenuActivity.setActivityTitle(getString(R.string.open_source_licenses_title, appName))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,44 +6,64 @@ package org.mozilla.fenix.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
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
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(activity as AppCompatActivity).title = getString(R.string.preferences_accessibility)
|
||||
(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
|
||||
|
||||
val useAutoSizePreference =
|
||||
findPreference<SwitchPreference>(getString(R.string.pref_key_accessibility_auto_size))
|
||||
useAutoSizePreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
Settings.getInstance(context!!).shouldUseAutoSize = newValue as Boolean
|
||||
requireComponents.core.engine.settings.automaticFontSizeAdjustment = newValue
|
||||
if (!newValue) {
|
||||
requireComponents.core.engine.settings.fontSizeFactor = Settings.getInstance(context!!).fontSizeFactor
|
||||
findPreference<SwitchPreference>(getPreferenceKey(R.string.pref_key_accessibility_auto_size))
|
||||
useAutoSizePreference?.setOnPreferenceChangeListener<Boolean> { preference, useAutoSize ->
|
||||
val settings = Settings.getInstance(preference.context)
|
||||
val components = preference.context.components
|
||||
|
||||
// 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
|
||||
requireComponents.useCases.sessionUseCases.reload.invoke()
|
||||
// Show the manual sizing controls if automatic sizing is turned off.
|
||||
textSizePreference?.isVisible = !useAutoSize
|
||||
|
||||
// Reload the current session to reflect the new text scale
|
||||
components.useCases.sessionUseCases.reload()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isGone
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import org.mozilla.fenix.R
|
||||
@ -32,10 +32,7 @@ class AccountAuthErrorPreference @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun updateEmailView(email: String?) {
|
||||
emailView?.text = email.orEmpty()
|
||||
emailView?.visibility = when (email.isNullOrEmpty()) {
|
||||
true -> View.GONE
|
||||
false -> View.VISIBLE
|
||||
}
|
||||
emailView?.text = email
|
||||
emailView?.isGone = email.isNullOrEmpty()
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isGone
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import org.mozilla.fenix.R
|
||||
@ -49,10 +49,7 @@ class AccountPreference @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private fun updateDisplayName(name: String?) {
|
||||
displayNameView?.text = name.orEmpty()
|
||||
displayNameView?.visibility = when (displayName.isNullOrEmpty()) {
|
||||
true -> View.GONE
|
||||
false -> View.VISIBLE
|
||||
}
|
||||
displayNameView?.text = name
|
||||
displayNameView?.isGone = displayName.isNullOrEmpty()
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package org.mozilla.fenix.settings
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import kotlinx.coroutines.launch
|
||||
@ -20,66 +20,60 @@ import org.mozilla.fenix.ext.requireComponents
|
||||
|
||||
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() {
|
||||
super.onResume()
|
||||
(activity as AppCompatActivity).title = getString(R.string.sync_reconnect)
|
||||
(activity as AppCompatActivity).supportActionBar?.show()
|
||||
|
||||
val accountManager = requireComponents.backgroundServices.accountManager
|
||||
|
||||
// We may have fixed our auth problem, in which case close this fragment.
|
||||
if (requireComponents.backgroundServices.accountManager.authenticatedAccount() != null &&
|
||||
!requireComponents.backgroundServices.accountManager.accountNeedsReauth()
|
||||
) {
|
||||
NavHostFragment.findNavController(this).popBackStack()
|
||||
if (accountManager.authenticatedAccount() != null && !accountManager.accountNeedsReauth()) {
|
||||
findNavController().popBackStack()
|
||||
return
|
||||
}
|
||||
|
||||
requireComponents.backgroundServices.accountManager.register(this, owner = this)
|
||||
accountManager.register(this, owner = this)
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.sync_problem, rootKey)
|
||||
|
||||
val preferenceSignIn =
|
||||
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_sign_in))
|
||||
findPreference<Preference>(getPreferenceKey(R.string.pref_key_sync_sign_in))
|
||||
val preferenceSignOut =
|
||||
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sign_out))
|
||||
preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn()
|
||||
preferenceSignOut?.onPreferenceClickListener = getClickListenerForSignOut()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
findPreference<Preference>(getPreferenceKey(R.string.pref_key_sign_out))
|
||||
preferenceSignIn?.onPreferenceClickListener = signInClickListener
|
||||
preferenceSignOut?.onPreferenceClickListener = signOutClickListener
|
||||
}
|
||||
|
||||
// We're told our auth problems have been fixed; close this fragment.
|
||||
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) {
|
||||
lifecycleScope.launch {
|
||||
NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack()
|
||||
}
|
||||
}
|
||||
override fun onAuthenticated(account: OAuthAccount, newAccount: Boolean) = closeFragment()
|
||||
|
||||
// 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 {
|
||||
NavHostFragment.findNavController(this@AccountProblemFragment).popBackStack()
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,14 +11,18 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
/**
|
||||
* Lets the user toggle telemetry on/off.
|
||||
*/
|
||||
class DataChoicesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val preferenceChangeListener =
|
||||
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||
when (key) {
|
||||
getString(R.string.pref_key_telemetry) -> {
|
||||
getPreferenceKey(R.string.pref_key_telemetry) -> {
|
||||
if (sharedPreferences.getBoolean(key, Settings.getInstance(requireContext()).isTelemetryEnabled)) {
|
||||
context?.components?.analytics?.metrics?.start()
|
||||
} else {
|
||||
@ -51,16 +55,13 @@ class DataChoicesFragment : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
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
|
||||
|
||||
val appName = context.getString(R.string.app_name)
|
||||
summary = context.getString(R.string.preferences_usage_data_description, appName)
|
||||
}
|
||||
telemetryPreference?.setOnPreferenceChangeListener { preference, newValue ->
|
||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
||||
.apply()
|
||||
true
|
||||
|
||||
onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,82 +4,22 @@
|
||||
|
||||
package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.RadioButton
|
||||
import android.widget.TextView
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.preference.Preference
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
|
||||
import org.mozilla.fenix.R
|
||||
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 {
|
||||
return when (featurePhone) {
|
||||
PhoneFeature.CAMERA -> {
|
||||
copy(
|
||||
camera = camera.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)
|
||||
PhoneFeature.CAMERA -> copy(camera = camera.toggle())
|
||||
PhoneFeature.LOCATION -> copy(location = location.toggle())
|
||||
PhoneFeature.MICROPHONE -> copy(microphone = microphone.toggle())
|
||||
PhoneFeature.NOTIFICATION -> copy(notification = notification.toggle())
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,3 +51,18 @@ fun initBlockedByAndroidView(phoneFeature: PhoneFeature, blockedByAndroidView: V
|
||||
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.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.NavHostFragment.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.android.synthetic.main.fragment_pair.*
|
||||
import mozilla.components.feature.qr.QrFeature
|
||||
import mozilla.components.support.base.feature.BackHandler
|
||||
@ -68,8 +69,7 @@ class PairFragment : Fragment(), BackHandler {
|
||||
|
||||
override fun onBackPressed(): Boolean {
|
||||
qrFeature.onBackPressed()
|
||||
findNavController(this@PairFragment)
|
||||
.popBackStack(R.id.turnOnSyncFragment, false)
|
||||
findNavController().popBackStack(R.id.turnOnSyncFragment, false)
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,12 @@ import android.Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
import android.Manifest.permission.ACCESS_FINE_LOCATION
|
||||
import android.Manifest.permission.RECORD_AUDIO
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import mozilla.components.feature.sitepermissions.SitePermissions
|
||||
import mozilla.components.feature.sitepermissions.SitePermissionsRules
|
||||
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 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 {
|
||||
val label = when (this) {
|
||||
CAMERA -> {
|
||||
sitePermissions?.camera?.toString(context) ?: settings
|
||||
?.sitePermissionsPhoneFeatureCameraAction
|
||||
?.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)
|
||||
}
|
||||
@StringRes val stringRes = when (getStatus(sitePermissions, settings)) {
|
||||
SitePermissions.Status.BLOCKED -> R.string.preference_option_phone_feature_blocked
|
||||
SitePermissions.Status.NO_DECISION -> R.string.preference_option_phone_feature_ask_to_allow
|
||||
SitePermissions.Status.ALLOWED -> R.string.preference_option_phone_feature_allowed
|
||||
}
|
||||
return requireNotNull(label)
|
||||
return context.getString(stringRes)
|
||||
}
|
||||
|
||||
fun getStatus(sitePermissions: SitePermissions? = null, settings: Settings? = null): SitePermissions.Status {
|
||||
val status = when (this) {
|
||||
CAMERA -> {
|
||||
sitePermissions?.camera ?: settings
|
||||
?.sitePermissionsPhoneFeatureCameraAction
|
||||
?.toStatus()
|
||||
}
|
||||
LOCATION -> {
|
||||
sitePermissions?.location ?: settings
|
||||
?.sitePermissionsPhoneFeatureLocation
|
||||
?.toStatus()
|
||||
}
|
||||
MICROPHONE -> {
|
||||
sitePermissions?.microphone ?: settings
|
||||
?.sitePermissionsPhoneFeatureMicrophoneAction
|
||||
?.toStatus()
|
||||
}
|
||||
NOTIFICATION -> {
|
||||
sitePermissions?.notification ?: settings
|
||||
?.sitePermissionsPhoneFeatureNotificationAction
|
||||
?.toStatus()
|
||||
}
|
||||
}
|
||||
val status = getStatus(sitePermissions) ?: settings?.let(::getAction)?.toStatus()
|
||||
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 {
|
||||
fun findFeatureBy(permissions: Array<out String>): PhoneFeature? {
|
||||
return PhoneFeature.values().find { feature ->
|
||||
|
@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class SearchEngineFragment : PreferenceFragmentCompat() {
|
||||
@ -23,25 +24,17 @@ class SearchEngineFragment : PreferenceFragmentCompat() {
|
||||
(activity as AppCompatActivity).supportActionBar?.show()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
searchSuggestionsPreference?.setOnPreferenceChangeListener { preference, newValue ->
|
||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
||||
.apply()
|
||||
true
|
||||
}
|
||||
searchSuggestionsPreference?.onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
showVisitedSitesBookmarks?.setOnPreferenceChangeListener { preference, newValue ->
|
||||
Settings.getInstance(preference.context).preferences.edit().putBoolean(preference.key, newValue as Boolean)
|
||||
.apply()
|
||||
true
|
||||
}
|
||||
showVisitedSitesBookmarks?.onPreferenceChangeListener = SharedPreferenceUpdater()
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -106,17 +106,17 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||
(activity as AppCompatActivity).title = getString(R.string.settings_title)
|
||||
(activity as AppCompatActivity).supportActionBar?.show()
|
||||
val defaultBrowserPreference =
|
||||
findPreference<DefaultBrowserPreference>(getString(R.string.pref_key_make_default_browser))
|
||||
findPreference<DefaultBrowserPreference>(getPreferenceKey(R.string.pref_key_make_default_browser))
|
||||
defaultBrowserPreference?.updateSwitch()
|
||||
|
||||
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 {
|
||||
requireComponents.search.searchEngineManager.getDefaultSearchEngine(it).name
|
||||
}
|
||||
|
||||
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 {
|
||||
if (org.mozilla.fenix.utils.Settings.getInstance(it).shouldUseTrackingProtection) {
|
||||
getString(R.string.tracking_protection_on)
|
||||
@ -126,12 +126,12 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||
}
|
||||
|
||||
val themesPreference =
|
||||
findPreference<Preference>(getString(R.string.pref_key_theme))
|
||||
findPreference<Preference>(getPreferenceKey(R.string.pref_key_theme))
|
||||
themesPreference?.summary = context?.let {
|
||||
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)
|
||||
aboutPreference?.title = getString(R.string.preferences_about, appName)
|
||||
|
||||
@ -198,16 +198,16 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||
navigateToThemeSettings()
|
||||
}
|
||||
resources.getString(pref_key_privacy_link) -> {
|
||||
requireContext().apply {
|
||||
val intent = SupportUtils.createCustomTabIntent(this, SupportUtils.PRIVACY_NOTICE_URL)
|
||||
requireContext().let { context ->
|
||||
val intent = SupportUtils.createCustomTabIntent(context, SupportUtils.PRIVACY_NOTICE_URL)
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
resources.getString(pref_key_your_rights) -> {
|
||||
requireContext().apply {
|
||||
requireContext().let { context ->
|
||||
val intent = SupportUtils.createCustomTabIntent(
|
||||
this,
|
||||
SupportUtils.getSumoURLForTopic(context!!, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
||||
context,
|
||||
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
||||
)
|
||||
startActivity(intent)
|
||||
}
|
||||
@ -229,9 +229,9 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver {
|
||||
}
|
||||
|
||||
private fun setupPreferences() {
|
||||
val makeDefaultBrowserKey = context!!.getPreferenceKey(pref_key_make_default_browser)
|
||||
val leakKey = context!!.getPreferenceKey(pref_key_leakcanary)
|
||||
val debuggingKey = context!!.getPreferenceKey(pref_key_remote_debugging)
|
||||
val makeDefaultBrowserKey = getPreferenceKey(pref_key_make_default_browser)
|
||||
val leakKey = getPreferenceKey(pref_key_leakcanary)
|
||||
val debuggingKey = getPreferenceKey(pref_key_remote_debugging)
|
||||
|
||||
val preferenceMakeDefaultBrowser = findPreference<Preference>(makeDefaultBrowserKey)
|
||||
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.mozilla.fenix.R
|
||||
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.LOCATION
|
||||
import org.mozilla.fenix.settings.PhoneFeature.MICROPHONE
|
||||
@ -83,7 +84,7 @@ class SitePermissionsDetailsExceptionsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
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))
|
||||
|
||||
button.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
|
@ -11,10 +11,7 @@ import androidx.preference.Preference
|
||||
import androidx.preference.Preference.OnPreferenceClickListener
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.settings.PhoneFeature.CAMERA
|
||||
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.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
@ -36,13 +33,12 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
private fun setupPreferences() {
|
||||
|
||||
bindCategoryPhoneFeatures()
|
||||
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))
|
||||
|
||||
exceptionsCategory.onPreferenceClickListener = OnPreferenceClickListener {
|
||||
@ -53,33 +49,17 @@ class SitePermissionsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
private fun bindCategoryPhoneFeatures() {
|
||||
val settings = Settings.getInstance(requireContext())
|
||||
|
||||
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)
|
||||
PhoneFeature.values().forEach(::initPhoneFeature)
|
||||
}
|
||||
|
||||
private fun initPhoneFeature(phoneFeature: PhoneFeature, summary: String) {
|
||||
val keyPreference = phoneFeature.getPreferenceKey(requireContext())
|
||||
val cameraPhoneFeatures: Preference = requireNotNull(findPreference(keyPreference))
|
||||
private fun initPhoneFeature(phoneFeature: PhoneFeature) {
|
||||
val context = requireContext()
|
||||
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.onPreferenceClickListener = OnPreferenceClickListener {
|
||||
|
@ -92,7 +92,7 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun RadioButton.restoreState(action: SitePermissionsRules.Action) {
|
||||
if (phoneFeature.action == action) {
|
||||
if (phoneFeature.getAction(settings) == action) {
|
||||
this.isChecked = true
|
||||
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) {
|
||||
val button = rootView.findViewById<Button>(R.id.settings_button)
|
||||
button.setOnClickListener {
|
||||
@ -144,11 +134,6 @@ class SitePermissionsManagePhoneFeatureFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun saveActionInSettings(action: SitePermissionsRules.Action) {
|
||||
when (phoneFeature) {
|
||||
PhoneFeature.CAMERA -> settings.sitePermissionsPhoneFeatureCameraAction = action
|
||||
PhoneFeature.LOCATION -> settings.sitePermissionsPhoneFeatureLocation = action
|
||||
PhoneFeature.MICROPHONE -> settings.sitePermissionsPhoneFeatureMicrophoneAction = action
|
||||
PhoneFeature.NOTIFICATION -> settings.sitePermissionsPhoneFeatureNotificationAction = action
|
||||
}
|
||||
settings.setSitePermissionsPhoneFeatureAction(phoneFeature, action)
|
||||
}
|
||||
}
|
||||
|
@ -39,23 +39,19 @@ import org.mozilla.fenix.R
|
||||
import java.text.NumberFormat
|
||||
|
||||
/**
|
||||
* 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].
|
||||
* 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].
|
||||
* The actual preference layout is customizable by setting `android:layout` on the
|
||||
* preference widget layout or `seekBarPreferenceStyle` 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.
|
||||
* Otherwise, it skips those keys.
|
||||
*
|
||||
*
|
||||
* The [SeekBar] value view can be shown or disabled by setting `showSeekBarValue`
|
||||
* 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.
|
||||
*/
|
||||
class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
@ -64,21 +60,32 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
defStyleAttr: Int = R.attr.seekBarPreferenceStyle,
|
||||
defStyleRes: Int = 0
|
||||
) : Preference(context, attrs, defStyleAttr, defStyleRes) {
|
||||
internal /* synthetic access */ var mSeekBarValue: Int = 0
|
||||
internal /* synthetic access */ var mMin: Int = 0
|
||||
/* synthetic access */
|
||||
internal var mSeekBarValue: Int = 0
|
||||
/* synthetic access */
|
||||
internal var mMin: Int = 0
|
||||
private var mMax: Int = 0
|
||||
private var mSeekBarIncrement: Int = 0
|
||||
internal /* synthetic access */ var mTrackingTouch: Boolean = false
|
||||
internal /* synthetic access */ var mSeekBar: SeekBar? = null
|
||||
/* synthetic access */
|
||||
internal var mTrackingTouch: Boolean = false
|
||||
/* synthetic access */
|
||||
internal var mSeekBar: SeekBar? = null
|
||||
private var mSeekBarValueTextView: TextView? = null
|
||||
private var mExampleTextTextView: TextView? = null
|
||||
// Whether the SeekBar should respond to the left/right keys
|
||||
/* synthetic access */ var isAdjustable: Boolean = false
|
||||
// Whether to show the SeekBar value TextView next to the bar
|
||||
/**
|
||||
* Whether the SeekBar should respond to the left/right keys
|
||||
*/
|
||||
/* synthetic access */
|
||||
var isAdjustable: Boolean = false
|
||||
/**
|
||||
* Whether to show the SeekBar value TextView next to the bar
|
||||
*/
|
||||
private var mShowSeekBarValue: Boolean = false
|
||||
// Whether the SeekBarPreference should continuously save the Seekbar value while it is being
|
||||
// dragged.
|
||||
/* synthetic access */ var updatesContinuously: Boolean = false
|
||||
/**
|
||||
* Whether the SeekBarPreference should continuously save the Seekbar value while it is being dragged.
|
||||
*/
|
||||
/* synthetic access */
|
||||
var updatesContinuously: Boolean = false
|
||||
/**
|
||||
* Listener reacting to the [SeekBar] changing value by the user
|
||||
*/
|
||||
@ -111,26 +118,21 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
* to be handled accordingly.
|
||||
*/
|
||||
private val mSeekBarKeyListener = View.OnKeyListener { _, keyCode, event ->
|
||||
if (event.action != KeyEvent.ACTION_DOWN) {
|
||||
return@OnKeyListener false
|
||||
}
|
||||
|
||||
if (!isAdjustable && (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)) {
|
||||
return@OnKeyListener if (event.action != KeyEvent.ACTION_DOWN) {
|
||||
false
|
||||
} else 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.
|
||||
return@OnKeyListener false
|
||||
}
|
||||
|
||||
// We don't want to propagate the click keys down to the SeekBar view since it will
|
||||
// create the ripple effect for the thumb.
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
return@OnKeyListener false
|
||||
}
|
||||
|
||||
if (mSeekBar == null) {
|
||||
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
|
||||
// create the ripple effect for the thumb.
|
||||
false
|
||||
} else if (mSeekBar == null) {
|
||||
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].
|
||||
* @return The amount of increment on the [SeekBar] performed after each user's arrow
|
||||
* 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
|
||||
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) {
|
||||
if (seekBarIncrement != mSeekBarIncrement) {
|
||||
mSeekBarIncrement = Math.min(mMax - mMin, Math.abs(seekBarIncrement))
|
||||
@ -173,10 +176,7 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets 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
|
||||
* Gets/Sets the upper bound set on the [SeekBar].
|
||||
*/
|
||||
var max: Int
|
||||
get() = mMax
|
||||
@ -195,29 +195,27 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
* Gets whether the current [SeekBar] value is displayed to the user.
|
||||
* @return Whether the current [SeekBar] value is displayed to the user
|
||||
* @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
|
||||
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) {
|
||||
mShowSeekBarValue = showSeekBarValue
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets 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]
|
||||
* Gets/Sets the current progress of the [SeekBar].
|
||||
*/
|
||||
var value: Int
|
||||
get() = mSeekBarValue
|
||||
set(seekBarValue) = setValueInternal(seekBarValue, true)
|
||||
|
||||
init {
|
||||
|
||||
val a = context.obtainStyledAttributes(
|
||||
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
|
||||
* 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
|
||||
if (seekBarValue != mSeekBarValue) {
|
||||
if (callChangeListener(seekBarValue)) {
|
||||
@ -324,9 +323,10 @@ class TextPercentageSeekBarPreference @JvmOverloads constructor(
|
||||
/**
|
||||
* 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
|
||||
if (mSeekBarValueTextView != null) {
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
if (mExampleTextTextView != null) {
|
||||
value = value * STEP_SIZE + MIN_VALUE
|
||||
|
@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
|
||||
class ThemeFragment : PreferenceFragmentCompat() {
|
||||
@ -60,7 +61,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
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.onClickListener {
|
||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_NO)
|
||||
@ -70,7 +71,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
||||
@SuppressLint("WrongConstant")
|
||||
// Suppressing erroneous lint warning about using MODE_NIGHT_AUTO_BATTERY, a likely library bug
|
||||
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.onClickListener {
|
||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
|
||||
@ -78,7 +79,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
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.onClickListener {
|
||||
setNewTheme(AppCompatDelegate.MODE_NIGHT_YES)
|
||||
@ -86,7 +87,7 @@ class ThemeFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
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))
|
||||
if (SDK_INT >= Build.VERSION_CODES.P) {
|
||||
radioFollowDeviceTheme.onClickListener {
|
||||
|
@ -6,16 +6,27 @@ package org.mozilla.fenix.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreference
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
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() {
|
||||
|
||||
private val exceptionsClickListener = Preference.OnPreferenceClickListener {
|
||||
val directions = TrackingProtectionFragmentDirections.actionTrackingProtectionFragmentToExceptionsFragment()
|
||||
view!!.findNavController().navigate(directions)
|
||||
true
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.tracking_protection_preferences, rootKey)
|
||||
}
|
||||
@ -26,34 +37,22 @@ class TrackingProtectionFragment : PreferenceFragmentCompat() {
|
||||
(activity as AppCompatActivity).supportActionBar?.show()
|
||||
|
||||
// Tracking Protection Switch
|
||||
val trackingProtectionKey =
|
||||
context!!.getPreferenceKey(R.string.pref_key_tracking_protection)
|
||||
val trackingProtectionKey = getPreferenceKey(R.string.pref_key_tracking_protection)
|
||||
val preferenceTP = findPreference<SwitchPreference>(trackingProtectionKey)
|
||||
|
||||
preferenceTP?.isChecked = Settings.getInstance(context!!).shouldUseTrackingProtection
|
||||
preferenceTP?.onPreferenceChangeListener =
|
||||
Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
Settings.getInstance(requireContext()).shouldUseTrackingProtection = newValue as Boolean
|
||||
with(requireComponents) {
|
||||
val policy = core.createTrackingProtectionPolicy(newValue)
|
||||
useCases.settingsUseCases.updateTrackingProtection.invoke(policy)
|
||||
useCases.sessionUseCases.reload.invoke()
|
||||
}
|
||||
true
|
||||
preferenceTP?.setOnPreferenceChangeListener<Boolean> { preference, trackingProtectionOn ->
|
||||
Settings.getInstance(preference.context).shouldUseTrackingProtection = trackingProtectionOn
|
||||
with(preference.context.components) {
|
||||
val policy = core.createTrackingProtectionPolicy(trackingProtectionOn)
|
||||
useCases.settingsUseCases.updateTrackingProtection(policy)
|
||||
useCases.sessionUseCases.reload()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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.core.text.HtmlCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.NavHostFragment.findNavController
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.*
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
@ -23,6 +23,22 @@ import org.mozilla.fenix.ext.requireComponents
|
||||
|
||||
@SuppressWarnings("TooManyFunctions")
|
||||
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?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
requireComponents.analytics.metrics.track(Event.SyncAuthOpened)
|
||||
@ -36,7 +52,7 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (requireComponents.backgroundServices.accountManager.authenticatedAccount() != null) {
|
||||
findNavController(this).popBackStack()
|
||||
findNavController().popBackStack()
|
||||
return
|
||||
}
|
||||
|
||||
@ -47,8 +63,8 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_turn_on_sync, container, false)
|
||||
view.signInScanButton.setOnClickListener(getClickListenerForPairing())
|
||||
view.signInEmailButton.setOnClickListener(getClickListenerForSignIn())
|
||||
view.signInScanButton.setOnClickListener(paringClickListener)
|
||||
view.signInEmailButton.setOnClickListener(signInClickListener)
|
||||
view.signInInstructions.text = HtmlCompat.fromHtml(
|
||||
getString(R.string.sign_in_instructions),
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||
@ -56,25 +72,6 @@ class TurnOnSyncFragment : Fragment(), AccountObserver {
|
||||
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) {
|
||||
FenixSnackbar.make(view!!, FenixSnackbar.LENGTH_SHORT)
|
||||
.setText(requireContext().getString(R.string.sync_syncing_in_progress))
|
||||
|
@ -113,12 +113,12 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
accountManager.register(accountStateObserver, this, true)
|
||||
|
||||
// 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)
|
||||
preferenceSignOut?.onPreferenceClickListener = getClickListenerForSignOut()
|
||||
|
||||
// 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)
|
||||
preferenceSyncNow?.let {
|
||||
it.onPreferenceClickListener = getClickListenerForSyncNow()
|
||||
@ -134,7 +134,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
// Device Name
|
||||
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 {
|
||||
onPreferenceChangeListener = getChangeListenerForDeviceName()
|
||||
deviceConstellation?.state()?.currentDevice?.let { device ->
|
||||
@ -211,7 +211,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
private val syncStatusObserver = object : SyncStatusObserver {
|
||||
override fun onStarted() {
|
||||
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))
|
||||
pref?.title = getString(R.string.sync_syncing_in_progress)
|
||||
pref?.isEnabled = false
|
||||
@ -221,7 +221,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
// Sync stopped successfully.
|
||||
override fun onIdle() {
|
||||
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.title = getString(R.string.preferences_sync_now)
|
||||
pref.isEnabled = true
|
||||
@ -235,7 +235,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
// Sync stopped after encountering a problem.
|
||||
override fun onError(error: Exception?) {
|
||||
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.title = getString(R.string.preferences_sync_now)
|
||||
pref.isEnabled = true
|
||||
@ -256,7 +256,7 @@ class AccountSettingsFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,10 @@ class QuickSettingsComponent(
|
||||
return if (sitePermissions == null) {
|
||||
val settings = Settings.getInstance(context)
|
||||
val origin = requireNotNull(url.toUri().host)
|
||||
var location = settings.sitePermissionsPhoneFeatureLocation.toStatus()
|
||||
var camera = settings.sitePermissionsPhoneFeatureCameraAction.toStatus()
|
||||
var microphone = settings.sitePermissionsPhoneFeatureMicrophoneAction.toStatus()
|
||||
var notification = settings.sitePermissionsPhoneFeatureNotificationAction.toStatus()
|
||||
var location = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION).toStatus()
|
||||
var camera = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA).toStatus()
|
||||
var microphone = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE).toStatus()
|
||||
var notification = settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION).toStatus()
|
||||
|
||||
when (featurePhone) {
|
||||
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.R
|
||||
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.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.
|
||||
@ -29,6 +30,19 @@ class Settings private constructor(
|
||||
companion object {
|
||||
const val autoBounceMaximumCount = 2
|
||||
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
|
||||
|
||||
@ -147,28 +161,19 @@ class Settings private constructor(
|
||||
default = true
|
||||
)
|
||||
|
||||
var sitePermissionsPhoneFeatureCameraAction by sitePermissionsRulesActionPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_camera)
|
||||
)
|
||||
fun getSitePermissionsPhoneFeatureAction(feature: PhoneFeature) =
|
||||
intToAction(preferences.getInt(feature.getPreferenceKey(appContext), ASK_TO_ALLOW_INT))
|
||||
|
||||
var sitePermissionsPhoneFeatureMicrophoneAction by sitePermissionsRulesActionPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_phone_feature_microphone)
|
||||
)
|
||||
|
||||
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 setSitePermissionsPhoneFeatureAction(feature: PhoneFeature, value: SitePermissionsRules.Action) {
|
||||
preferences.edit().putInt(feature.getPreferenceKey(appContext), actionToInt(value)).apply()
|
||||
}
|
||||
|
||||
fun getSitePermissionsCustomSettingsRules(): SitePermissionsRules {
|
||||
return SitePermissionsRules(
|
||||
notification = sitePermissionsPhoneFeatureNotificationAction,
|
||||
microphone = sitePermissionsPhoneFeatureMicrophoneAction,
|
||||
location = sitePermissionsPhoneFeatureLocation,
|
||||
camera = sitePermissionsPhoneFeatureCameraAction
|
||||
notification = getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION),
|
||||
microphone = getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE),
|
||||
location = getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION),
|
||||
camera = getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,12 @@
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<androidx.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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
@ -45,7 +47,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/sign_in_instructions"
|
||||
tools:text="@string/sign_in_instructions"
|
||||
android:textColor="?primaryText"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -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.mozilla.fenix.TestApplication
|
||||
import org.mozilla.fenix.ext.clearAndCommit
|
||||
import org.mozilla.fenix.settings.PhoneFeature
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@ObsoleteCoroutinesApi
|
||||
@ -231,52 +232,52 @@ class SettingsTest {
|
||||
fun sitePermissionsPhoneFeatureCameraAction() {
|
||||
// When just created
|
||||
// Then
|
||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureCameraAction)
|
||||
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA))
|
||||
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureCameraAction)
|
||||
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sitePermissionsPhoneFeatureMicrophoneAction() {
|
||||
// When just created
|
||||
// Then
|
||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureMicrophoneAction)
|
||||
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE))
|
||||
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureMicrophoneAction)
|
||||
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sitePermissionsPhoneFeatureNotificationAction() {
|
||||
// When just created
|
||||
// Then
|
||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureNotificationAction)
|
||||
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION))
|
||||
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureNotificationAction)
|
||||
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sitePermissionsPhoneFeatureLocation() {
|
||||
// When just created
|
||||
// Then
|
||||
assertEquals(ASK_TO_ALLOW, settings.sitePermissionsPhoneFeatureLocation)
|
||||
assertEquals(ASK_TO_ALLOW, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION))
|
||||
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureLocation = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(BLOCKED, settings.sitePermissionsPhoneFeatureLocation)
|
||||
assertEquals(BLOCKED, settings.getSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -292,7 +293,7 @@ class SettingsTest {
|
||||
@Test
|
||||
fun getSitePermissionsCustomSettingsRules_camera() {
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureCameraAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.CAMERA, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
@ -304,7 +305,7 @@ class SettingsTest {
|
||||
@Test
|
||||
fun getSitePermissionsCustomSettingsRules_notification() {
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureNotificationAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.NOTIFICATION, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
@ -316,7 +317,7 @@ class SettingsTest {
|
||||
@Test
|
||||
fun getSitePermissionsCustomSettingsRules_location() {
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureLocation = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.LOCATION, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
@ -328,7 +329,7 @@ class SettingsTest {
|
||||
@Test
|
||||
fun getSitePermissionsCustomSettingsRules_microphone() {
|
||||
// When
|
||||
settings.sitePermissionsPhoneFeatureMicrophoneAction = BLOCKED
|
||||
settings.setSitePermissionsPhoneFeatureAction(PhoneFeature.MICROPHONE, BLOCKED)
|
||||
|
||||
// Then
|
||||
assertEquals(
|
||||
|
Loading…
Reference in New Issue
Block a user