convert EmojiPreference and EmojiCompatFont to Kotlin (#1922)
* convert EmojiPreference and EmojiCompatFont to Kotlin * move preference related to to dedicated preference package * update proguard-rules.pro * reformat & add comment * maintain disposable information in EmojiPreference instead of EmojiCompatFont
This commit is contained in:
parent
fc7b02d987
commit
1d309850b0
21 changed files with 709 additions and 906 deletions
|
|
@ -0,0 +1,343 @@
|
|||
/* 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.components.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()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
package com.keylesspalace.tusky.components.preference
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.SplashActivity
|
||||
import com.keylesspalace.tusky.util.EmojiCompatFont
|
||||
import com.keylesspalace.tusky.util.EmojiCompatFont.Companion.FONTS
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import okhttp3.OkHttpClient
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
* This Preference lets the user select their preferred emoji font
|
||||
*/
|
||||
class EmojiPreference(
|
||||
context: Context,
|
||||
private val okHttpClient: OkHttpClient
|
||||
) : Preference(context) {
|
||||
|
||||
private lateinit var selected: EmojiCompatFont
|
||||
private lateinit var original: EmojiCompatFont
|
||||
private val radioButtons = mutableListOf<RadioButton>()
|
||||
private var updated = false
|
||||
private var currentNeedsUpdate = false
|
||||
|
||||
private val downloadDisposables = MutableList<Disposable?>(FONTS.size) { null }
|
||||
|
||||
override fun onAttachedToHierarchy(preferenceManager: PreferenceManager) {
|
||||
super.onAttachedToHierarchy(preferenceManager)
|
||||
|
||||
// Find out which font is currently active
|
||||
selected = EmojiCompatFont.byId(
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getInt(key, 0)
|
||||
)
|
||||
// We'll use this later to determine if anything has changed
|
||||
original = selected
|
||||
summary = selected.getDisplay(context)
|
||||
}
|
||||
|
||||
override fun onClick() {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_emojicompat, null)
|
||||
viewIds.forEachIndexed { index, viewId ->
|
||||
setupItem(view.findViewById(viewId), FONTS[index])
|
||||
}
|
||||
AlertDialog.Builder(context)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> onDialogOk() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun setupItem(container: View, font: EmojiCompatFont) {
|
||||
val title: TextView = container.findViewById(R.id.emojicompat_name)
|
||||
val caption: TextView = container.findViewById(R.id.emojicompat_caption)
|
||||
val thumb: ImageView = container.findViewById(R.id.emojicompat_thumb)
|
||||
val download: ImageButton = container.findViewById(R.id.emojicompat_download)
|
||||
val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel)
|
||||
val radio: RadioButton = container.findViewById(R.id.emojicompat_radio)
|
||||
|
||||
// Initialize all the views
|
||||
title.text = font.getDisplay(container.context)
|
||||
caption.setText(font.caption)
|
||||
thumb.setImageResource(font.img)
|
||||
|
||||
// There needs to be a list of all the radio buttons in order to uncheck them when one is selected
|
||||
radioButtons.add(radio)
|
||||
updateItem(font, container)
|
||||
|
||||
// Set actions
|
||||
download.setOnClickListener { startDownload(font, container) }
|
||||
cancel.setOnClickListener { cancelDownload(font, container) }
|
||||
radio.setOnClickListener { radioButton: View -> select(font, radioButton as RadioButton) }
|
||||
container.setOnClickListener { containerView: View ->
|
||||
select(font, containerView.findViewById(R.id.emojicompat_radio))
|
||||
}
|
||||
}
|
||||
|
||||
private fun startDownload(font: EmojiCompatFont, container: View) {
|
||||
val download: ImageButton = container.findViewById(R.id.emojicompat_download)
|
||||
val caption: TextView = container.findViewById(R.id.emojicompat_caption)
|
||||
val progressBar: ProgressBar = container.findViewById(R.id.emojicompat_progress)
|
||||
val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel)
|
||||
|
||||
// Switch to downloading style
|
||||
download.visibility = View.GONE
|
||||
caption.visibility = View.INVISIBLE
|
||||
progressBar.visibility = View.VISIBLE
|
||||
progressBar.progress = 0
|
||||
cancel.visibility = View.VISIBLE
|
||||
font.downloadFontFile(context, okHttpClient)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{ progress ->
|
||||
// The progress is returned as a float between 0 and 1, or -1 if it could not determined
|
||||
if (progress >= 0) {
|
||||
progressBar.isIndeterminate = false
|
||||
val max = progressBar.max.toFloat()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
progressBar.setProgress((max * progress).toInt(), true)
|
||||
} else {
|
||||
progressBar.progress = (max * progress).toInt()
|
||||
}
|
||||
} else {
|
||||
progressBar.isIndeterminate = true
|
||||
}
|
||||
},
|
||||
{
|
||||
Toast.makeText(context, R.string.download_failed, Toast.LENGTH_SHORT).show()
|
||||
updateItem(font, container)
|
||||
},
|
||||
{
|
||||
finishDownload(font, container)
|
||||
}
|
||||
).also { downloadDisposables[font.id] = it }
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun cancelDownload(font: EmojiCompatFont, container: View) {
|
||||
font.deleteDownloadedFile(container.context)
|
||||
downloadDisposables[font.id]?.dispose()
|
||||
downloadDisposables[font.id] = null
|
||||
updateItem(font, container)
|
||||
}
|
||||
|
||||
private fun finishDownload(font: EmojiCompatFont, container: View) {
|
||||
select(font, container.findViewById(R.id.emojicompat_radio))
|
||||
updateItem(font, container)
|
||||
// Set the flag to restart the app (because an update has been downloaded)
|
||||
if (selected === original && currentNeedsUpdate) {
|
||||
updated = true
|
||||
currentNeedsUpdate = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a font both visually and logically
|
||||
*
|
||||
* @param font The font to be selected
|
||||
* @param radio The radio button associated with it's visual item
|
||||
*/
|
||||
private fun select(font: EmojiCompatFont, radio: RadioButton) {
|
||||
selected = font
|
||||
// Uncheck all the other buttons
|
||||
for (other in radioButtons) {
|
||||
if (other !== radio) {
|
||||
other.isChecked = false
|
||||
}
|
||||
}
|
||||
radio.isChecked = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a "consistent" state is reached, i.e. it's not downloading the font
|
||||
*
|
||||
* @param font The font to be displayed
|
||||
* @param container The ConstraintLayout containing the item
|
||||
*/
|
||||
private fun updateItem(font: EmojiCompatFont, container: View) {
|
||||
// Assignments
|
||||
val download: ImageButton = container.findViewById(R.id.emojicompat_download)
|
||||
val caption: TextView = container.findViewById(R.id.emojicompat_caption)
|
||||
val progress: ProgressBar = container.findViewById(R.id.emojicompat_progress)
|
||||
val cancel: ImageButton = container.findViewById(R.id.emojicompat_download_cancel)
|
||||
val radio: RadioButton = container.findViewById(R.id.emojicompat_radio)
|
||||
|
||||
// There's no download going on
|
||||
progress.visibility = View.GONE
|
||||
cancel.visibility = View.GONE
|
||||
caption.visibility = View.VISIBLE
|
||||
if (font.isDownloaded(context)) {
|
||||
// Make it selectable
|
||||
download.visibility = View.GONE
|
||||
radio.visibility = View.VISIBLE
|
||||
container.isClickable = true
|
||||
} else {
|
||||
// Make it downloadable
|
||||
download.visibility = View.VISIBLE
|
||||
radio.visibility = View.GONE
|
||||
container.isClickable = false
|
||||
}
|
||||
|
||||
// Select it if necessary
|
||||
if (font === selected) {
|
||||
radio.isChecked = true
|
||||
// Update available
|
||||
if (!font.isDownloaded(context)) {
|
||||
currentNeedsUpdate = true
|
||||
}
|
||||
} else {
|
||||
radio.isChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSelectedFont() {
|
||||
val index = selected.id
|
||||
Log.i(TAG, "saveSelectedFont: Font ID: $index")
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(context)
|
||||
.edit()
|
||||
.putInt(key, index)
|
||||
.apply()
|
||||
summary = selected.getDisplay(context)
|
||||
}
|
||||
|
||||
/**
|
||||
* User clicked ok -> save the selected font and offer to restart the app if something changed
|
||||
*/
|
||||
private fun onDialogOk() {
|
||||
saveSelectedFont()
|
||||
if (selected !== original || updated) {
|
||||
AlertDialog.Builder(context)
|
||||
.setTitle(R.string.restart_required)
|
||||
.setMessage(R.string.restart_emoji)
|
||||
.setNegativeButton(R.string.later, null)
|
||||
.setPositiveButton(R.string.restart) { _, _ ->
|
||||
// Restart the app
|
||||
// From https://stackoverflow.com/a/17166729/5070653
|
||||
val launchIntent = Intent(context, SplashActivity::class.java)
|
||||
val mPendingIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
0x1f973, // This is the codepoint of the party face emoji :D
|
||||
launchIntent,
|
||||
PendingIntent.FLAG_CANCEL_CURRENT)
|
||||
val mgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
mgr.set(
|
||||
AlarmManager.RTC,
|
||||
System.currentTimeMillis() + 100,
|
||||
mPendingIntent)
|
||||
exitProcess(0)
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "EmojiPreference"
|
||||
|
||||
// Please note that this array must sorted in the same way as the fonts.
|
||||
private val viewIds = intArrayOf(
|
||||
R.id.item_nomoji,
|
||||
R.id.item_blobmoji,
|
||||
R.id.item_twemoji,
|
||||
R.id.item_notoemoji
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/* 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.components.preference
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
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.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(), Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var accountManager: AccountManager
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
fun newInstance(): NotificationPreferencesFragment {
|
||||
return NotificationPreferencesFragment()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/* 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.components.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.MenuItem
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.keylesspalace.tusky.BaseActivity
|
||||
import com.keylesspalace.tusky.MainActivity
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.getNonNullString
|
||||
import dagger.android.DispatchingAndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
HasAndroidInjector {
|
||||
|
||||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
@Inject
|
||||
lateinit var androidInjector: DispatchingAndroidInjector<Any>
|
||||
|
||||
private var restartActivitiesOnExit: Boolean = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.activity_preferences)
|
||||
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar?.run {
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
||||
val fragment: Fragment = when (intent.getIntExtra(EXTRA_PREFERENCE_TYPE, 0)) {
|
||||
GENERAL_PREFERENCES -> {
|
||||
setTitle(R.string.action_view_preferences)
|
||||
PreferencesFragment.newInstance()
|
||||
}
|
||||
ACCOUNT_PREFERENCES -> {
|
||||
setTitle(R.string.action_view_account_preferences)
|
||||
AccountPreferencesFragment.newInstance()
|
||||
}
|
||||
NOTIFICATION_PREFERENCES -> {
|
||||
setTitle(R.string.pref_title_edit_notification_settings)
|
||||
NotificationPreferencesFragment.newInstance()
|
||||
}
|
||||
TAB_FILTER_PREFERENCES -> {
|
||||
setTitle(R.string.pref_title_status_tabs)
|
||||
TabFilterPreferencesFragment.newInstance()
|
||||
}
|
||||
PROXY_PREFERENCES -> {
|
||||
setTitle(R.string.pref_title_http_proxy_settings)
|
||||
ProxyPreferencesFragment.newInstance()
|
||||
}
|
||||
else -> throw IllegalArgumentException("preferenceType not known")
|
||||
}
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment_container, fragment)
|
||||
.commit()
|
||||
|
||||
restartActivitiesOnExit = intent.getBooleanExtra("restart", false)
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun saveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean("restart", restartActivitiesOnExit)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean("restart", restartActivitiesOnExit)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
|
||||
when (key) {
|
||||
"appTheme" -> {
|
||||
val theme = sharedPreferences.getNonNullString("appTheme", ThemeUtils.APP_THEME_DEFAULT)
|
||||
Log.d("activeTheme", theme)
|
||||
ThemeUtils.setAppNightMode(theme)
|
||||
|
||||
restartActivitiesOnExit = true
|
||||
this.restartCurrentActivity()
|
||||
|
||||
}
|
||||
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars",
|
||||
"useBlurhash", "showCardsInTimelines", "confirmReblogs", "enableSwipeForTabs", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR -> {
|
||||
restartActivitiesOnExit = true
|
||||
}
|
||||
"language" -> {
|
||||
restartActivitiesOnExit = true
|
||||
this.restartCurrentActivity()
|
||||
}
|
||||
}
|
||||
|
||||
eventHub.dispatch(PreferenceChangedEvent(key))
|
||||
}
|
||||
|
||||
private fun restartCurrentActivity() {
|
||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
val savedInstanceState = Bundle()
|
||||
saveInstanceState(savedInstanceState)
|
||||
intent.putExtras(savedInstanceState)
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.fade_in, R.anim.fade_out)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
/* Switching themes won't actually change the theme of activities on the back stack.
|
||||
* Either the back stack activities need to all be recreated, or do the easier thing, which
|
||||
* is hijack the back button press and use it to launch a new MainActivity and clear the
|
||||
* back stack. */
|
||||
if (restartActivitiesOnExit) {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivityWithSlideInAnimation(intent)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun androidInjector() = androidInjector
|
||||
|
||||
companion object {
|
||||
|
||||
const val GENERAL_PREFERENCES = 0
|
||||
const val ACCOUNT_PREFERENCES = 1
|
||||
const val NOTIFICATION_PREFERENCES = 2
|
||||
const val TAB_FILTER_PREFERENCES = 3
|
||||
const val PROXY_PREFERENCES = 4
|
||||
private const val EXTRA_PREFERENCE_TYPE = "EXTRA_PREFERENCE_TYPE"
|
||||
|
||||
@JvmStatic
|
||||
fun newIntent(context: Context, preferenceType: Int): Intent {
|
||||
val intent = Intent(context, PreferencesActivity::class.java)
|
||||
intent.putExtra(EXTRA_PREFERENCE_TYPE, preferenceType)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
/* 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.components.preference
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
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.sizePx
|
||||
import okhttp3.OkHttpClient
|
||||
import javax.inject.Inject
|
||||
|
||||
class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var okhttpclient: OkHttpClient
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
emojiPreference(okhttpclient) {
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
listPreference {
|
||||
setDefaultValue("top")
|
||||
setEntries(R.array.pref_main_nav_position_options)
|
||||
setEntryValues(R.array.pref_main_nav_position_values)
|
||||
key = PrefKeys.MAIN_NAV_POSITION
|
||||
setSummaryProvider { entry }
|
||||
setTitle(R.string.pref_main_nav_position)
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
setDefaultValue(false)
|
||||
key = PrefKeys.HIDE_TOP_TOOLBAR
|
||||
setTitle(R.string.pref_title_hide_top_toolbar)
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
setDefaultValue(false)
|
||||
key = PrefKeys.FAB_HIDE
|
||||
setTitle(R.string.pref_title_hide_follow_button)
|
||||
isSingleLineTitle = false
|
||||
}
|
||||
|
||||
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(false)
|
||||
key = PrefKeys.SHOW_CARDS_IN_TIMELINES
|
||||
setTitle(R.string.pref_title_show_cards_in_timelines)
|
||||
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(true)
|
||||
key = PrefKeys.CONFIRM_REBLOGS
|
||||
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 ->
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateHttpProxySummary()
|
||||
}
|
||||
|
||||
private fun updateHttpProxySummary() {
|
||||
val sharedPreferences = preferenceManager.sharedPreferences
|
||||
val httpProxyEnabled = sharedPreferences.getBoolean(PrefKeys.HTTP_PROXY_ENABLED, false)
|
||||
val httpServer = sharedPreferences.getNonNullString(PrefKeys.HTTP_PROXY_SERVER, "")
|
||||
|
||||
try {
|
||||
val httpPort = sharedPreferences.getNonNullString(PrefKeys.HTTP_PROXY_PORT, "-1")
|
||||
.toInt()
|
||||
|
||||
if (httpProxyEnabled && httpServer.isNotBlank() && httpPort > 0 && httpPort < 65535) {
|
||||
httpProxyPref?.summary = "$httpServer:$httpPort"
|
||||
return
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
// user has entered wrong port, fall back to empty summary
|
||||
}
|
||||
|
||||
httpProxyPref?.summary = ""
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(): PreferencesFragment {
|
||||
return PreferencesFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/* 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.components.preference
|
||||
|
||||
import android.os.Bundle
|
||||
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() {
|
||||
private var pendingRestart = false
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
makePreferenceScreen {
|
||||
switchPreference {
|
||||
setTitle(R.string.pref_title_http_proxy_enable)
|
||||
isIconSpaceReserved = false
|
||||
key = PrefKeys.HTTP_PROXY_ENABLED
|
||||
setDefaultValue(false)
|
||||
}
|
||||
|
||||
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 onPause() {
|
||||
super.onPause()
|
||||
if (pendingRestart) {
|
||||
pendingRestart = false
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance(): ProxyPreferencesFragment {
|
||||
return ProxyPreferencesFragment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/* 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.components.preference
|
||||
|
||||
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() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue