diff --git a/app/src/main/java/com/keylesspalace/tusky/EmojiPreference.java b/app/src/main/java/com/keylesspalace/tusky/EmojiPreference.java
index cdf09002a..8837c7d8d 100644
--- a/app/src/main/java/com/keylesspalace/tusky/EmojiPreference.java
+++ b/app/src/main/java/com/keylesspalace/tusky/EmojiPreference.java
@@ -43,6 +43,18 @@ public class EmojiPreference extends Preference {
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) {
super(context, attrs);
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
index 3e54f7ce5..9fa6a6e54 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
@@ -19,21 +19,21 @@ import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
-import com.google.android.material.snackbar.Snackbar
import android.util.Log
-import android.view.View
-import androidx.preference.*
+import androidx.preference.PreferenceFragmentCompat
+import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.*
-import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
import com.keylesspalace.tusky.components.instancemute.InstanceListActivity
+import com.keylesspalace.tusky.db.AccountEntity
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi
+import com.keylesspalace.tusky.settings.*
import com.keylesspalace.tusky.util.ThemeUtils
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
@@ -44,11 +44,7 @@ import retrofit2.Callback
import retrofit2.Response
import javax.inject.Inject
-
-class AccountPreferencesFragment : PreferenceFragmentCompat(),
- Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
- Injectable {
-
+class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
@Inject
lateinit var accountManager: AccountManager
@@ -58,182 +54,217 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
@Inject
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?) {
- addPreferencesFromResource(R.xml.account_preferences)
-
- notificationPreference = requirePreference("notificationPreference")
- tabPreference = requirePreference("tabPreference")
- mutedUsersPreference = requirePreference("mutedUsersPreference")
- blockedUsersPreference = requirePreference("blockedUsersPreference")
- mutedDomainsPreference = requirePreference("mutedDomainsPreference")
- 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
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- 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 {
- when (preference) {
- defaultPostPrivacyPreference -> {
- preference.icon = getIconForVisibility(Status.Visibility.byString(newValue as String))
- syncWithServer(visibility = newValue)
- }
- defaultMediaSensitivityPreference -> {
- preference.icon = getIconForSensitivity(newValue as Boolean)
- syncWithServer(sensitive = newValue)
- }
- mediaPreviewEnabledPreference -> {
- accountManager.activeAccount?.let {
- it.mediaPreviewEnabled = newValue as Boolean
- accountManager.saveAccount(it)
+ val context = requireContext()
+ makePreferenceScreen {
+ preference {
+ setTitle(R.string.pref_title_edit_notification_settings)
+ icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_notifications).apply {
+ sizeRes = R.dimen.preference_icon_size
+ colorInt = ThemeUtils.getColor(context, R.attr.iconColor)
+ }
+ setOnPreferenceClickListener {
+ openNotificationPrefs()
+ true
}
}
- alwaysShowSensitiveMediaPreference -> {
- accountManager.activeAccount?.let {
- it.alwaysShowSensitiveMedia = newValue as Boolean
- accountManager.saveAccount(it)
+
+ preference {
+ setTitle(R.string.title_tab_preferences)
+ setOnPreferenceClickListener {
+ val intent = Intent(context, TabPreferenceActivity::class.java)
+ activity?.startActivity(intent)
+ activity?.overridePendingTransition(R.anim.slide_from_right,
+ R.anim.slide_to_left)
+ true
}
}
- alwaysOpenSpoilerPreference -> {
- accountManager.activeAccount?.let {
- it.alwaysOpenSpoiler = newValue as Boolean
- accountManager.saveAccount(it)
+
+ 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
}
}
- }
- eventHub.dispatch(PreferenceChangedEvent(preference.key))
+ 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
+ }
+ }
- return 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
+ }
+ }
- override fun onPreferenceClick(preference: Preference): Boolean {
-
- return when (preference) {
- notificationPreference -> {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val intent = Intent()
- intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
- intent.putExtra("android.provider.extra.APP_PACKAGE", BuildConfig.APPLICATION_ID)
- startActivity(intent)
- } else {
- activity?.let {
- val intent = PreferencesActivity.newIntent(it, PreferencesActivity.NOTIFICATION_PREFERENCES)
- it.startActivity(intent)
- it.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
+ 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)
+ eventHub.dispatch(PreferenceChangedEvent(key))
+ true
+ }
+ }
+
+ 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)
+ eventHub.dispatch(PreferenceChangedEvent(key))
+ true
}
-
}
- 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
+ preferenceCategory(R.string.pref_title_timelines) {
+ switchPreference {
+ 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
+ }
+ }
+
+ 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
+ }
+ }
+
+ switchPreference {
+ 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) {
+ val intent = Intent()
+ intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
+ intent.putExtra("android.provider.extra.APP_PACKAGE", BuildConfig.APPLICATION_ID)
+ startActivity(intent)
+ } else {
+ activity?.let {
+ val intent = PreferencesActivity.newIntent(it, PreferencesActivity.NOTIFICATION_PREFERENCES)
+ it.startActivity(intent)
+ it.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
+ }
+
+ }
+ }
+
+ 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) {
@@ -297,17 +328,15 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
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)
intent.putExtra(FiltersActivity.FILTERS_CONTEXT, filterContext)
intent.putExtra(FiltersActivity.FILTERS_TITLE, getString(titleResource))
activity?.startActivity(intent)
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
- return true
}
companion object {
fun newInstance() = AccountPreferencesFragment()
}
-
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
index db01b0271..800ea7c1d 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
@@ -16,80 +16,148 @@
package com.keylesspalace.tusky.fragment.preference
import android.os.Bundle
-import android.view.View
-import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
-import androidx.preference.SwitchPreferenceCompat
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.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
-class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener, Injectable {
+class NotificationPreferencesFragment : PreferenceFragmentCompat(), Injectable {
@Inject
lateinit var accountManager: AccountManager
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- addPreferencesFromResource(R.xml.notification_preferences)
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- val activeAccount = accountManager.activeAccount
-
- if (activeAccount != null) {
- for (pair in mapOf(
- "notificationsEnabled" to activeAccount.notificationsEnabled,
- "notificationFilterMentions" to activeAccount.notificationsMentioned,
- "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
+ val activeAccount = accountManager.activeAccount ?: return
+ val context = requireContext()
+ makePreferenceScreen {
+ switchPreference {
+ setTitle(R.string.pref_title_notifications_enabled)
+ key = PrefKeys.NOTIFICATIONS_ENABLED
+ isIconSpaceReserved = false
+ isChecked = activeAccount.notificationsEnabled
+ setOnPreferenceChangeListener { _, newValue ->
+ updateAccount { it.notificationsEnabled = newValue as Boolean }
+ if (NotificationHelper.areNotificationsEnabled(context, accountManager)) {
+ NotificationHelper.enablePullNotifications(context)
+ } else {
+ NotificationHelper.disablePullNotifications(context)
+ }
+ true
}
}
- }
- }
- override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
+ preferenceCategory(R.string.pref_title_notification_filters) { category ->
+ category.dependency = PrefKeys.NOTIFICATIONS_ENABLED
+ category.isIconSpaceReserved = false
- 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 {
- NotificationHelper.disablePullNotifications(preference.context)
+ 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
}
}
- "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
+ 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 {
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/PreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/PreferencesFragment.kt
index 825275a1a..60e978111 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/PreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/PreferencesFragment.kt
@@ -20,58 +20,178 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.keylesspalace.tusky.PreferencesActivity
import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.settings.*
import com.keylesspalace.tusky.util.ThemeUtils
import com.keylesspalace.tusky.util.getNonNullString
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt
-import com.mikepenz.iconics.utils.sizeRes
-
-fun PreferenceFragmentCompat.requirePreference(key: String): Preference {
- return findPreference(key)!!
-}
+import com.mikepenz.iconics.utils.sizePx
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?) {
+ 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")
- themePreference.icon = IconicsDrawable(themePreference.context, GoogleMaterial.Icon.gmd_palette).apply { sizeRes = R.dimen.preference_icon_size; colorInt = ThemeUtils.getColor(themePreference.context, R.attr.iconColor) }
+ listPreference {
+ 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")
- 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) }
+ listPreference {
+ 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")
- 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) }
+ switchPreference {
+ setDefaultValue(false)
+ key = PrefKeys.FAB_HIDE
+ setTitle(R.string.pref_title_hide_follow_button)
+ isSingleLineTitle = false
+ }
- val timelineFilterPreferences: Preference = requirePreference("timelineFilterPreferences")
- timelineFilterPreferences.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)
+ switchPreference {
+ 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 ->
+ 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
+ }
+ }
+
+ switchPreference {
+ 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
+ }
}
- true
+
+ 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 ->
+ val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.PROXY_PREFERENCES)
+ activity.startActivity(intent)
+ activity.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
+ }
+ true
+ }
+ }
+ }
+ }
+ }
+
+ private fun makeIcon(icon: GoogleMaterial.Icon): IconicsDrawable {
+ val context = requireContext()
+ return IconicsDrawable(context, icon).apply {
+ sizePx = iconSize
+ colorInt = ThemeUtils.getColor(context, R.attr.iconColor)
}
- val httpProxyPreferences: Preference = requirePreference("httpProxyPreferences")
- httpProxyPreferences.setOnPreferenceClickListener {
- activity?.let { activity ->
- val intent = PreferencesActivity.newIntent(activity, PreferencesActivity.PROXY_PREFERENCES)
- activity.startActivity(intent)
- activity.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
- }
- true
- }
-
- val languagePreference: Preference = requirePreference("language")
- 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 botIndicatorPreference = requirePreference("showBotOverlay")
-
- botIndicatorPreference.icon = ThemeUtils.getTintedDrawable(requireContext(), R.drawable.ic_bot_24dp, R.attr.iconColor)
}
override fun onResume() {
@@ -80,28 +200,23 @@ class PreferencesFragment : PreferenceFragmentCompat() {
}
private fun updateHttpProxySummary() {
-
- val httpProxyPref: Preference = requirePreference("httpProxyPreferences")
-
val sharedPreferences = preferenceManager.sharedPreferences
-
- val httpProxyEnabled = sharedPreferences.getBoolean("httpProxyEnabled", false)
-
- val httpServer = sharedPreferences.getNonNullString("httpProxyServer", "")
+ val httpProxyEnabled = sharedPreferences.getBoolean(PrefKeys.HTTP_PROXY_ENABLED, false)
+ val httpServer = sharedPreferences.getNonNullString(PrefKeys.HTTP_PROXY_SERVER, "")
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) {
- httpProxyPref.summary = "$httpServer:$httpPort"
+ httpProxyPref?.summary = "$httpServer:$httpPort"
return
}
} catch (e: NumberFormatException) {
// user has entered wrong port, fall back to empty summary
}
- httpProxyPref.summary = ""
-
+ httpProxyPref?.summary = ""
}
companion object {
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/ProxyPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/ProxyPreferencesFragment.kt
index a4efff2d7..e7ee7ade0 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/ProxyPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/ProxyPreferencesFragment.kt
@@ -15,61 +15,53 @@
package com.keylesspalace.tusky.fragment.preference
-import android.content.SharedPreferences
import android.os.Bundle
-import androidx.preference.EditTextPreference
import androidx.preference.PreferenceFragmentCompat
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
-class ProxyPreferencesFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener {
-
+class ProxyPreferencesFragment : PreferenceFragmentCompat() {
private var pendingRestart = false
- private lateinit var sharedPreferences: SharedPreferences
-
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- addPreferencesFromResource(R.xml.http_proxy_preferences)
+ makePreferenceScreen {
+ switchPreference {
+ setTitle(R.string.pref_title_http_proxy_enable)
+ isIconSpaceReserved = false
+ key = PrefKeys.HTTP_PROXY_ENABLED
+ setDefaultValue(false)
+ }
- sharedPreferences = preferenceManager.sharedPreferences
+ editTextPreference {
+ setTitle(R.string.pref_title_http_proxy_server)
+ key = PrefKeys.HTTP_PROXY_SERVER
+ isIconSpaceReserved = false
+ setSummaryProvider { text }
+ }
- }
+ editTextPreference {
+ setTitle(R.string.pref_title_http_proxy_port)
+ key = PrefKeys.HTTP_PROXY_PORT
+ isIconSpaceReserved = false
+ setSummaryProvider { text }
+ }
+ }
- override fun onResume() {
- super.onResume()
-
- sharedPreferences.registerOnSharedPreferenceChangeListener(this)
-
- updateSummary("httpProxyServer")
- updateSummary("httpProxyPort")
}
override fun onPause() {
super.onPause()
-
- sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
-
if (pendingRestart) {
pendingRestart = false
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 {
-
fun newInstance(): ProxyPreferencesFragment {
return ProxyPreferencesFragment()
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/TabFilterPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/TabFilterPreferencesFragment.kt
index 8d92d54bd..cd76300da 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/TabFilterPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/TabFilterPreferencesFragment.kt
@@ -15,22 +15,38 @@
package com.keylesspalace.tusky.fragment.preference
-import android.content.SharedPreferences
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
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() {
-
- private lateinit var sharedPreferences: SharedPreferences
-
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- addPreferencesFromResource(R.xml.timeline_filter_preferences)
- sharedPreferences = preferenceManager.sharedPreferences
+ makePreferenceScreen {
+ 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 {
-
fun newInstance(): TabFilterPreferencesFragment {
return TabFilterPreferencesFragment()
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt
new file mode 100644
index 000000000..ab60206fe
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsConstants.kt
@@ -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"
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/settings/SettingsDSL.kt b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsDSL.kt
new file mode 100644
index 000000000..effad5370
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/settings/SettingsDSL.kt
@@ -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
+}
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 91fa69c80..c48d7cb23 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -234,7 +234,7 @@
Language
Show indicator for bots
Animate GIF avatars
- Show colorful gradients for hidden media
+ Show colorful gradients for hidden media
Timeline filtering
Tabs
diff --git a/app/src/main/res/xml/account_preferences.xml b/app/src/main/res/xml/account_preferences.xml
deleted file mode 100644
index ec4d2c2ae..000000000
--- a/app/src/main/res/xml/account_preferences.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/xml/http_proxy_preferences.xml b/app/src/main/res/xml/http_proxy_preferences.xml
deleted file mode 100644
index fef294266..000000000
--- a/app/src/main/res/xml/http_proxy_preferences.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/notification_preferences.xml b/app/src/main/res/xml/notification_preferences.xml
deleted file mode 100644
index fa03f8d1b..000000000
--- a/app/src/main/res/xml/notification_preferences.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
deleted file mode 100644
index dcb37b73c..000000000
--- a/app/src/main/res/xml/preferences.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/xml/timeline_filter_preferences.xml b/app/src/main/res/xml/timeline_filter_preferences.xml
deleted file mode 100644
index bbe749d02..000000000
--- a/app/src/main/res/xml/timeline_filter_preferences.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file