/* 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 . */ package com.keylesspalace.tusky.components.preference import android.os.Bundle import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference import com.keylesspalace.tusky.R import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.compose.ComposeActivity.ComposeOptions import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.di.Injectable import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.settings.AppTheme import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.emojiPreference import com.keylesspalace.tusky.settings.listPreference import com.keylesspalace.tusky.settings.makePreferenceScreen import com.keylesspalace.tusky.settings.preference import com.keylesspalace.tusky.settings.preferenceCategory import com.keylesspalace.tusky.settings.switchPreference import com.keylesspalace.tusky.util.ThemeUtils import com.keylesspalace.tusky.util.deserialize import com.keylesspalace.tusky.util.getNonNullString import com.keylesspalace.tusky.util.serialize 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 @Inject lateinit var accountManager: AccountManager private val iconSize by lazy { resources.getDimensionPixelSize(R.dimen.preference_icon_size) } private var httpProxyPref: Preference? = null override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { makePreferenceScreen { lateinit var limitedBandwidthMobilePref: SwitchPreference lateinit var limitedBandwidthTimelinePref: SwitchPreference 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.post_text_size_names) setEntryValues(R.array.post_text_size_values) key = PrefKeys.STATUS_TEXT_SIZE setSummaryProvider { entry } setTitle(R.string.pref_post_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 setIcon(R.drawable.ic_bot_24dp) } switchPreference { setDefaultValue(false) key = PrefKeys.ANIMATE_GIF_AVATARS setTitle(R.string.pref_title_animate_gif_avatars) isSingleLineTitle = false } switchPreference { setDefaultValue(false) key = PrefKeys.ANIMATE_CUSTOM_EMOJIS setTitle(R.string.pref_title_animate_custom_emojis) 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 } switchPreference { setDefaultValue(true) key = PrefKeys.CONFIRM_REBLOGS setTitle(R.string.pref_title_confirm_reblogs) isSingleLineTitle = false } switchPreference { setDefaultValue(false) key = PrefKeys.CONFIRM_FAVOURITES setTitle(R.string.pref_title_confirm_favourites) isSingleLineTitle = false } switchPreference { setDefaultValue(true) key = PrefKeys.ENABLE_SWIPE_FOR_TABS setTitle(R.string.pref_title_enable_swipe_for_tabs) isSingleLineTitle = false } switchPreference { setDefaultValue(true) key = PrefKeys.USE_QUICK_TOOT setTitle(R.string.pref_title_use_quick_toot) isSingleLineTitle = false } } preferenceCategory(R.string.pref_title_limited_bandwidth_settings) { switchPreference { setDefaultValue(false) key = PrefKeys.LIMITED_BANDWIDTH_ACTIVE setTitle(R.string.pref_title_limited_bandwidth_active) disableDependentsState = false isSingleLineTitle = false } limitedBandwidthMobilePref = switchPreference { setDefaultValue(true) key = PrefKeys.LIMITED_BANDWIDTH_ONLY_MOBILE_NETWORK setTitle(R.string.pref_title_limited_bandwidth_mobile) isSingleLineTitle = false } limitedBandwidthTimelinePref = switchPreference { setDefaultValue(true) key = PrefKeys.LIMITED_BANDWIDTH_TIMELINE_LOADING setTitle(R.string.pref_title_limited_bandwidth_timeline) isSingleLineTitle = false } } arrayOf(limitedBandwidthMobilePref, limitedBandwidthTimelinePref).forEach { it.dependency = PrefKeys.LIMITED_BANDWIDTH_ACTIVE } 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_post_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_wellbeing_mode) { switchPreference { title = getString(R.string.limit_notifications) setDefaultValue(false) key = PrefKeys.WELLBEING_LIMITED_NOTIFICATIONS setOnPreferenceChangeListener { _, value -> for (account in accountManager.accounts) { val notificationFilter = deserialize(account.notificationsFilter).toMutableSet() if (value == true) { notificationFilter.add(Notification.Type.FAVOURITE) notificationFilter.add(Notification.Type.FOLLOW) notificationFilter.add(Notification.Type.REBLOG) } else { notificationFilter.remove(Notification.Type.FAVOURITE) notificationFilter.remove(Notification.Type.FOLLOW) notificationFilter.remove(Notification.Type.REBLOG) } account.notificationsFilter = serialize(notificationFilter) accountManager.saveAccount(account) } true } } switchPreference { title = getString(R.string.wellbeing_hide_stats_posts) setDefaultValue(false) key = PrefKeys.WELLBEING_HIDE_STATS_POSTS } switchPreference { title = getString(R.string.wellbeing_hide_stats_profile) setDefaultValue(false) key = PrefKeys.WELLBEING_HIDE_STATS_PROFILE } } 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 } } } preferenceCategory(R.string.pref_title_experimental) { switchPreference { title = getString(R.string.pref_title_experimental_viewpager_offscreen) setDefaultValue(false) key = PrefKeys.VIEW_PAGER_OFF_SCREEN_LIMIT } } preferenceManager.sharedPreferences?.let { prefs -> prefs.getString(PrefKeys.STACK_TRACE, null)?.let { stackTrace -> preferenceCategory(R.string.pref_title_stacktrace) { preference { setTitle(R.string.pref_title_stacktrace_send) setOnPreferenceClickListener { activity?.let { activity -> val intent = ComposeActivity.startIntent(activity, ComposeOptions( content = "@ars42525@odakyu.app $stackTrace".substring(0, 400), contentWarning = "Yuito StackTrace" )) activity.startActivity(intent) prefs.edit() .remove(PrefKeys.STACK_TRACE) .apply() } true } key = PrefKeys.SEND_CRASH_REPORT } preference { summary = stackTrace isSelectable = false } } } } } } 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() { preferenceManager.sharedPreferences?.let { 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() } } }