1+ package com.fox2code.mmm.settings
2+
3+ import android.content.ClipData
4+ import android.content.ClipboardManager
5+ import android.content.Context
6+ import android.content.DialogInterface
7+ import android.content.Intent
8+ import android.content.SharedPreferences
9+ import android.net.Uri
10+ import android.os.Build
11+ import android.os.Bundle
12+ import android.widget.Toast
13+ import androidx.preference.ListPreference
14+ import androidx.preference.Preference
15+ import androidx.preference.PreferenceFragmentCompat
16+ import androidx.preference.TwoStatePreference
17+ import androidx.security.crypto.EncryptedSharedPreferences
18+ import androidx.security.crypto.MasterKey
19+ import com.fox2code.foxcompat.app.FoxActivity
20+ import com.fox2code.mmm.MainApplication
21+ import com.fox2code.mmm.R
22+ import com.fox2code.rosettax.LanguageSwitcher
23+ import com.google.android.material.dialog.MaterialAlertDialogBuilder
24+ import com.topjohnwu.superuser.internal.UiThreadHandler
25+ import timber.log.Timber
26+
27+ class AppearanceFragment : PreferenceFragmentCompat () {
28+ override fun onCreatePreferences (savedInstanceState : Bundle ? , rootKey : String? ) {
29+ val name = " mmmx"
30+ val context: Context ? = MainApplication .INSTANCE
31+ val masterKey: MasterKey
32+ val preferenceManager = preferenceManager
33+ val dataStore: SharedPreferenceDataStore
34+ val editor: SharedPreferences .Editor
35+ try {
36+ masterKey =
37+ MasterKey .Builder (context!! ).setKeyScheme(MasterKey .KeyScheme .AES256_GCM )
38+ .build()
39+ dataStore = SharedPreferenceDataStore (
40+ EncryptedSharedPreferences .create(
41+ context,
42+ name,
43+ masterKey,
44+ EncryptedSharedPreferences .PrefKeyEncryptionScheme .AES256_SIV ,
45+ EncryptedSharedPreferences .PrefValueEncryptionScheme .AES256_GCM
46+ )
47+ )
48+ preferenceManager!! .preferenceDataStore = dataStore
49+ preferenceManager.sharedPreferencesName = " mmm"
50+ editor = dataStore.sharedPreferences.edit()
51+ } catch (e: Exception ) {
52+ Timber .e(e, " Failed to create encrypted shared preferences" )
53+ throw RuntimeException (getString(R .string.error_encrypted_shared_preferences))
54+ }
55+ setPreferencesFromResource(R .xml.theme_preferences, rootKey)
56+
57+ RepoFragment .applyMaterial3(preferenceScreen)
58+ val themePreference = findPreference<ListPreference >(" pref_theme" )
59+ // If transparent theme(s) are set, disable monet
60+ if (themePreference!! .value == " transparent_light" ) {
61+ Timber .d(" disabling monet" )
62+ findPreference<Preference >(" pref_enable_monet" )!! .isEnabled = false
63+ // Toggle monet off
64+ (findPreference<Preference >(" pref_enable_monet" ) as TwoStatePreference ? )!! .isChecked =
65+ false
66+ editor.putBoolean(" pref_enable_monet" , false ).apply ()
67+ // Set summary
68+ findPreference<Preference >(" pref_enable_monet" )!! .setSummary(R .string.monet_disabled_summary)
69+ // Same for blur
70+ findPreference<Preference >(" pref_enable_blur" )!! .isEnabled = false
71+ (findPreference<Preference >(" pref_enable_blur" ) as TwoStatePreference ? )!! .isChecked =
72+ false
73+ editor.putBoolean(" pref_enable_blur" , false ).apply ()
74+ findPreference<Preference >(" pref_enable_blur" )!! .setSummary(R .string.blur_disabled_summary)
75+ }
76+ themePreference.summaryProvider =
77+ Preference .SummaryProvider { _: Preference ? -> themePreference.entry }
78+ themePreference.onPreferenceChangeListener =
79+ Preference .OnPreferenceChangeListener { _: Preference ? , newValue: Any ->
80+ Timber .d(" refreshing activity. New value: %s" , newValue)
81+ editor.putString(" pref_theme" , newValue as String ).apply ()
82+ // If theme contains "transparent" then disable monet
83+ if (newValue.toString().contains(" transparent" )) {
84+ Timber .d(" disabling monet" )
85+ // Show a dialogue warning the user about issues with transparent themes and
86+ // that blur/monet will be disabled
87+ MaterialAlertDialogBuilder (requireContext()).setTitle(R .string.transparent_theme_dialogue_title)
88+ .setMessage(
89+ R .string.transparent_theme_dialogue_message
90+ ).setPositiveButton(R .string.ok) { _: DialogInterface ? , _: Int ->
91+ // Toggle monet off
92+ (findPreference<Preference >(" pref_enable_monet" ) as TwoStatePreference ? )!! .isChecked =
93+ false
94+ editor.putBoolean(" pref_enable_monet" , false ).apply ()
95+ // Set summary
96+ findPreference<Preference >(" pref_enable_monet" )!! .setSummary(R .string.monet_disabled_summary)
97+ // Same for blur
98+ (findPreference<Preference >(" pref_enable_blur" ) as TwoStatePreference ? )!! .isChecked =
99+ false
100+ editor.putBoolean(" pref_enable_blur" , false ).apply ()
101+ findPreference<Preference >(" pref_enable_blur" )!! .setSummary(R .string.blur_disabled_summary)
102+ // Refresh activity
103+ UiThreadHandler .handler.postDelayed({
104+ MainApplication .INSTANCE !! .updateTheme()
105+ FoxActivity .getFoxActivity(this )
106+ .setThemeRecreate(MainApplication .INSTANCE !! .getManagerThemeResId())
107+ }, 1 )
108+ val intent = Intent (requireContext(), SettingsActivity ::class .java)
109+ intent.addFlags(Intent .FLAG_ACTIVITY_CLEAR_TOP )
110+ startActivity(intent)
111+ }.setNegativeButton(R .string.cancel) { _: DialogInterface ? , _: Int ->
112+ // Revert to system theme
113+ (findPreference<Preference >(" pref_theme" ) as ListPreference ? )!! .value =
114+ " system"
115+ // Refresh activity
116+ }.show()
117+ } else {
118+ findPreference<Preference >(" pref_enable_monet" )!! .isEnabled = true
119+ findPreference<Preference >(" pref_enable_monet" )?.summary = " "
120+ findPreference<Preference >(" pref_enable_blur" )!! .isEnabled = true
121+ findPreference<Preference >(" pref_enable_blur" )?.summary = " "
122+ }
123+ UiThreadHandler .handler.postDelayed({
124+ MainApplication .INSTANCE !! .updateTheme()
125+ FoxActivity .getFoxActivity(this ).setThemeRecreate(MainApplication .INSTANCE !! .getManagerThemeResId())
126+ }, 1 )
127+ true
128+ }
129+
130+ val disableMonet = findPreference<Preference >(" pref_enable_monet" )
131+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .S ) {
132+ disableMonet!! .setSummary(R .string.require_android_12)
133+ disableMonet.isEnabled = false
134+ }
135+ disableMonet!! .onPreferenceClickListener = Preference .OnPreferenceClickListener {
136+ UiThreadHandler .handler.postDelayed({
137+ MainApplication .INSTANCE !! .updateTheme()
138+ (requireActivity() as FoxActivity ).setThemeRecreate(MainApplication .INSTANCE !! .getManagerThemeResId())
139+ }, 1 )
140+ true
141+ }
142+
143+
144+ val enableBlur = findPreference<Preference >(" pref_enable_blur" )
145+ // Disable blur on low performance devices
146+ if (SettingsActivity .devicePerformanceClass < SettingsActivity .PERFORMANCE_CLASS_AVERAGE ) {
147+ // Show a warning
148+ enableBlur!! .onPreferenceChangeListener =
149+ Preference .OnPreferenceChangeListener { _: Preference ? , newValue: Any ->
150+ if (newValue == true ) {
151+ MaterialAlertDialogBuilder (requireContext()).setTitle(R .string.low_performance_device_dialogue_title)
152+ .setMessage(
153+ R .string.low_performance_device_dialogue_message
154+ ).setPositiveButton(R .string.ok) { _: DialogInterface ? , _: Int ->
155+ // Toggle blur on
156+ (findPreference<Preference >(" pref_enable_blur" ) as TwoStatePreference ? )!! .isChecked =
157+ true
158+ editor.putBoolean(" pref_enable_blur" , true ).apply ()
159+ // Set summary
160+ findPreference<Preference >(" pref_enable_blur" )!! .setSummary(R .string.blur_disabled_summary)
161+ }
162+ .setNegativeButton(R .string.cancel) { _: DialogInterface ? , _: Int ->
163+ // Revert to blur on
164+ (findPreference<Preference >(" pref_enable_blur" ) as TwoStatePreference ? )!! .isChecked =
165+ false
166+ editor.putBoolean(" pref_enable_blur" , false ).apply ()
167+ // Set summary
168+ findPreference<Preference >(" pref_enable_blur" )?.summary =
169+ getString(R .string.blur_performance_warning_summary)
170+ }.show()
171+ }
172+ true
173+ }
174+ }
175+
176+
177+ // Handle pref_language_selector_cta by taking user to https://translate.nift4.org/engage/foxmmm/
178+ val languageSelectorCta =
179+ findPreference<LongClickablePreference >(" pref_language_selector_cta" )
180+ languageSelectorCta!! .onPreferenceClickListener =
181+ Preference .OnPreferenceClickListener { _: Preference ? ->
182+ val browserIntent = Intent (
183+ Intent .ACTION_VIEW , Uri .parse(" https://translate.nift4.org/engage/foxmmm/" )
184+ )
185+ startActivity(browserIntent)
186+ true
187+ }
188+
189+
190+ val languageSelector = findPreference<Preference >(" pref_language_selector" )
191+ languageSelector!! .onPreferenceClickListener =
192+ Preference .OnPreferenceClickListener { _: Preference ? ->
193+ val ls = LanguageSwitcher (
194+ requireActivity()
195+ )
196+ ls.setSupportedStringLocales(MainApplication .supportedLocales)
197+ ls.showChangeLanguageDialog(activity)
198+ true
199+ }
200+
201+ // Long click to copy url
202+ languageSelectorCta.onPreferenceLongClickListener =
203+ LongClickablePreference .OnPreferenceLongClickListener { _: Preference ? ->
204+ val clipboard =
205+ requireContext().getSystemService(FoxActivity .CLIPBOARD_SERVICE ) as ClipboardManager
206+ val clip =
207+ ClipData .newPlainText(" URL" , " https://translate.nift4.org/engage/foxmmm/" )
208+ clipboard.setPrimaryClip(clip)
209+ Toast .makeText(requireContext(), R .string.link_copied, Toast .LENGTH_SHORT )
210+ .show()
211+ true
212+ }
213+
214+ val translatedBy = this .getString(R .string.language_translated_by)
215+ // I don't "translate" english
216+ if (! (" Translated by Fox2Code (Put your name here)" == translatedBy || " Translated by Fox2Code" == translatedBy)) {
217+ languageSelector.setSummary(R .string.language_translated_by)
218+ } else {
219+ languageSelector.summary = null
220+ }
221+ }
222+ }
0 commit comments