Settings refactor (#1615)

* Refactor main preferences to use DSL

* Refactor account preferences to use DSL

* Use DSL in rest of the preference screens

* Preferences cleanup

* Fix preference dependencies
This commit is contained in:
Ivan Kupalov 2020-06-08 09:21:12 +02:00 committed by GitHub
parent 4188b6ea09
commit c64df0fd1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 686 additions and 637 deletions

View File

@ -43,6 +43,18 @@ public class EmojiPreference extends Preference {
private boolean updated, currentNeedsUpdate; private boolean updated, currentNeedsUpdate;
public EmojiPreference(Context context) {
super(context);
// Find out which font is currently active
this.selected = EmojiCompatFont.byId(PreferenceManager
.getDefaultSharedPreferences(context)
.getInt(FONT_PREFERENCE, 0));
// We'll use this later to determine if anything has changed
this.original = this.selected;
setSummary(selected.getDisplay(context));
}
public EmojiPreference(Context context, AttributeSet attrs) { public EmojiPreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);

View File

@ -19,21 +19,21 @@ import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import android.util.Log import android.util.Log
import android.view.View import androidx.preference.PreferenceFragmentCompat
import androidx.preference.* import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.* import com.keylesspalace.tusky.*
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.appstore.EventHub import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
import com.keylesspalace.tusky.components.instancemute.InstanceListActivity import com.keylesspalace.tusky.components.instancemute.InstanceListActivity
import com.keylesspalace.tusky.db.AccountEntity
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Account import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.*
import com.keylesspalace.tusky.util.ThemeUtils import com.keylesspalace.tusky.util.ThemeUtils
import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
@ -44,11 +44,7 @@ import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import javax.inject.Inject import javax.inject.Inject
class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
class AccountPreferencesFragment : PreferenceFragmentCompat(),
Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
Injectable {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager
@ -58,122 +54,197 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
private lateinit var notificationPreference: Preference
private lateinit var tabPreference: Preference
private lateinit var mutedUsersPreference: Preference
private lateinit var blockedUsersPreference: Preference
private lateinit var mutedDomainsPreference: Preference
private lateinit var defaultPostPrivacyPreference: ListPreference
private lateinit var defaultMediaSensitivityPreference: SwitchPreferenceCompat
private lateinit var alwaysShowSensitiveMediaPreference: SwitchPreferenceCompat
private lateinit var alwaysOpenSpoilerPreference: SwitchPreferenceCompat
private lateinit var mediaPreviewEnabledPreference: SwitchPreferenceCompat
private lateinit var homeFiltersPreference: Preference
private lateinit var notificationFiltersPreference: Preference
private lateinit var publicFiltersPreference: Preference
private lateinit var threadFiltersPreference: Preference
private lateinit var accountFiltersPreference: Preference
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.account_preferences) val context = requireContext()
makePreferenceScreen {
notificationPreference = requirePreference("notificationPreference") preference {
tabPreference = requirePreference("tabPreference") setTitle(R.string.pref_title_edit_notification_settings)
mutedUsersPreference = requirePreference("mutedUsersPreference") icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_notifications).apply {
blockedUsersPreference = requirePreference("blockedUsersPreference") sizeRes = R.dimen.preference_icon_size
mutedDomainsPreference = requirePreference("mutedDomainsPreference") colorInt = ThemeUtils.getColor(context, R.attr.iconColor)
defaultPostPrivacyPreference = requirePreference("defaultPostPrivacy") as ListPreference
defaultMediaSensitivityPreference = requirePreference("defaultMediaSensitivity") as SwitchPreferenceCompat
mediaPreviewEnabledPreference = requirePreference("mediaPreviewEnabled") as SwitchPreferenceCompat
alwaysShowSensitiveMediaPreference = requirePreference("alwaysShowSensitiveMedia") as SwitchPreferenceCompat
alwaysOpenSpoilerPreference = requirePreference("alwaysOpenSpoiler") as SwitchPreferenceCompat
homeFiltersPreference = requirePreference("homeFilters")
notificationFiltersPreference = requirePreference("notificationFilters")
publicFiltersPreference = requirePreference("publicFilters")
threadFiltersPreference = requirePreference("threadFilters")
accountFiltersPreference = requirePreference("accountFilters")
notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(notificationPreference.context, R.attr.iconColor) }
mutedUsersPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
blockedUsersPreference.icon = IconicsDrawable(blockedUsersPreference.context, GoogleMaterial.Icon.gmd_block).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(blockedUsersPreference.context, R.attr.iconColor) }
mutedDomainsPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
notificationPreference.onPreferenceClickListener = this
tabPreference.onPreferenceClickListener = this
mutedUsersPreference.onPreferenceClickListener = this
blockedUsersPreference.onPreferenceClickListener = this
mutedDomainsPreference.onPreferenceClickListener = this
homeFiltersPreference.onPreferenceClickListener = this
notificationFiltersPreference.onPreferenceClickListener = this
publicFiltersPreference.onPreferenceClickListener = this
threadFiltersPreference.onPreferenceClickListener = this
accountFiltersPreference.onPreferenceClickListener = this
defaultPostPrivacyPreference.onPreferenceChangeListener = this
defaultMediaSensitivityPreference.onPreferenceChangeListener = this
mediaPreviewEnabledPreference.onPreferenceChangeListener = this
alwaysShowSensitiveMediaPreference.onPreferenceChangeListener = this
alwaysOpenSpoilerPreference.onPreferenceChangeListener = this
} }
setOnPreferenceClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { openNotificationPrefs()
super.onViewCreated(view, savedInstanceState) true
accountManager.activeAccount?.let {
defaultPostPrivacyPreference.value = it.defaultPostPrivacy.serverString()
defaultPostPrivacyPreference.icon = getIconForVisibility(it.defaultPostPrivacy)
defaultMediaSensitivityPreference.isChecked = it.defaultMediaSensitivity
defaultMediaSensitivityPreference.icon = getIconForSensitivity(it.defaultMediaSensitivity)
mediaPreviewEnabledPreference.isChecked = it.mediaPreviewEnabled
alwaysShowSensitiveMediaPreference.isChecked = it.alwaysShowSensitiveMedia
alwaysOpenSpoilerPreference.isChecked = it.alwaysOpenSpoiler
} }
} }
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean { preference {
when (preference) { setTitle(R.string.title_tab_preferences)
defaultPostPrivacyPreference -> { setOnPreferenceClickListener {
preference.icon = getIconForVisibility(Status.Visibility.byString(newValue as String)) val intent = Intent(context, TabPreferenceActivity::class.java)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right,
R.anim.slide_to_left)
true
}
}
preference {
setTitle(R.string.action_view_mutes)
icon = getTintedIcon(R.drawable.ic_mute_24dp)
setOnPreferenceClickListener {
val intent = Intent(context, AccountListActivity::class.java)
intent.putExtra("type", AccountListActivity.Type.MUTES)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right,
R.anim.slide_to_left)
true
}
}
preference {
setTitle(R.string.action_view_blocks)
icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_block).apply {
sizeRes = R.dimen.preference_icon_size
colorInt = ThemeUtils.getColor(context, R.attr.iconColor)
}
setOnPreferenceClickListener {
val intent = Intent(context, AccountListActivity::class.java)
intent.putExtra("type", AccountListActivity.Type.BLOCKS)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right,
R.anim.slide_to_left)
true
}
}
preference {
setTitle(R.string.title_domain_mutes)
icon = getTintedIcon(R.drawable.ic_mute_24dp)
setOnPreferenceClickListener {
val intent = Intent(context, InstanceListActivity::class.java)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right,
R.anim.slide_to_left)
true
}
}
preferenceCategory(R.string.pref_publishing) {
listPreference {
setTitle(R.string.pref_default_post_privacy)
setEntries(R.array.post_privacy_names)
setEntryValues(R.array.post_privacy_values)
key = PrefKeys.DEFAULT_POST_PRIVACY
setSummaryProvider { entry }
val visibility = accountManager.activeAccount?.defaultPostPrivacy
?: Status.Visibility.PUBLIC
value = visibility.serverString()
icon = getIconForVisibility(visibility)
setOnPreferenceChangeListener { _, newValue ->
icon = getIconForVisibility(
Status.Visibility.byString(newValue as String)
)
syncWithServer(visibility = newValue) syncWithServer(visibility = newValue)
eventHub.dispatch(PreferenceChangedEvent(key))
true
} }
defaultMediaSensitivityPreference -> { }
preference.icon = getIconForSensitivity(newValue as Boolean)
switchPreference {
setTitle(R.string.pref_default_media_sensitivity)
setIcon(R.drawable.ic_eye_24dp)
key = PrefKeys.DEFAULT_MEDIA_SENSITIVITY
isSingleLineTitle = false
val sensitivity = accountManager.activeAccount?.defaultMediaSensitivity
?: false
setDefaultValue(sensitivity)
icon = getIconForSensitivity(sensitivity)
setOnPreferenceChangeListener { _, newValue ->
icon = getIconForSensitivity(newValue as Boolean)
syncWithServer(sensitive = newValue) syncWithServer(sensitive = newValue)
} eventHub.dispatch(PreferenceChangedEvent(key))
mediaPreviewEnabledPreference -> { true
accountManager.activeAccount?.let {
it.mediaPreviewEnabled = newValue as Boolean
accountManager.saveAccount(it)
}
}
alwaysShowSensitiveMediaPreference -> {
accountManager.activeAccount?.let {
it.alwaysShowSensitiveMedia = newValue as Boolean
accountManager.saveAccount(it)
}
}
alwaysOpenSpoilerPreference -> {
accountManager.activeAccount?.let {
it.alwaysOpenSpoiler = newValue as Boolean
accountManager.saveAccount(it)
} }
} }
} }
eventHub.dispatch(PreferenceChangedEvent(preference.key)) preferenceCategory(R.string.pref_title_timelines) {
switchPreference {
return true key = PrefKeys.MEDIA_PREVIEW_ENABLED
setTitle(R.string.pref_title_show_media_preview)
isSingleLineTitle = false
isChecked = accountManager.activeAccount?.mediaPreviewEnabled ?: true
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.mediaPreviewEnabled = newValue as Boolean }
eventHub.dispatch(PreferenceChangedEvent(key))
true
}
} }
override fun onPreferenceClick(preference: Preference): Boolean { switchPreference {
key = PrefKeys.ALWAYS_SHOW_SENSITIVE_MEDIA
setTitle(R.string.pref_title_alway_show_sensitive_media)
isSingleLineTitle = false
isChecked = accountManager.activeAccount?.alwaysShowSensitiveMedia ?: false
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.alwaysShowSensitiveMedia = newValue as Boolean }
eventHub.dispatch(PreferenceChangedEvent(key))
true
}
}
return when (preference) { switchPreference {
notificationPreference -> { key = PrefKeys.ALWAYS_OPEN_SPOILER
setTitle(R.string.pref_title_alway_open_spoiler)
isSingleLineTitle = false
isChecked = accountManager.activeAccount?.alwaysOpenSpoiler ?: false
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.alwaysOpenSpoiler = newValue as Boolean }
eventHub.dispatch(PreferenceChangedEvent(key))
true
}
}
}
preferenceCategory(R.string.pref_title_timeline_filters) {
preference {
setTitle(R.string.pref_title_public_filter_keywords)
setOnPreferenceClickListener {
launchFilterActivity(Filter.THREAD,
R.string.pref_title_thread_filter_keywords)
true
}
}
preference {
setTitle(R.string.title_notifications)
setOnPreferenceClickListener {
launchFilterActivity(Filter.NOTIFICATIONS, R.string.title_notifications)
true
}
}
preference {
setTitle(R.string.title_home)
setOnPreferenceClickListener {
launchFilterActivity(Filter.HOME, R.string.title_home)
true
}
}
preference {
setTitle(R.string.pref_title_thread_filter_keywords)
setOnPreferenceClickListener {
launchFilterActivity(Filter.THREAD,
R.string.pref_title_thread_filter_keywords)
true
}
}
preference {
setTitle(R.string.title_accounts)
setOnPreferenceClickListener {
launchFilterActivity(Filter.ACCOUNT, R.string.title_accounts)
true
}
}
}
}
}
private fun openNotificationPrefs() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent() val intent = Intent()
intent.action = "android.settings.APP_NOTIFICATION_SETTINGS" intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
@ -187,53 +258,13 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
} }
} }
true
}
tabPreference -> {
val intent = Intent(context, TabPreferenceActivity::class.java)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
true
}
mutedUsersPreference -> {
val intent = Intent(context, AccountListActivity::class.java)
intent.putExtra("type", AccountListActivity.Type.MUTES)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
true
}
blockedUsersPreference -> {
val intent = Intent(context, AccountListActivity::class.java)
intent.putExtra("type", AccountListActivity.Type.BLOCKS)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
true
}
mutedDomainsPreference -> {
val intent = Intent(context, InstanceListActivity::class.java)
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
true
}
homeFiltersPreference -> {
launchFilterActivity(Filter.HOME, R.string.title_home)
}
notificationFiltersPreference -> {
launchFilterActivity(Filter.NOTIFICATIONS, R.string.title_notifications)
}
publicFiltersPreference -> {
launchFilterActivity(Filter.PUBLIC, R.string.pref_title_public_filter_keywords)
}
threadFiltersPreference -> {
launchFilterActivity(Filter.THREAD, R.string.pref_title_thread_filter_keywords)
}
accountFiltersPreference -> {
launchFilterActivity(Filter.ACCOUNT, R.string.title_accounts)
} }
else -> false private inline fun updateAccount(changer: (AccountEntity) -> Unit) {
accountManager.activeAccount?.let { account ->
changer(account)
accountManager.saveAccount(account)
} }
} }
private fun syncWithServer(visibility: String? = null, sensitive: Boolean? = null) { private fun syncWithServer(visibility: String? = null, sensitive: Boolean? = null) {
@ -297,17 +328,15 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
return ThemeUtils.getTintedDrawable(requireContext(), iconId, R.attr.iconColor) return ThemeUtils.getTintedDrawable(requireContext(), iconId, R.attr.iconColor)
} }
private fun launchFilterActivity(filterContext: String, titleResource: Int): Boolean { private fun launchFilterActivity(filterContext: String, titleResource: Int) {
val intent = Intent(context, FiltersActivity::class.java) val intent = Intent(context, FiltersActivity::class.java)
intent.putExtra(FiltersActivity.FILTERS_CONTEXT, filterContext) intent.putExtra(FiltersActivity.FILTERS_CONTEXT, filterContext)
intent.putExtra(FiltersActivity.FILTERS_TITLE, getString(titleResource)) intent.putExtra(FiltersActivity.FILTERS_TITLE, getString(titleResource))
activity?.startActivity(intent) activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left) activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
return true
} }
companion object { companion object {
fun newInstance() = AccountPreferencesFragment() fun newInstance() = AccountPreferencesFragment()
} }
} }

View File

@ -16,80 +16,148 @@
package com.keylesspalace.tusky.fragment.preference package com.keylesspalace.tusky.fragment.preference
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.db.AccountEntity
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.components.notifications.NotificationHelper import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.makePreferenceScreen
import com.keylesspalace.tusky.settings.preferenceCategory
import com.keylesspalace.tusky.settings.switchPreference
import javax.inject.Inject import javax.inject.Inject
class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener, Injectable { class NotificationPreferencesFragment : PreferenceFragmentCompat(), Injectable {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.notification_preferences) val activeAccount = accountManager.activeAccount ?: return
} val context = requireContext()
makePreferenceScreen {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { switchPreference {
super.onViewCreated(view, savedInstanceState) setTitle(R.string.pref_title_notifications_enabled)
key = PrefKeys.NOTIFICATIONS_ENABLED
val activeAccount = accountManager.activeAccount isIconSpaceReserved = false
isChecked = activeAccount.notificationsEnabled
if (activeAccount != null) { setOnPreferenceChangeListener { _, newValue ->
for (pair in mapOf( updateAccount { it.notificationsEnabled = newValue as Boolean }
"notificationsEnabled" to activeAccount.notificationsEnabled, if (NotificationHelper.areNotificationsEnabled(context, accountManager)) {
"notificationFilterMentions" to activeAccount.notificationsMentioned, NotificationHelper.enablePullNotifications(context)
"notificationFilterFollows" to activeAccount.notificationsFollowed,
"notificationFilterFollowRequests" to activeAccount.notificationsFollowRequested,
"notificationFilterReblogs" to activeAccount.notificationsReblogged,
"notificationFilterFavourites" to activeAccount.notificationsFavorited,
"notificationFilterPolls" to activeAccount.notificationsPolls,
"notificationAlertSound" to activeAccount.notificationSound,
"notificationAlertVibrate" to activeAccount.notificationVibration,
"notificationAlertLight" to activeAccount.notificationLight
)) {
(requirePreference(pair.key) as SwitchPreferenceCompat).apply {
isChecked = pair.value
onPreferenceChangeListener = this@NotificationPreferencesFragment
}
}
}
}
override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
val activeAccount = accountManager.activeAccount
if (activeAccount != null) {
when (preference.key) {
"notificationsEnabled" -> {
activeAccount.notificationsEnabled = newValue as Boolean
if (NotificationHelper.areNotificationsEnabled(preference.context, accountManager)) {
NotificationHelper.enablePullNotifications(preference.context)
} else { } else {
NotificationHelper.disablePullNotifications(preference.context) NotificationHelper.disablePullNotifications(context)
} }
true
} }
"notificationFilterMentions" -> activeAccount.notificationsMentioned = newValue as Boolean
"notificationFilterFollows" -> activeAccount.notificationsFollowed = newValue as Boolean
"notificationFilterFollowRequests" -> activeAccount.notificationsFollowRequested = newValue as Boolean
"notificationFilterReblogs" -> activeAccount.notificationsReblogged = newValue as Boolean
"notificationFilterFavourites" -> activeAccount.notificationsFavorited = newValue as Boolean
"notificationFilterPolls" -> activeAccount.notificationsPolls = newValue as Boolean
"notificationAlertSound" -> activeAccount.notificationSound = newValue as Boolean
"notificationAlertVibrate" -> activeAccount.notificationVibration = newValue as Boolean
"notificationAlertLight" -> activeAccount.notificationLight = newValue as Boolean
}
accountManager.saveAccount(activeAccount)
return true
} }
return false preferenceCategory(R.string.pref_title_notification_filters) { category ->
category.dependency = PrefKeys.NOTIFICATIONS_ENABLED
category.isIconSpaceReserved = false
switchPreference {
setTitle(R.string.pref_title_notification_filter_follows)
key = PrefKeys.NOTIFICATIONS_FILTER_FOLLOWS
isIconSpaceReserved = false
isChecked = activeAccount.notificationsFollowed
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationsFollowed = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_filter_follow_requests)
key = PrefKeys.NOTIFICATION_FILTER_FOLLOW_REQUESTS
isIconSpaceReserved = false
isChecked = activeAccount.notificationsFollowRequested
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationsFollowRequested = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_filter_reblogs)
key = PrefKeys.NOTIFICATION_FILTER_REBLOGS
isIconSpaceReserved = false
isChecked = activeAccount.notificationsReblogged
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationsReblogged = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_filter_favourites)
key = PrefKeys.NOTIFICATION_FILTER_FAVS
isIconSpaceReserved = false
isChecked = activeAccount.notificationsFavorited
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationsFavorited = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_filter_poll)
key = PrefKeys.NOTIFICATION_FILTER_POLLS
isIconSpaceReserved = false
isChecked = activeAccount.notificationsPolls
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationsPolls = newValue as Boolean }
true
}
}
}
preferenceCategory(R.string.pref_title_notification_alerts) { category ->
category.dependency = PrefKeys.NOTIFICATIONS_ENABLED
category.isIconSpaceReserved = false
switchPreference {
setTitle(R.string.pref_title_notification_alert_sound)
key = PrefKeys.NOTIFICATION_ALERT_SOUND
isIconSpaceReserved = false
isChecked = activeAccount.notificationSound
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationSound = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_alert_vibrate)
key = PrefKeys.NOTIFICATION_ALERT_VIBRATE
isIconSpaceReserved = false
isChecked = activeAccount.notificationVibration
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationVibration = newValue as Boolean }
true
}
}
switchPreference {
setTitle(R.string.pref_title_notification_alert_light)
key = PrefKeys.NOTIFICATION_ALERT_LIGHT
isIconSpaceReserved = false
isChecked = activeAccount.notificationLight
setOnPreferenceChangeListener { _, newValue ->
updateAccount { it.notificationLight = newValue as Boolean }
true
}
}
}
}
}
private inline fun updateAccount(changer: (AccountEntity) -> Unit) {
accountManager.activeAccount?.let { account ->
changer(account)
accountManager.saveAccount(account)
}
} }
companion object { companion object {

View File

@ -20,34 +20,108 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.keylesspalace.tusky.PreferencesActivity import com.keylesspalace.tusky.PreferencesActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.*
import com.keylesspalace.tusky.util.ThemeUtils import com.keylesspalace.tusky.util.ThemeUtils
import com.keylesspalace.tusky.util.getNonNullString import com.keylesspalace.tusky.util.getNonNullString
import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeRes import com.mikepenz.iconics.utils.sizePx
fun PreferenceFragmentCompat.requirePreference(key: String): Preference {
return findPreference(key)!!
}
class PreferencesFragment : PreferenceFragmentCompat() { class PreferencesFragment : PreferenceFragmentCompat() {
private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) }
private var httpProxyPref: Preference? = null
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val context = requireContext()
makePreferenceScreen {
preferenceCategory(R.string.pref_title_appearance_settings) {
listPreference {
setDefaultValue(AppTheme.NIGHT.value)
setEntries(R.array.app_theme_names)
entryValues = AppTheme.stringValues()
key = PrefKeys.APP_THEME
setSummaryProvider { entry }
setTitle(R.string.pref_title_app_theme)
icon = makeIcon(GoogleMaterial.Icon.gmd_palette)
}
addPreferencesFromResource(R.xml.preferences) emojiPreference {
setDefaultValue("system_default")
setIcon(R.drawable.ic_emoji_24dp)
key = PrefKeys.EMOJI
setSummary(R.string.system_default)
setTitle(R.string.emoji_style)
icon = makeIcon(GoogleMaterial.Icon.gmd_sentiment_satisfied)
}
val themePreference: Preference = requirePreference("appTheme") listPreference {
themePreference.icon = IconicsDrawable(themePreference.context, GoogleMaterial.Icon.gmd_palette).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) } setDefaultValue("default")
setEntries(R.array.language_entries)
setEntryValues(R.array.language_values)
key = PrefKeys.LANGUAGE
setSummaryProvider { entry }
setTitle(R.string.pref_title_language)
icon = makeIcon(GoogleMaterial.Icon.gmd_translate)
}
val emojiPreference: Preference = requirePreference("emojiCompat") listPreference {
emojiPreference.icon = IconicsDrawable(emojiPreference.context, GoogleMaterial.Icon.gmd_sentiment_satisfied).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) } setDefaultValue("medium")
setEntries(R.array.status_text_size_names)
setEntryValues(R.array.status_text_size_values)
key = PrefKeys.STATUS_TEXT_SIZE
setSummaryProvider { entry }
setTitle(R.string.pref_status_text_size)
icon = makeIcon(GoogleMaterial.Icon.gmd_format_size)
}
val textSizePreference: Preference = requirePreference("statusTextSize") switchPreference {
textSizePreference.icon = IconicsDrawable(textSizePreference.context, GoogleMaterial.Icon.gmd_format_size).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) } setDefaultValue(false)
key = PrefKeys.FAB_HIDE
setTitle(R.string.pref_title_hide_follow_button)
isSingleLineTitle = false
}
val timelineFilterPreferences: Preference = requirePreference("timelineFilterPreferences") switchPreference {
timelineFilterPreferences.setOnPreferenceClickListener { setDefaultValue(false)
key = PrefKeys.ABSOLUTE_TIME_VIEW
setTitle(R.string.pref_title_absolute_time)
isSingleLineTitle = false
}
switchPreference {
setDefaultValue(true)
key = PrefKeys.SHOW_BOT_OVERLAY
setTitle(R.string.pref_title_bot_overlay)
isSingleLineTitle = false
icon = ThemeUtils.getTintedDrawable(
context,
R.drawable.ic_bot_24dp,
R.attr.iconColor
)
}
switchPreference {
setDefaultValue(false)
key = PrefKeys.ANIMATE_GIF_AVATARS
setTitle(R.string.pref_title_animate_gif_avatars)
isSingleLineTitle = false
}
switchPreference {
setDefaultValue(true)
key = PrefKeys.USE_BLURHASH
setTitle(R.string.pref_title_gradient_for_media)
isSingleLineTitle = false
}
switchPreference {
setDefaultValue(true)
key = PrefKeys.SHOW_NOTIFICATIONS_FILTER
setTitle(R.string.pref_title_show_notifications_filter)
isSingleLineTitle = false
setOnPreferenceClickListener {
activity?.let { activity -> activity?.let { activity ->
val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.TAB_FILTER_PREFERENCES) val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.TAB_FILTER_PREFERENCES)
activity.startActivity(intent) activity.startActivity(intent)
@ -55,9 +129,50 @@ class PreferencesFragment : PreferenceFragmentCompat() {
} }
true true
} }
}
val httpProxyPreferences: Preference = requirePreference("httpProxyPreferences") switchPreference {
httpProxyPreferences.setOnPreferenceClickListener { setDefaultValue(false)
key = PrefKeys.SHOW_CARDS_IN_TIMELINES
setTitle(R.string.pref_title_confirm_reblogs)
isSingleLineTitle = false
}
switchPreference {
setDefaultValue(true)
key = PrefKeys.ENABLE_SWIPE_FOR_TABS
setTitle(R.string.pref_title_enable_swipe_for_tabs)
isSingleLineTitle = false
}
}
preferenceCategory(R.string.pref_title_browser_settings) {
switchPreference {
setDefaultValue(false)
key = PrefKeys.CUSTOM_TABS
setTitle(R.string.pref_title_custom_tabs)
isSingleLineTitle = false
}
}
preferenceCategory(R.string.pref_title_timeline_filters) {
preference {
setTitle(R.string.pref_title_status_tabs)
setOnPreferenceClickListener {
activity?.let { activity ->
val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.TAB_FILTER_PREFERENCES)
activity.startActivity(intent)
activity.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
}
true
}
}
}
preferenceCategory(R.string.pref_title_proxy_settings) {
httpProxyPref = preference {
setTitle(R.string.pref_title_http_proxy_settings)
setOnPreferenceClickListener {
activity?.let { activity -> activity?.let { activity ->
val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.PROXY_PREFERENCES) val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.PROXY_PREFERENCES)
activity.startActivity(intent) activity.startActivity(intent)
@ -65,13 +180,18 @@ class PreferencesFragment : PreferenceFragmentCompat() {
} }
true true
} }
}
}
}
}
val languagePreference: Preference = requirePreference("language") private fun makeIcon(icon: GoogleMaterial.Icon): IconicsDrawable {
languagePreference.icon = IconicsDrawable(languagePreference.context, GoogleMaterial.Icon.gmd_translate).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) } val context = requireContext()
return IconicsDrawable(context, icon).apply {
sizePx = iconSize
colorInt = ThemeUtils.getColor(context, R.attr.iconColor)
}
val botIndicatorPreference = requirePreference("showBotOverlay")
botIndicatorPreference.icon = ThemeUtils.getTintedDrawable(requireContext(), R.drawable.ic_bot_24dp, R.attr.iconColor)
} }
override fun onResume() { override fun onResume() {
@ -80,28 +200,23 @@ class PreferencesFragment : PreferenceFragmentCompat() {
} }
private fun updateHttpProxySummary() { private fun updateHttpProxySummary() {
val httpProxyPref: Preference = requirePreference("httpProxyPreferences")
val sharedPreferences = preferenceManager.sharedPreferences val sharedPreferences = preferenceManager.sharedPreferences
val httpProxyEnabled = sharedPreferences.getBoolean(PrefKeys.HTTP_PROXY_ENABLED, false)
val httpProxyEnabled = sharedPreferences.getBoolean("httpProxyEnabled", false) val httpServer = sharedPreferences.getNonNullString(PrefKeys.HTTP_PROXY_SERVER, "")
val httpServer = sharedPreferences.getNonNullString("httpProxyServer", "")
try { try {
val httpPort = sharedPreferences.getNonNullString("httpProxyPort", "-1").toInt() val httpPort = sharedPreferences.getNonNullString(PrefKeys.HTTP_PROXY_PORT, "-1")
.toInt()
if (httpProxyEnabled && httpServer.isNotBlank() && httpPort > 0 && httpPort < 65535) { if (httpProxyEnabled && httpServer.isNotBlank() && httpPort > 0 && httpPort < 65535) {
httpProxyPref.summary = "$httpServer:$httpPort" httpProxyPref?.summary = "$httpServer:$httpPort"
return return
} }
} catch (e: NumberFormatException) { } catch (e: NumberFormatException) {
// user has entered wrong port, fall back to empty summary // user has entered wrong port, fall back to empty summary
} }
httpProxyPref.summary = "" httpProxyPref?.summary = ""
} }
companion object { companion object {

View File

@ -15,61 +15,53 @@
package com.keylesspalace.tusky.fragment.preference package com.keylesspalace.tusky.fragment.preference
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.editTextPreference
import com.keylesspalace.tusky.settings.makePreferenceScreen
import com.keylesspalace.tusky.settings.switchPreference
import kotlin.system.exitProcess import kotlin.system.exitProcess
class ProxyPreferencesFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { class ProxyPreferencesFragment : PreferenceFragmentCompat() {
private var pendingRestart = false private var pendingRestart = false
private lateinit var sharedPreferences: SharedPreferences
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.http_proxy_preferences) makePreferenceScreen {
switchPreference {
sharedPreferences = preferenceManager.sharedPreferences setTitle(R.string.pref_title_http_proxy_enable)
isIconSpaceReserved = false
key = PrefKeys.HTTP_PROXY_ENABLED
setDefaultValue(false)
} }
override fun onResume() { editTextPreference {
super.onResume() setTitle(R.string.pref_title_http_proxy_server)
key = PrefKeys.HTTP_PROXY_SERVER
isIconSpaceReserved = false
setSummaryProvider { text }
}
sharedPreferences.registerOnSharedPreferenceChangeListener(this) editTextPreference {
setTitle(R.string.pref_title_http_proxy_port)
key = PrefKeys.HTTP_PROXY_PORT
isIconSpaceReserved = false
setSummaryProvider { text }
}
}
updateSummary("httpProxyServer")
updateSummary("httpProxyPort")
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
if (pendingRestart) { if (pendingRestart) {
pendingRestart = false pendingRestart = false
exitProcess(0) exitProcess(0)
} }
} }
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
updateSummary (key)
}
private fun updateSummary(key: String) {
when (key) {
"httpProxyServer", "httpProxyPort" -> {
val editTextPreference = requirePreference(key) as EditTextPreference
editTextPreference.summary = editTextPreference.text
}
}
}
companion object { companion object {
fun newInstance(): ProxyPreferencesFragment { fun newInstance(): ProxyPreferencesFragment {
return ProxyPreferencesFragment() return ProxyPreferencesFragment()
} }

View File

@ -15,22 +15,38 @@
package com.keylesspalace.tusky.fragment.preference package com.keylesspalace.tusky.fragment.preference
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.checkBoxPreference
import com.keylesspalace.tusky.settings.makePreferenceScreen
import com.keylesspalace.tusky.settings.preferenceCategory
class TabFilterPreferencesFragment : PreferenceFragmentCompat() { class TabFilterPreferencesFragment : PreferenceFragmentCompat() {
private lateinit var sharedPreferences: SharedPreferences
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.timeline_filter_preferences) makePreferenceScreen {
sharedPreferences = preferenceManager.sharedPreferences preferenceCategory(R.string.title_home) { category ->
category.isIconSpaceReserved = false
checkBoxPreference {
setTitle(R.string.pref_title_show_boosts)
key = PrefKeys.TAB_FILTER_HOME_BOOSTS
setDefaultValue(true)
isIconSpaceReserved = false
}
checkBoxPreference {
setTitle(R.string.pref_title_show_replies)
key = PrefKeys.TAB_FILTER_HOME_REPLIES
setDefaultValue(false)
isIconSpaceReserved = false
}
}
}
} }
companion object { companion object {
fun newInstance(): TabFilterPreferencesFragment { fun newInstance(): TabFilterPreferencesFragment {
return TabFilterPreferencesFragment() return TabFilterPreferencesFragment()
} }

View File

@ -0,0 +1,56 @@
package com.keylesspalace.tusky.settings
enum class AppTheme(val value: String) {
NIGHT("night"),
DAY("day"),
BLACK("black"),
AUTO("auto"),
AUTO_SYSTEM("auto_system");
companion object {
fun stringValues() = values().map { it.value }.toTypedArray()
}
}
object PrefKeys {
// Note: not all of these keys are actually used as SharedPreferences keys but we must give
// each preference a key for it to work.
const val APP_THEME = "appTheme"
const val EMOJI = "emojiCompat"
const val FAB_HIDE = "fabHide"
const val LANGUAGE = "language"
const val STATUS_TEXT_SIZE = "statusTextSize"
const val ABSOLUTE_TIME_VIEW = "absoluteTimeView"
const val SHOW_BOT_OVERLAY = "showBotOverlay"
const val ANIMATE_GIF_AVATARS = "animateGifAvatars"
const val USE_BLURHASH = "useBlurhash"
const val SHOW_NOTIFICATIONS_FILTER = "showNotificationsFilter"
const val SHOW_CARDS_IN_TIMELINES = "showCardsInTimelines"
const val ENABLE_SWIPE_FOR_TABS = "enableSwipeForTabs"
const val CUSTOM_TABS = "customTabs"
const val HTTP_PROXY_ENABLED = "httpProxyEnabled"
const val HTTP_PROXY_SERVER = "httpProxyServer"
const val HTTP_PROXY_PORT = "httpProxyPort"
const val DEFAULT_POST_PRIVACY = "defaultPostPrivacy"
const val DEFAULT_MEDIA_SENSITIVITY = "defaultMediaSensitivity"
const val MEDIA_PREVIEW_ENABLED = "mediaPreviewEnabled"
const val ALWAYS_SHOW_SENSITIVE_MEDIA = "alwaysShowSensitiveMedia"
const val ALWAYS_OPEN_SPOILER = "alwaysOpenSpoiler"
const val NOTIFICATIONS_ENABLED = "notificationsEnabled"
const val NOTIFICATION_ALERT_LIGHT = "notificationAlertLight"
const val NOTIFICATION_ALERT_VIBRATE = "notificationAlertVibrate"
const val NOTIFICATION_ALERT_SOUND = "notificationAlertSound"
const val NOTIFICATION_FILTER_POLLS = "notificationFilterPolls"
const val NOTIFICATION_FILTER_FAVS = "notificationFilterFavourites"
const val NOTIFICATION_FILTER_REBLOGS = "notificationFilterReblogs"
const val NOTIFICATION_FILTER_FOLLOW_REQUESTS = "notificationFilterFollowRequests"
const val NOTIFICATIONS_FILTER_FOLLOWS = "notificationFilterFollows"
const val TAB_FILTER_HOME_REPLIES = "tabFilterHomeBoosts"
const val TAB_FILTER_HOME_BOOSTS = "tabFilterHomeReplies"
}

View File

@ -0,0 +1,83 @@
package com.keylesspalace.tusky.settings
import android.content.Context
import androidx.annotation.StringRes
import androidx.preference.*
import com.keylesspalace.tusky.EmojiPreference
class PreferenceParent(
val context: Context,
val addPref: (pref: Preference) -> Unit
)
inline fun PreferenceParent.preference(builder: Preference.() -> Unit): Preference {
val pref = Preference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.listPreference(builder: ListPreference.() -> Unit): ListPreference {
val pref = ListPreference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.emojiPreference(builder: EmojiPreference.() -> Unit): EmojiPreference {
val pref = EmojiPreference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.switchPreference(
builder: SwitchPreference.() -> Unit
): SwitchPreference {
val pref = SwitchPreference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.editTextPreference(
builder: EditTextPreference.() -> Unit
): EditTextPreference {
val pref = EditTextPreference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.checkBoxPreference(
builder: CheckBoxPreference.() -> Unit
): CheckBoxPreference {
val pref = CheckBoxPreference(context)
addPref(pref)
builder(pref)
return pref
}
inline fun PreferenceParent.preferenceCategory(
@StringRes title: Int,
builder: PreferenceParent.(PreferenceCategory) -> Unit
) {
val category = PreferenceCategory(context)
addPref(category)
category.setTitle(title)
val newParent = PreferenceParent(context) { category.addPreference(it) }
builder(newParent, category)
}
inline fun PreferenceFragmentCompat.makePreferenceScreen(
builder: PreferenceParent.() -> Unit
): PreferenceScreen {
val context = requireContext()
val screen = preferenceManager.createPreferenceScreen(context)
val parent = PreferenceParent(context) { screen.addPreference(it) }
// For some functions (like dependencies) it's much easier for us if we attach screen first
// and change it later
preferenceScreen = screen
builder(parent)
return screen
}

View File

@ -234,7 +234,7 @@
<string name="pref_title_language">Language</string> <string name="pref_title_language">Language</string>
<string name="pref_title_bot_overlay">Show indicator for bots</string> <string name="pref_title_bot_overlay">Show indicator for bots</string>
<string name="pref_title_animate_gif_avatars">Animate GIF avatars</string> <string name="pref_title_animate_gif_avatars">Animate GIF avatars</string>
<string name="gradient_for_media">Show colorful gradients for hidden media</string> <string name="pref_title_gradient_for_media">Show colorful gradients for hidden media</string>
<string name="pref_title_status_filter">Timeline filtering</string> <string name="pref_title_status_filter">Timeline filtering</string>
<string name="pref_title_status_tabs">Tabs</string> <string name="pref_title_status_tabs">Tabs</string>

View File

@ -1,81 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="@string/preferences_file_key">
<Preference
android:key="notificationPreference"
android:title="@string/pref_title_edit_notification_settings" />
<Preference
android:key="tabPreference"
android:title="@string/title_tab_preferences" />
<Preference
android:key="mutedUsersPreference"
android:title="@string/action_view_mutes" />
<Preference
android:key="blockedUsersPreference"
android:title="@string/action_view_blocks" />
<Preference
android:key="mutedDomainsPreference"
android:title="@string/action_view_domain_mutes" />
<PreferenceCategory android:title="@string/pref_publishing">
<ListPreference
android:defaultValue="public"
android:entries="@array/post_privacy_names"
android:entryValues="@array/post_privacy_values"
android:key="defaultPostPrivacy"
android:summary="%s"
android:title="@string/pref_default_post_privacy" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:icon="@drawable/ic_eye_24dp"
android:key="defaultMediaSensitivity"
android:title="@string/pref_default_media_sensitivity"
app:singleLineTitle="false" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_timelines">
<SwitchPreferenceCompat
android:key="mediaPreviewEnabled"
android:title="@string/pref_title_show_media_preview"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:key="alwaysShowSensitiveMedia"
android:title="@string/pref_title_alway_show_sensitive_media"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:key="alwaysOpenSpoiler"
android:title="@string/pref_title_alway_open_spoiler"
app:singleLineTitle="false" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_timeline_filters">
<Preference
android:key="publicFilters"
android:title="@string/pref_title_public_filter_keywords" />
<Preference
android:key="notificationFilters"
android:title="@string/title_notifications" />
<Preference
android:key="homeFilters"
android:title="@string/title_home" />
<Preference
android:key="threadFilters"
android:title="@string/pref_title_thread_filter_keywords" />
<Preference
android:key="accountFilters"
android:title="@string/title_accounts" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/pref_title_http_proxy_settings">
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="httpProxyEnabled"
android:title="@string/pref_title_http_proxy_enable"
app:iconSpaceReserved="false" />
<EditTextPreference
android:key="httpProxyServer"
android:summary="%s"
android:title="@string/pref_title_http_proxy_server"
app:iconSpaceReserved="false" />
<EditTextPreference
android:key="httpProxyPort"
android:summary="%s"
android:title="@string/pref_title_http_proxy_port"
app:iconSpaceReserved="false" />
</androidx.preference.PreferenceScreen>

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="notificationSettings"
android:title="@string/pref_title_edit_notification_settings">
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationsEnabled"
android:title="@string/pref_title_notifications_enabled"
app:iconSpaceReserved="false" />
<PreferenceCategory
android:dependency="notificationsEnabled"
android:title="@string/pref_title_notification_filters"
app:iconSpaceReserved="false">
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationFilterMentions"
android:title="@string/pref_title_notification_filter_mentions"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationFilterFollows"
android:title="@string/pref_title_notification_filter_follows"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="notificationFilterFollowRequests"
android:title="@string/pref_title_notification_filter_follow_requests"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationFilterReblogs"
android:title="@string/pref_title_notification_filter_reblogs"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationFilterFavourites"
android:title="@string/pref_title_notification_filter_favourites"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationFilterPolls"
android:title="@string/pref_title_notification_filter_poll"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:dependency="notificationsEnabled"
android:title="@string/pref_title_notification_alerts"
app:iconSpaceReserved="false">
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationAlertSound"
android:title="@string/pref_title_notification_alert_sound"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationAlertVibrate"
android:title="@string/pref_title_notification_alert_vibrate"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="notificationAlertLight"
android:title="@string/pref_title_notification_alert_light"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -1,118 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="@string/preferences_file_key">
<PreferenceCategory android:title="@string/pref_title_appearance_settings">
<ListPreference
android:defaultValue="night"
android:entries="@array/app_theme_names"
android:entryValues="@array/app_theme_values"
android:key="appTheme"
android:summary="%s"
android:title="@string/pref_title_app_theme" />
<com.keylesspalace.tusky.EmojiPreference
android:defaultValue="@string/system_default"
android:icon="@drawable/ic_emoji_24dp"
android:key="emojiCompat"
android:summary="@string/system_default"
android:title="@string/emoji_style" />
<ListPreference
android:defaultValue="default"
android:entries="@array/language_entries"
android:entryValues="@array/language_values"
android:key="language"
android:summary="%s"
android:title="@string/pref_title_language" />
<ListPreference
android:defaultValue="medium"
android:entries="@array/status_text_size_names"
android:entryValues="@array/status_text_size_values"
android:key="statusTextSize"
android:summary="%s"
android:title="@string/pref_status_text_size" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="fabHide"
android:title="@string/pref_title_hide_follow_button"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="absoluteTimeView"
android:title="@string/pref_title_absolute_time"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="showBotOverlay"
android:title="@string/pref_title_bot_overlay"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="animateGifAvatars"
android:title="@string/pref_title_animate_gif_avatars"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="useBlurhash"
android:title="@string/gradient_for_media"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="showNotificationsFilter"
android:title="@string/pref_title_show_notifications_filter"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="showCardsInTimelines"
android:title="@string/pref_title_show_cards_in_timelines"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="confirmReblogs"
android:title="@string/pref_title_confirm_reblogs"
app:singleLineTitle="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="enableSwipeForTabs"
android:title="@string/pref_title_enable_swipe_for_tabs"
app:singleLineTitle="false" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_browser_settings">
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="customTabs"
android:title="@string/pref_title_custom_tabs"
app:singleLineTitle="false" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_status_filter">
<Preference
android:key="timelineFilterPreferences"
android:title="@string/pref_title_status_tabs" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_proxy_settings">
<Preference
android:key="httpProxyPreferences"
android:summary="%s"
android:title="@string/pref_title_http_proxy_settings" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:title="@string/pref_title_status_tabs">
<PreferenceCategory
android:title="@string/title_home"
app:iconSpaceReserved="false">
<CheckBoxPreference
android:defaultValue="true"
android:key="tabFilterHomeBoosts"
android:title="@string/pref_title_show_boosts"
app:iconSpaceReserved="false" />
<CheckBoxPreference
android:defaultValue="true"
android:key="tabFilterHomeReplies"
android:title="@string/pref_title_show_replies"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>