2 * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser Android is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.fragments
22 import android.annotation.SuppressLint
23 import android.content.Intent
24 import android.content.SharedPreferences
25 import android.content.SharedPreferences.OnSharedPreferenceChangeListener
26 import android.content.res.Configuration
27 import android.os.Build
28 import android.os.Bundle
29 import android.os.Handler
30 import android.os.Looper
31 import android.webkit.WebView
32 import android.widget.ArrayAdapter
34 import androidx.appcompat.app.AppCompatDelegate
35 import androidx.preference.Preference
36 import androidx.preference.PreferenceCategory
37 import androidx.preference.PreferenceFragmentCompat
39 import com.stoutner.privacybrowser.R
40 import com.stoutner.privacybrowser.activities.SETTINGS_CUSTOM_USER_AGENT
41 import com.stoutner.privacybrowser.activities.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT
42 import com.stoutner.privacybrowser.activities.UNRECOGNIZED_USER_AGENT
43 import com.stoutner.privacybrowser.helpers.ProxyHelper
44 import kotlin.system.exitProcess
46 class SettingsFragment : PreferenceFragmentCompat() {
47 // Declare the class variables.
48 private lateinit var appThemeEntriesStringArray: Array<String>
49 private lateinit var appThemeEntryValuesStringArray: Array<String>
50 private lateinit var defaultUserAgent: String
51 private lateinit var sharedPreferenceChangeListener: OnSharedPreferenceChangeListener
52 private lateinit var translatedUserAgentNamesArray: Array<String>
53 private lateinit var userAgentDataArray: Array<String>
54 private lateinit var userAgentNamesArray: ArrayAdapter<CharSequence>
55 private lateinit var webViewThemeEntriesStringArray: Array<String>
56 private lateinit var webViewThemeEntryValuesStringArray: Array<String>
58 // Define the the class views.
59 private lateinit var javaScriptPreference: Preference
60 private lateinit var cookiesPreference: Preference
61 private lateinit var domStoragePreference: Preference
62 private lateinit var formDataPreference: Preference // The form data preference can be removed once the minimum API >= 26.
63 private lateinit var userAgentPreference: Preference
64 private lateinit var customUserAgentPreference: Preference
65 private lateinit var incognitoModePreference: Preference
66 private lateinit var allowScreenshotsPreference: Preference
67 private lateinit var easyListPreference: Preference
68 private lateinit var easyPrivacyPreference: Preference
69 private lateinit var fanboyAnnoyanceListPreference: Preference
70 private lateinit var fanboySocialBlockingListPreference: Preference
71 private lateinit var ultraListPreference: Preference
72 private lateinit var ultraPrivacyPreference: Preference
73 private lateinit var blockAllThirdPartyRequestsPreference: Preference
74 private lateinit var trackingQueriesPreference: Preference
75 private lateinit var ampRedirectsPreference: Preference
76 private lateinit var searchPreference: Preference
77 private lateinit var searchCustomURLPreference: Preference
78 private lateinit var proxyPreference: Preference
79 private lateinit var proxyCustomUrlPreference: Preference
80 private lateinit var fullScreenBrowsingModePreference: Preference
81 private lateinit var hideAppBarPreference: Preference
82 private lateinit var clearEverythingPreference: Preference
83 private lateinit var clearCookiesPreference: Preference
84 private lateinit var clearDomStoragePreference: Preference
85 private lateinit var clearFormDataPreference: Preference // The clear form data preference can be removed once the minimum API >= 26.
86 private lateinit var clearLogcatPreference: Preference
87 private lateinit var clearCachePreference: Preference
88 private lateinit var homepagePreference: Preference
89 private lateinit var fontSizePreference: Preference
90 private lateinit var openIntentsInNewTabPreference: Preference
91 private lateinit var swipeToRefreshPreference: Preference
92 private lateinit var downloadWithExternalAppPreference: Preference
93 private lateinit var scrollAppBarPreference: Preference
94 private lateinit var bottomAppBarPreference: Preference
95 private lateinit var displayAdditionalAppBarIconsPreference: Preference
96 private lateinit var appThemePreference: Preference
97 private lateinit var webViewThemePreference: Preference
98 private lateinit var wideViewportPreference: Preference
99 private lateinit var displayWebpageImagesPreference: Preference
101 override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
102 // Load the preferences from the XML file.
103 setPreferencesFromResource(R.xml.preferences, rootKey)
105 // Get a handle for the shared preferences.
106 val sharedPreferences = preferenceScreen.sharedPreferences!!
108 // Get handles for the preferences.
109 javaScriptPreference = findPreference(getString(R.string.javascript_key))!!
110 cookiesPreference = findPreference(getString(R.string.cookies_key))!!
111 domStoragePreference = findPreference(getString(R.string.dom_storage_key))!!
112 formDataPreference = findPreference(getString(R.string.save_form_data_key))!! // The form data preference can be removed once the minimum API >= 26.
113 userAgentPreference = findPreference(getString(R.string.user_agent_key))!!
114 customUserAgentPreference = findPreference(getString(R.string.custom_user_agent_key))!!
115 incognitoModePreference = findPreference(getString(R.string.incognito_mode_key))!!
116 allowScreenshotsPreference = findPreference(getString(R.string.allow_screenshots_key))!!
117 easyListPreference = findPreference(getString(R.string.easylist_key))!!
118 easyPrivacyPreference = findPreference(getString(R.string.easyprivacy_key))!!
119 fanboyAnnoyanceListPreference = findPreference(getString(R.string.fanboys_annoyance_list_key))!!
120 fanboySocialBlockingListPreference = findPreference(getString(R.string.fanboys_social_blocking_list_key))!!
121 ultraListPreference = findPreference(getString(R.string.ultralist_key))!!
122 ultraPrivacyPreference = findPreference(getString(R.string.ultraprivacy_key))!!
123 blockAllThirdPartyRequestsPreference = findPreference(getString(R.string.block_all_third_party_requests_key))!!
124 trackingQueriesPreference = findPreference(getString(R.string.tracking_queries_key))!!
125 ampRedirectsPreference = findPreference(getString(R.string.amp_redirects_key))!!
126 searchPreference = findPreference(getString(R.string.search_key))!!
127 searchCustomURLPreference = findPreference(getString(R.string.search_custom_url_key))!!
128 proxyPreference = findPreference(getString(R.string.proxy_key))!!
129 proxyCustomUrlPreference = findPreference(getString(R.string.proxy_custom_url_key))!!
130 fullScreenBrowsingModePreference = findPreference(getString(R.string.full_screen_browsing_mode_key))!!
131 hideAppBarPreference = findPreference(getString(R.string.hide_app_bar_key))!!
132 clearEverythingPreference = findPreference(getString(R.string.clear_everything_key))!!
133 clearCookiesPreference = findPreference(getString(R.string.clear_cookies_key))!!
134 clearDomStoragePreference = findPreference(getString(R.string.clear_dom_storage_key))!!
135 clearFormDataPreference = findPreference(getString(R.string.clear_form_data_key))!! // The clear form data preference can be removed once the minimum API >= 26.
136 clearLogcatPreference = findPreference(getString(R.string.clear_logcat_key))!!
137 clearCachePreference = findPreference(getString(R.string.clear_cache_key))!!
138 homepagePreference = findPreference(getString(R.string.homepage_key))!!
139 fontSizePreference = findPreference(getString(R.string.font_size_key))!!
140 openIntentsInNewTabPreference = findPreference(getString(R.string.open_intents_in_new_tab_key))!!
141 swipeToRefreshPreference = findPreference(getString(R.string.swipe_to_refresh_key))!!
142 downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key))!!
143 scrollAppBarPreference = findPreference(getString(R.string.scroll_app_bar_key))!!
144 bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key))!!
145 displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key))!!
146 appThemePreference = findPreference(getString(R.string.app_theme_key))!!
147 webViewThemePreference = findPreference(getString(R.string.webview_theme_key))!!
148 wideViewportPreference = findPreference(getString(R.string.wide_viewport_key))!!
149 displayWebpageImagesPreference = findPreference(getString(R.string.display_webpage_images_key))!!
151 // Set the preference dependencies.
152 domStoragePreference.dependency = getString(R.string.javascript_key)
153 hideAppBarPreference.dependency = getString(R.string.full_screen_browsing_mode_key)
155 // Get strings from the preferences.
156 val userAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
157 val searchString = sharedPreferences.getString(getString(R.string.search_key), getString(R.string.search_default_value))
158 val proxyString = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))
160 // Get booleans that are used in multiple places from the preferences.
161 val javaScriptEnabled = sharedPreferences.getBoolean(getString(R.string.javascript_key), false)
162 val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
163 val fanboySocialBlockingEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
164 val fullScreenBrowsingMode = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)
165 val clearEverything = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
167 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
168 if (Build.VERSION.SDK_INT >= 26) {
169 // Get handles for the categories.
170 val privacyCategory = findPreference<PreferenceCategory>(getString(R.string.privacy_category_key))!!
171 val clearAndExitCategory = findPreference<PreferenceCategory>(getString(R.string.clear_and_exit_category_key))!!
173 // Remove the form data preferences.
174 privacyCategory.removePreference(formDataPreference)
175 clearAndExitCategory.removePreference(clearFormDataPreference)
178 // Remove the WebView theme preference if the API < 29.
179 if (Build.VERSION.SDK_INT < 29) {
180 // Get a handle for the general category.
181 val generalCategory = findPreference<PreferenceCategory>(getString(R.string.general_category_key))!!
183 // Remove the WebView theme preference.
184 generalCategory.removePreference(webViewThemePreference)
187 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
188 fanboySocialBlockingListPreference.isEnabled = !fanboyAnnoyanceListEnabled
191 // Inflate a WebView to get the default user agent.
192 val inflater = requireActivity().layoutInflater
194 // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because the `bare_webview` will not be displayed.
195 @SuppressLint("InflateParams") val bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false)
197 // Get a handle for the bare WebView.
198 val bareWebView = bareWebViewLayout.findViewById<WebView>(R.id.bare_webview)
200 // Get the default user agent.
201 defaultUserAgent = bareWebView.settings.userAgentString
203 // Get the user agent arrays.
204 userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item)
205 translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names)
206 userAgentDataArray = resources.getStringArray(R.array.user_agent_data)
208 // Populate the user agent summary.
209 when (val userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName)) {
210 // The user agent name is not on the canonical list.
211 // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. Use the current user agent entry name as the summary.
212 UNRECOGNIZED_USER_AGENT -> userAgentPreference.summary = userAgentName
214 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
215 SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n$defaultUserAgent"
217 // Display the custom user agent.
218 SETTINGS_CUSTOM_USER_AGENT -> userAgentPreference.setSummary(R.string.custom_user_agent)
220 // Get the user agent summary from the user agent data array.
221 else -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n${userAgentDataArray[userAgentArrayPosition]}"
224 // Set the summary text for the custom user agent preference.
225 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
227 // Only enable the custom user agent preference if the user agent is set to custom.
228 customUserAgentPreference.isEnabled = (userAgentPreference.summary == getString(R.string.custom_user_agent))
230 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
231 if (searchString == getString(R.string.custom_url_item)) {
232 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
233 searchPreference.setSummary(R.string.custom_url)
235 // Set the array value as the summary text.
236 searchPreference.summary = searchString
239 // Set the summary text for the search custom URL (the default is `""`).
240 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
242 // Only enable the search custom URL preference if the search is set to a custom URL.
243 searchCustomURLPreference.isEnabled = (searchString == getString(R.string.custom_url_item))
245 // Set the summary text for the proxy preference.
246 proxyPreference.summary = when (proxyString) {
247 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
248 ProxyHelper.TOR -> getString(R.string.tor_enabled)
249 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
250 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
251 else -> getString(R.string.no_proxy_enabled)
254 // Set the summary text for the custom proxy URL.
255 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
257 // Only enable the custom proxy URL if a custom proxy is selected.
258 proxyCustomUrlPreference.isEnabled = proxyString == ProxyHelper.CUSTOM
260 // Set the status of the clear and exit preferences.
261 clearCookiesPreference.isEnabled = !clearEverything
262 clearDomStoragePreference.isEnabled = !clearEverything
263 clearFormDataPreference.isEnabled = !clearEverything // Clear form data can be removed once the minimum API is >= 26.
264 clearLogcatPreference.isEnabled = !clearEverything
265 clearCachePreference.isEnabled = !clearEverything
267 // Set the homepage URL as the summary text for the homepage preference.
268 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
270 // Set the font size as the summary text for the preference.
271 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
273 // Get the app theme string arrays.
274 appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries)
275 appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values)
277 // Get the app theme entry number that matches the current app theme.
278 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
279 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
280 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
281 else -> 0 // The system default theme is selected.
284 // Set the current theme as the summary text for the preference.
285 appThemePreference.summary = appThemeEntriesStringArray[appThemeEntryNumber]
287 // Enable the WebView theme preference if the app theme is not set to light. Google does not allow light themes to display dark WebViews.
288 webViewThemePreference.isEnabled = (appThemeEntryNumber != 1)
290 // Get the WebView theme string arrays.
291 webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries)
292 webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
294 // Get the WebView theme entry number that matches the current WebView theme.
295 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
296 webViewThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
297 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
298 else -> 0 // The system default theme is selected.
301 // Set the current theme as the summary text for the preference.
302 webViewThemePreference.summary = webViewThemeEntriesStringArray[webViewThemeEntryNumber]
304 // Set the JavaScript icon.
305 if (javaScriptEnabled)
306 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
308 javaScriptPreference.setIcon(R.drawable.privacy_mode)
310 // Set the cookies icon.
311 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
312 cookiesPreference.setIcon(R.drawable.cookies_enabled)
314 cookiesPreference.setIcon(R.drawable.cookies_disabled)
316 // Set the DOM storage icon.
317 if (javaScriptEnabled) { // JavaScript is enabled.
318 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false)) // DOM storage is enabled.
319 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
320 else // DOM storage is disabled.
321 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
322 } else { // JavaScript is disabled. DOM storage should be ghosted.
323 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
326 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
327 if (Build.VERSION.SDK_INT < 26) {
328 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
329 formDataPreference.setIcon(R.drawable.form_data_enabled)
331 formDataPreference.setIcon(R.drawable.form_data_disabled)
334 // Set the custom user agent icon.
335 if (customUserAgentPreference.isEnabled)
336 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
338 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
340 // Set the incognito mode icon.
341 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
342 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
344 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
346 // Set the allow screenshots icon.
347 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
348 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
350 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
352 // Set the EasyList icon.
353 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
354 easyListPreference.setIcon(R.drawable.block_ads_enabled)
356 easyListPreference.setIcon(R.drawable.block_ads_disabled)
358 // Set the EasyPrivacy icon.
359 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
360 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
362 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
364 // Set the Fanboy lists icons.
365 if (fanboyAnnoyanceListEnabled) {
366 // Set the Fanboy annoyance list icon.
367 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
369 // Set the Fanboy social blocking list icon.
370 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
372 // Set the Fanboy annoyance list icon.
373 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
375 // Set the Fanboy social blocking list icon.
376 if (fanboySocialBlockingEnabled)
377 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
379 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
382 // Set the UltraList icon.
383 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
384 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
386 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
388 // Set the UltraPrivacy icon.
389 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
390 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
392 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
394 // Set the block all third-party requests icon.
395 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests), false))
396 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
398 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
400 // Set the Tracking Queries icon.
401 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
402 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
404 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
406 // Set the AMP Redirects icon.
407 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
408 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
410 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
412 // Set the search custom URL icon.
413 if (searchCustomURLPreference.isEnabled)
414 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
416 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
418 // Set the proxy icons according to the theme and status.
419 if (proxyString == ProxyHelper.NONE) { // Proxying is disabled.
420 // Set the main proxy icon to be disabled.
421 proxyPreference.setIcon(R.drawable.proxy_disabled)
423 // Set the custom proxy URL icon to be ghosted.
424 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
425 } else { // Proxying is enabled.
426 // Set the main proxy icon to be enabled.
427 proxyPreference.setIcon(R.drawable.proxy_enabled)
429 // Set the custom proxy URL icon according to its status.
430 if (proxyCustomUrlPreference.isEnabled)
431 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
433 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
436 // Set the full-screen browsing mode icons.
437 if (fullScreenBrowsingMode) { // Full-screen browsing mode is enabled.
438 // Set the full screen browsing mode preference icon.
439 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
441 // Set the hide app bar icon.
442 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
443 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
445 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
446 } else { // Full screen browsing mode is disabled.
448 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
449 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
452 // Set the clear everything icon.
453 if (clearEverything) {
454 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
456 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
459 // Set the clear cookies icon.
460 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
461 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
463 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
465 // Set the clear DOM storage icon.
466 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
467 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
469 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
471 // Set the clear form data icon if the API < 26. It has no effect on newer versions of Android.
472 if (Build.VERSION.SDK_INT < 26) {
473 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
474 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
476 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
479 // Set the clear logcat icon.
480 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
481 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
483 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
485 // Set the clear cache icon.
486 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
487 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
489 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
491 // Set the open intents in new tab icon.
492 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
493 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
495 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
497 // Set the swipe to refresh icon.
498 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
499 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
501 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
503 // Set the download with external app icon.
504 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
505 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
507 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
509 // Set the scroll app bar icon.
510 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
511 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
513 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
515 // Set the bottom app bar icon.
516 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
517 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
519 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
521 // Set the display additional app bar icons icon.
522 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
523 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
525 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
527 // Set the WebView theme icon.
528 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
529 when (webViewThemeEntryNumber) {
530 // The system default WebView theme is selected.
532 // Get the current theme status.
533 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
535 // Set the icon according to the app theme.
536 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
537 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
539 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
542 // The light WebView theme is selected.
545 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
548 // The dark WebView theme is selected.
551 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
554 } else { // The WebView theme preference is disabled.
555 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
558 // Set the wide viewport icon.
559 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
560 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
562 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
564 // Set the display webpage images icon.
565 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
566 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
568 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
571 // The listener should be unregistered when the app is paused.
572 override fun onPause() {
573 // Run the default commands.
576 // Get a handle for the shared preferences.
577 val sharedPreferences = preferenceScreen.sharedPreferences!!
579 // Unregister the shared preference listener.
580 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
583 // The listener should be re-registered when the app is resumed.
584 override fun onResume() {
585 // Run the default commands.
588 // Get a new shared preference change listener.
589 sharedPreferenceChangeListener = getSharedPreferenceChangeListener()
591 // Get a handle for the shared preferences.
592 val sharedPreferences = preferenceScreen.sharedPreferences!!
594 // Re-register the shared preference listener.
595 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
598 private fun getSharedPreferenceChangeListener(): OnSharedPreferenceChangeListener {
599 // Return the shared preference change listener.
600 return OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences, key: String? ->
602 getString(R.string.javascript_key) -> {
603 // Update the icons and the DOM storage preference status.
604 if (sharedPreferences.getBoolean(getString(R.string.javascript_key), false)) { // The JavaScript preference is enabled.
605 // Update the icon for the JavaScript preference.
606 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
608 // Update the status of the DOM storage preference.
609 domStoragePreference.isEnabled = true
611 // Update the icon for the DOM storage preference.
612 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
613 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
615 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
616 } else { // The JavaScript preference is disabled.
617 // Update the icon for the JavaScript preference.
618 javaScriptPreference.setIcon(R.drawable.privacy_mode)
620 // Update the status of the DOM storage preference.
621 domStoragePreference.isEnabled = false
623 // Set the icon for DOM storage preference to be ghosted.
624 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
628 getString(R.string.cookies_key) -> {
630 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
631 cookiesPreference.setIcon(R.drawable.cookies_enabled)
633 cookiesPreference.setIcon(R.drawable.cookies_disabled)
636 getString(R.string.dom_storage_key) -> {
638 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
639 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
641 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
644 getString(R.string.save_form_data_key) -> { // Saved form data can be removed once the minimum API >= 26.
646 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
647 formDataPreference.setIcon(R.drawable.form_data_enabled)
649 formDataPreference.setIcon(R.drawable.form_data_disabled)
652 getString(R.string.user_agent_key) -> {
653 // Get the new user agent name.
654 val newUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
656 // Get the array position for the new user agent name.
657 val newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName)
659 // Get the translated new user agent name.
660 val translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition]
662 // Populate the user agent summary.
663 when (newUserAgentArrayPosition) {
664 SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> {
665 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
666 userAgentPreference.summary = "$translatedNewUserAgentName:\n$defaultUserAgent"
668 // Disable the custom user agent preference.
669 customUserAgentPreference.isEnabled = false
671 // Set the custom user agent preference icon.
672 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
675 SETTINGS_CUSTOM_USER_AGENT -> {
676 // Set the summary text.
677 userAgentPreference.setSummary(R.string.custom_user_agent)
679 // Enable the custom user agent preference.
680 customUserAgentPreference.isEnabled = true
682 // Set the custom user agent preference icon.
683 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
687 // Get the user agent summary from the user agent data array.
688 userAgentPreference.summary = "$translatedNewUserAgentName:\n${userAgentDataArray[newUserAgentArrayPosition]}"
690 // Disable the custom user agent preference.
691 customUserAgentPreference.isEnabled = false
693 // Set the custom user agent preference icon.
694 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
699 getString(R.string.custom_user_agent_key) -> {
700 // Set the new custom user agent as the summary text for the preference.
701 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
704 getString(R.string.incognito_mode_key) -> {
706 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
707 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
709 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
712 getString(R.string.allow_screenshots_key) -> {
714 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
715 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
717 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
719 // Restart Privacy Browser.
720 restartPrivacyBrowser()
723 getString(R.string.easylist_key) -> {
725 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
726 easyListPreference.setIcon(R.drawable.block_ads_enabled)
728 easyListPreference.setIcon(R.drawable.block_ads_disabled)
731 getString(R.string.easyprivacy_key) -> {
733 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
734 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
736 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
739 getString(R.string.fanboys_annoyance_list_key) -> {
740 // Get the current Fanboy settings.
741 val currentFanboyAnnoyanceList = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
742 val currentFanboySocialBlockingList = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
744 // Update the Fanboy icons.
745 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
746 // Update the Fanboy's annoyance list icon.
747 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
749 // Update the Fanboy's social blocking list icon.
750 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
751 } else { // Fanboy's annoyance list is disabled.
752 // Update the Fanboy's annoyance list icon.
753 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
755 // Update the Fanboy's social blocking list icon.
756 if (currentFanboySocialBlockingList)
757 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
759 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
762 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
763 fanboySocialBlockingListPreference.isEnabled = !currentFanboyAnnoyanceList
766 getString(R.string.fanboys_social_blocking_list_key) -> {
768 if (sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true))
769 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
771 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
774 getString(R.string.ultralist_key) -> {
776 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
777 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
779 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
782 getString(R.string.ultraprivacy_key) -> {
784 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
785 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
787 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
790 getString(R.string.block_all_third_party_requests_key) -> {
792 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false)) {
793 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
795 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
799 getString(R.string.tracking_queries_key) -> {
801 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
802 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
804 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
807 getString(R.string.amp_redirects_key) -> {
809 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
810 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
812 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
815 getString(R.string.search_key) -> {
816 // Store the new search string.
817 val newSearchString = sharedPreferences.getString(getString(R.string.search_key), getString(R.string.search_default_value))
819 // Update the search and search custom URL preferences.
820 if (newSearchString == getString(R.string.custom_url_item)) { // A custom URL is selected.
821 // Set the summary text to `R.string.custom_url`, which is translated.
822 searchPreference.setSummary(R.string.custom_url)
824 // Enable the search custom URL preference.
825 searchCustomURLPreference.isEnabled = true
827 // Set the search custom URL preference icon.
828 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
829 } else { // A custom URL is not selected.
830 // Set the summary text to the new search string.
831 searchPreference.summary = newSearchString
833 // Disable the search custom URL Preference.
834 searchCustomURLPreference.isEnabled = false
836 // Set the search custom URL preference icon.
837 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
841 getString(R.string.search_custom_url_key) -> {
842 // Set the new search custom URL as the summary text for the preference.
843 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
846 getString(R.string.proxy_key) -> {
847 // Get the current proxy string.
848 val currentProxyString = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))
850 // Update the proxy preference summary text.
851 proxyPreference.summary = when (currentProxyString) {
852 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
853 ProxyHelper.TOR -> getString(R.string.tor_enabled)
854 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
855 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
856 else -> getString(R.string.no_proxy_enabled)
859 // Update the status of the custom URL preference.
860 proxyCustomUrlPreference.isEnabled = currentProxyString == ProxyHelper.CUSTOM
863 if (currentProxyString == ProxyHelper.NONE) { // Proxying is disabled.
864 // Set the main proxy icon to be disabled
865 proxyPreference.setIcon(R.drawable.proxy_disabled)
867 // Set the custom proxy URL icon to be ghosted.
868 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
869 } else { // Proxying is enabled.
870 // Set the main proxy icon to be enabled.
871 proxyPreference.setIcon(R.drawable.proxy_enabled)
873 /// Set the custom proxy URL icon according to its status.
874 if (proxyCustomUrlPreference.isEnabled)
875 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
877 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
881 getString(R.string.proxy_custom_url_key) -> {
882 // Set the summary text for the proxy custom URL.
883 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
886 getString(R.string.full_screen_browsing_mode_key) -> {
888 if (sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)) { // Full screen browsing is enabled.
889 // Set the full screen browsing mode preference icon.
890 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
892 // Set the hide app bar preference icon.
893 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
894 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
896 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
897 } else { // Full screen browsing is disabled.
899 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
900 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
904 getString(R.string.hide_app_bar_key) -> {
906 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
907 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
909 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
912 getString(R.string.clear_everything_key) -> {
913 // Store the new clear everything status
914 val newClearEverythingBoolean = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
916 // Update the status of the clear and exit preferences.
917 clearCookiesPreference.isEnabled = !newClearEverythingBoolean
918 clearDomStoragePreference.isEnabled = !newClearEverythingBoolean
919 clearFormDataPreference.isEnabled = !newClearEverythingBoolean // Clear form data can be removed once the minimum API >= 26.
920 clearLogcatPreference.isEnabled = !newClearEverythingBoolean
921 clearCachePreference.isEnabled = !newClearEverythingBoolean
923 // Update the clear everything preference icon.
924 if (newClearEverythingBoolean)
925 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
927 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
929 // Update the clear cookies preference icon.
930 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
931 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
933 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
935 // Update the clear dom storage preference icon.
936 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
937 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
939 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
941 // Update the clear form data preference icon if the API < 26.
942 if (Build.VERSION.SDK_INT < 26) {
943 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
944 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
946 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
949 // Update the clear logcat preference icon.
950 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
951 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
953 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
955 // Update the clear cache preference icon.
956 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
957 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
959 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
962 getString(R.string.clear_cookies_key) -> {
964 if (sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
965 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
967 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
970 getString(R.string.clear_dom_storage_key) -> {
972 if (sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
973 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
975 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
978 getString(R.string.clear_form_data_key) -> {
980 if (sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
981 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
983 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
986 getString(R.string.clear_logcat_key) -> {
988 if (sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
989 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
991 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
994 getString(R.string.clear_cache_key) -> {
996 if (sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
997 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
999 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
1002 getString(R.string.homepage_key) -> {
1003 // Set the new homepage URL as the summary text for the Homepage preference.
1004 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
1007 getString(R.string.font_size_key) -> {
1008 // Update the font size summary text.
1009 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
1012 getString(R.string.open_intents_in_new_tab_key) -> {
1014 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
1015 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
1017 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
1020 getString(R.string.swipe_to_refresh_key) -> {
1022 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
1023 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
1025 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
1028 getString(R.string.download_with_external_app_key) -> {
1030 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
1031 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
1033 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
1036 getString(R.string.scroll_app_bar_key) -> {
1038 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
1039 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
1041 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
1044 getString(R.string.bottom_app_bar_key) -> {
1046 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
1047 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
1049 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
1051 // Restart Privacy Browser.
1052 restartPrivacyBrowser()
1055 getString(R.string.display_additional_app_bar_icons_key) -> {
1057 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
1058 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
1060 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
1062 // Restart Privacy Browser.
1063 restartPrivacyBrowser()
1066 getString(R.string.app_theme_key) -> {
1067 // Get the app theme entry number that matches the current app theme.
1068 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
1069 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
1070 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1071 else -> 0 // The system default theme is selected.
1074 // Update the system according to the new theme.
1075 when (appThemeEntryNumber) {
1076 0 -> { // The system default theme is selected.
1077 // Update the theme preference summary text.
1078 appThemePreference.summary = appThemeEntriesStringArray[0]
1080 // Apply the new theme.
1081 if (Build.VERSION.SDK_INT >= 28) { // The system default theme is supported.
1082 // Follow the system default theme.
1083 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
1084 } else { // The system default theme is not supported.
1085 // Follow the battery saver mode.
1086 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
1090 1 -> { // The light theme is selected.
1091 // Update the theme preference summary text.
1092 appThemePreference.summary = appThemeEntriesStringArray[1]
1094 // Apply the new theme.
1095 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1098 2 -> { // The dark theme is selected.
1099 // Update the theme preference summary text.
1100 appThemePreference.summary = appThemeEntriesStringArray[2]
1102 // Apply the new theme.
1103 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
1107 // Enable the WebView theme preference if the app theme is not set to light. Google does not allow light themes to display dark WebViews.
1108 webViewThemePreference.isEnabled = (appThemeEntryNumber != 1)
1110 // Get the webView theme entry number that matches the new WebView theme.
1111 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1112 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1113 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1114 else -> 0 // The system default theme is selected.
1117 // Update the WebView theme icon.
1118 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
1119 when (webViewThemeEntryNumber) {
1120 // The system default WebView theme is selected.
1122 // Get the current theme status.
1123 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1125 // Set the icon according to the app theme.
1126 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1127 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1129 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1132 // The light WebView theme is selected.
1135 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1138 // The dark WebView theme is selected.
1141 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1144 } else { // The WebView theme preference is disabled.
1145 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
1149 getString(R.string.webview_theme_key) -> {
1150 // Get the webView theme entry number that matches the new WebView theme.
1151 val newWebViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1152 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1153 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1154 else -> 0 // The system default theme is selected.
1157 // Update the WebView theme icon.
1158 when (newWebViewThemeEntryNumber) {
1159 // The system default WebView theme is selected.
1161 // Get the current theme status.
1162 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1165 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1166 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1168 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1171 // The light WebView theme is selected.
1174 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1177 // The dark WebView theme is selected.
1180 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1184 // Set the current theme as the summary text for the preference.
1185 webViewThemePreference.summary = webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]
1188 getString(R.string.wide_viewport_key) -> {
1190 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
1191 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
1193 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
1196 getString(R.string.display_webpage_images_key) -> {
1198 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
1199 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
1201 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
1207 private fun restartPrivacyBrowser() {
1208 // Create an intent to restart Privacy Browser.
1209 val restartIntent = requireActivity().parentActivityIntent!!
1211 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1212 restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
1214 // Create a handler to restart the activity.
1215 val restartHandler = Handler(Looper.getMainLooper())
1217 // Create a runnable to restart the activity.
1218 val restartRunnable = Runnable {
1219 // Restart the activity.
1220 startActivity(restartIntent)
1222 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1226 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1227 restartHandler.postDelayed(restartRunnable, 400)