344 lines
14 KiB
Kotlin
344 lines
14 KiB
Kotlin
/* Copyright 2018 Conny Duck
|
|
*
|
|
* This file is a part of Tusky.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with Tusky; if not,
|
|
* see <http://www.gnu.org/licenses>. */
|
|
|
|
package com.keylesspalace.tusky.fragment.preference
|
|
|
|
import android.content.Intent
|
|
import android.graphics.drawable.Drawable
|
|
import android.os.Build
|
|
import android.os.Bundle
|
|
import android.util.Log
|
|
import androidx.preference.PreferenceFragmentCompat
|
|
import com.google.android.material.snackbar.Snackbar
|
|
import com.keylesspalace.tusky.*
|
|
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
|
|
import com.mikepenz.iconics.utils.colorInt
|
|
import com.mikepenz.iconics.utils.sizeRes
|
|
import retrofit2.Call
|
|
import retrofit2.Callback
|
|
import retrofit2.Response
|
|
import javax.inject.Inject
|
|
|
|
class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
|
@Inject
|
|
lateinit var accountManager: AccountManager
|
|
|
|
@Inject
|
|
lateinit var mastodonApi: MastodonApi
|
|
|
|
@Inject
|
|
lateinit var eventHub: EventHub
|
|
|
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
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
|
|
}
|
|
}
|
|
|
|
preference {
|
|
setTitle(R.string.title_tab_preferences)
|
|
icon = getTintedIcon(R.drawable.ic_tabs)
|
|
setOnPreferenceClickListener {
|
|
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)
|
|
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
|
|
}
|
|
}
|
|
}
|
|
|
|
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.PUBLIC,
|
|
R.string.pref_title_public_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) {
|
|
mastodonApi.accountUpdateSource(visibility, sensitive)
|
|
.enqueue(object : Callback<Account> {
|
|
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
|
val account = response.body()
|
|
if (response.isSuccessful && account != null) {
|
|
|
|
accountManager.activeAccount?.let {
|
|
it.defaultPostPrivacy = account.source?.privacy
|
|
?: Status.Visibility.PUBLIC
|
|
it.defaultMediaSensitivity = account.source?.sensitive ?: false
|
|
accountManager.saveAccount(it)
|
|
}
|
|
} else {
|
|
Log.e("AccountPreferences", "failed updating settings on server")
|
|
showErrorSnackbar(visibility, sensitive)
|
|
}
|
|
}
|
|
|
|
override fun onFailure(call: Call<Account>, t: Throwable) {
|
|
Log.e("AccountPreferences", "failed updating settings on server", t)
|
|
showErrorSnackbar(visibility, sensitive)
|
|
}
|
|
|
|
})
|
|
}
|
|
|
|
private fun showErrorSnackbar(visibility: String?, sensitive: Boolean?) {
|
|
view?.let { view ->
|
|
Snackbar.make(view, R.string.pref_failed_to_sync, Snackbar.LENGTH_LONG)
|
|
.setAction(R.string.action_retry) { syncWithServer(visibility, sensitive) }
|
|
.show()
|
|
}
|
|
}
|
|
|
|
private fun getIconForVisibility(visibility: Status.Visibility): Drawable? {
|
|
val drawableId = when (visibility) {
|
|
Status.Visibility.PRIVATE -> R.drawable.ic_lock_outline_24dp
|
|
|
|
Status.Visibility.UNLISTED -> R.drawable.ic_lock_open_24dp
|
|
|
|
else -> R.drawable.ic_public_24dp
|
|
}
|
|
|
|
return getTintedIcon(drawableId)
|
|
}
|
|
|
|
private fun getIconForSensitivity(sensitive: Boolean): Drawable? {
|
|
val drawableId = if (sensitive) {
|
|
R.drawable.ic_hide_media_24dp
|
|
} else {
|
|
R.drawable.ic_eye_24dp
|
|
}
|
|
|
|
return getTintedIcon(drawableId)
|
|
}
|
|
|
|
private fun getTintedIcon(iconId: Int): Drawable? {
|
|
return ThemeUtils.getTintedDrawable(requireContext(), iconId, R.attr.iconColor)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
companion object {
|
|
fun newInstance() = AccountPreferencesFragment()
|
|
}
|
|
}
|