2 * Copyright 2016-2022 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.MainWebViewActivity
41 import com.stoutner.privacybrowser.helpers.ProxyHelper
42 import kotlin.system.exitProcess
44 class SettingsFragment : PreferenceFragmentCompat() {
45 // Declare the class variables.
46 private lateinit var appThemeEntriesStringArray: Array<String>
47 private lateinit var appThemeEntryValuesStringArray: Array<String>
48 private lateinit var defaultUserAgent: String
49 private lateinit var sharedPreferenceChangeListener: OnSharedPreferenceChangeListener
50 private lateinit var translatedUserAgentNamesArray: Array<String>
51 private lateinit var userAgentDataArray: Array<String>
52 private lateinit var userAgentNamesArray: ArrayAdapter<CharSequence>
53 private lateinit var webViewThemeEntriesStringArray: Array<String>
54 private lateinit var webViewThemeEntryValuesStringArray: Array<String>
56 // Define the the class views.
57 private lateinit var javaScriptPreference: Preference
58 private lateinit var cookiesPreference: Preference
59 private lateinit var domStoragePreference: Preference
60 private lateinit var formDataPreference: Preference // The form data preference can be removed once the minimum API >= 26.
61 private lateinit var userAgentPreference: Preference
62 private lateinit var customUserAgentPreference: Preference
63 private lateinit var incognitoModePreference: Preference
64 private lateinit var allowScreenshotsPreference: Preference
65 private lateinit var easyListPreference: Preference
66 private lateinit var easyPrivacyPreference: Preference
67 private lateinit var fanboyAnnoyanceListPreference: Preference
68 private lateinit var fanboySocialBlockingListPreference: Preference
69 private lateinit var ultraListPreference: Preference
70 private lateinit var ultraPrivacyPreference: Preference
71 private lateinit var blockAllThirdPartyRequestsPreference: Preference
72 private lateinit var trackingQueriesPreference: Preference
73 private lateinit var ampRedirectsPreference: Preference
74 private lateinit var searchPreference: Preference
75 private lateinit var searchCustomURLPreference: Preference
76 private lateinit var proxyPreference: Preference
77 private lateinit var proxyCustomUrlPreference: Preference
78 private lateinit var fullScreenBrowsingModePreference: Preference
79 private lateinit var hideAppBarPreference: Preference
80 private lateinit var clearEverythingPreference: Preference
81 private lateinit var clearCookiesPreference: Preference
82 private lateinit var clearDomStoragePreference: Preference
83 private lateinit var clearFormDataPreference: Preference // The clear form data preference can be removed once the minimum API >= 26.
84 private lateinit var clearLogcatPreference: Preference
85 private lateinit var clearCachePreference: Preference
86 private lateinit var homepagePreference: Preference
87 private lateinit var fontSizePreference: Preference
88 private lateinit var openIntentsInNewTabPreference: Preference
89 private lateinit var swipeToRefreshPreference: Preference
90 private lateinit var downloadWithExternalAppPreference: Preference
91 private lateinit var scrollAppBarPreference: Preference
92 private lateinit var bottomAppBarPreference: Preference
93 private lateinit var displayAdditionalAppBarIconsPreference: Preference
94 private lateinit var appThemePreference: Preference
95 private lateinit var webViewThemePreference: Preference
96 private lateinit var wideViewportPreference: Preference
97 private lateinit var displayWebpageImagesPreference: Preference
99 override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
100 // Load the preferences from the XML file.
101 setPreferencesFromResource(R.xml.preferences, rootKey)
103 // Get a handle for the shared preferences.
104 val sharedPreferences = preferenceScreen.sharedPreferences!!
106 // Get handles for the preferences.
107 javaScriptPreference = findPreference(getString(R.string.javascript_key))!!
108 cookiesPreference = findPreference(getString(R.string.cookies_key))!!
109 domStoragePreference = findPreference(getString(R.string.dom_storage_key))!!
110 formDataPreference = findPreference(getString(R.string.save_form_data_key))!! // The form data preference can be removed once the minimum API >= 26.
111 userAgentPreference = findPreference(getString(R.string.user_agent_key))!!
112 customUserAgentPreference = findPreference(getString(R.string.custom_user_agent_key))!!
113 incognitoModePreference = findPreference(getString(R.string.incognito_mode_key))!!
114 allowScreenshotsPreference = findPreference(getString(R.string.allow_screenshots_key))!!
115 easyListPreference = findPreference(getString(R.string.easylist_key))!!
116 easyPrivacyPreference = findPreference(getString(R.string.easyprivacy_key))!!
117 fanboyAnnoyanceListPreference = findPreference(getString(R.string.fanboys_annoyance_list_key))!!
118 fanboySocialBlockingListPreference = findPreference(getString(R.string.fanboys_social_blocking_list_key))!!
119 ultraListPreference = findPreference(getString(R.string.ultralist_key))!!
120 ultraPrivacyPreference = findPreference(getString(R.string.ultraprivacy_key))!!
121 blockAllThirdPartyRequestsPreference = findPreference(getString(R.string.block_all_third_party_requests_key))!!
122 trackingQueriesPreference = findPreference(getString(R.string.tracking_queries_key))!!
123 ampRedirectsPreference = findPreference(getString(R.string.amp_redirects_key))!!
124 searchPreference = findPreference(getString(R.string.search_key))!!
125 searchCustomURLPreference = findPreference(getString(R.string.search_custom_url_key))!!
126 proxyPreference = findPreference(getString(R.string.proxy_key))!!
127 proxyCustomUrlPreference = findPreference(getString(R.string.proxy_custom_url_key))!!
128 fullScreenBrowsingModePreference = findPreference(getString(R.string.full_screen_browsing_mode_key))!!
129 hideAppBarPreference = findPreference(getString(R.string.hide_app_bar_key))!!
130 clearEverythingPreference = findPreference(getString(R.string.clear_everything_key))!!
131 clearCookiesPreference = findPreference(getString(R.string.clear_cookies_key))!!
132 clearDomStoragePreference = findPreference(getString(R.string.clear_dom_storage_key))!!
133 clearFormDataPreference = findPreference(getString(R.string.clear_form_data_key))!! // The clear form data preference can be removed once the minimum API >= 26.
134 clearLogcatPreference = findPreference(getString(R.string.clear_logcat_key))!!
135 clearCachePreference = findPreference(getString(R.string.clear_cache_key))!!
136 homepagePreference = findPreference(getString(R.string.homepage_key))!!
137 fontSizePreference = findPreference(getString(R.string.font_size_key))!!
138 openIntentsInNewTabPreference = findPreference(getString(R.string.open_intents_in_new_tab_key))!!
139 swipeToRefreshPreference = findPreference(getString(R.string.swipe_to_refresh_key))!!
140 downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key))!!
141 scrollAppBarPreference = findPreference(getString(R.string.scroll_app_bar_key))!!
142 bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key))!!
143 displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key))!!
144 appThemePreference = findPreference(getString(R.string.app_theme_key))!!
145 webViewThemePreference = findPreference(getString(R.string.webview_theme_key))!!
146 wideViewportPreference = findPreference(getString(R.string.wide_viewport_key))!!
147 displayWebpageImagesPreference = findPreference(getString(R.string.display_webpage_images_key))!!
149 // Set the preference dependencies.
150 domStoragePreference.dependency = getString(R.string.javascript_key)
151 hideAppBarPreference.dependency = getString(R.string.full_screen_browsing_mode_key)
153 // Get strings from the preferences.
154 val userAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
155 val searchString = sharedPreferences.getString(getString(R.string.search_key), getString(R.string.search_default_value))
156 val proxyString = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))
158 // Get booleans that are used in multiple places from the preferences.
159 val javaScriptEnabled = sharedPreferences.getBoolean(getString(R.string.javascript_key), false)
160 val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
161 val fanboySocialBlockingEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
162 val fullScreenBrowsingMode = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)
163 val clearEverything = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
165 // Remove the form data preferences if the API is >= 26 as they no longer do anything.
166 if (Build.VERSION.SDK_INT >= 26) {
167 // Get handles for the categories.
168 val privacyCategory = findPreference<PreferenceCategory>(getString(R.string.privacy_category_key))!!
169 val clearAndExitCategory = findPreference<PreferenceCategory>(getString(R.string.clear_and_exit_category_key))!!
171 // Remove the form data preferences.
172 privacyCategory.removePreference(formDataPreference)
173 clearAndExitCategory.removePreference(clearFormDataPreference)
176 // Remove the WebView theme preference if the API < 29.
177 if (Build.VERSION.SDK_INT < 29) {
178 // Get a handle for the general category.
179 val generalCategory = findPreference<PreferenceCategory>(getString(R.string.general_category_key))!!
181 // Remove the WebView theme preference.
182 generalCategory.removePreference(webViewThemePreference)
185 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
186 fanboySocialBlockingListPreference.isEnabled = !fanboyAnnoyanceListEnabled
189 // Inflate a WebView to get the default user agent.
190 val inflater = requireActivity().layoutInflater
192 // `@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.
193 @SuppressLint("InflateParams") val bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false)
195 // Get a handle for the bare WebView.
196 val bareWebView = bareWebViewLayout.findViewById<WebView>(R.id.bare_webview)
198 // Get the default user agent.
199 defaultUserAgent = bareWebView.settings.userAgentString
201 // Get the user agent arrays.
202 userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item)
203 translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names)
204 userAgentDataArray = resources.getStringArray(R.array.user_agent_data)
206 // Populate the user agent summary.
207 when (val userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName)) {
208 // The user agent name is not on the canonical list.
209 // 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.
210 MainWebViewActivity.UNRECOGNIZED_USER_AGENT -> userAgentPreference.summary = userAgentName
212 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
213 MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n$defaultUserAgent"
215 // Display the custom user agent.
216 MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT -> userAgentPreference.setSummary(R.string.custom_user_agent)
218 // Get the user agent summary from the user agent data array.
219 else -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n${userAgentDataArray[userAgentArrayPosition]}"
222 // Set the summary text for the custom user agent preference.
223 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
225 // Only enable the custom user agent preference if the user agent is set to custom.
226 customUserAgentPreference.isEnabled = (userAgentPreference.summary == getString(R.string.custom_user_agent))
228 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
229 if (searchString == getString(R.string.custom_url_item)) {
230 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
231 searchPreference.setSummary(R.string.custom_url)
233 // Set the array value as the summary text.
234 searchPreference.summary = searchString
237 // Set the summary text for the search custom URL (the default is `""`).
238 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
240 // Only enable the search custom URL preference if the search is set to a custom URL.
241 searchCustomURLPreference.isEnabled = (searchString == getString(R.string.custom_url_item))
243 // Set the summary text for the proxy preference.
244 proxyPreference.summary = when (proxyString) {
245 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
246 ProxyHelper.TOR -> getString(R.string.tor_enabled)
247 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
248 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
249 else -> getString(R.string.no_proxy_enabled)
252 // Set the summary text for the custom proxy URL.
253 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
255 // Only enable the custom proxy URL if a custom proxy is selected.
256 proxyCustomUrlPreference.isEnabled = proxyString == ProxyHelper.CUSTOM
258 // Set the status of the clear and exit preferences.
259 clearCookiesPreference.isEnabled = !clearEverything
260 clearDomStoragePreference.isEnabled = !clearEverything
261 clearFormDataPreference.isEnabled = !clearEverything // Clear form data can be removed once the minimum API is >= 26.
262 clearLogcatPreference.isEnabled = !clearEverything
263 clearCachePreference.isEnabled = !clearEverything
265 // Set the homepage URL as the summary text for the homepage preference.
266 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
268 // Set the font size as the summary text for the preference.
269 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
271 // Get the app theme string arrays.
272 appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries)
273 appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values)
275 // Get the app theme entry number that matches the current app theme.
276 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
277 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
278 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
279 else -> 0 // The system default theme is selected.
282 // Set the current theme as the summary text for the preference.
283 appThemePreference.summary = appThemeEntriesStringArray[appThemeEntryNumber]
285 // Enable the WebView theme preference if the app theme is not set to light. Google does not allow light themes to display dark WebViews.
286 webViewThemePreference.isEnabled = (appThemeEntryNumber != 1)
288 // Get the WebView theme string arrays.
289 webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries)
290 webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
292 // Get the WebView theme entry number that matches the current WebView theme.
293 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
294 webViewThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
295 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
296 else -> 0 // The system default theme is selected.
299 // Set the current theme as the summary text for the preference.
300 webViewThemePreference.summary = webViewThemeEntriesStringArray[webViewThemeEntryNumber]
302 // Set the JavaScript icon.
303 if (javaScriptEnabled)
304 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
306 javaScriptPreference.setIcon(R.drawable.privacy_mode)
308 // Set the cookies icon.
309 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
310 cookiesPreference.setIcon(R.drawable.cookies_enabled)
312 cookiesPreference.setIcon(R.drawable.cookies_disabled)
314 // Set the DOM storage icon.
315 if (javaScriptEnabled) { // JavaScript is enabled.
316 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false)) // DOM storage is enabled.
317 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
318 else // DOM storage is disabled.
319 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
320 } else { // JavaScript is disabled. DOM storage should be ghosted.
321 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
324 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
325 if (Build.VERSION.SDK_INT < 26) {
326 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
327 formDataPreference.setIcon(R.drawable.form_data_enabled)
329 formDataPreference.setIcon(R.drawable.form_data_disabled)
332 // Set the custom user agent icon.
333 if (customUserAgentPreference.isEnabled)
334 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
336 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
338 // Set the incognito mode icon.
339 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
340 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
342 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
344 // Set the allow screenshots icon.
345 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
346 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
348 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
350 // Set the EasyList icon.
351 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
352 easyListPreference.setIcon(R.drawable.block_ads_enabled)
354 easyListPreference.setIcon(R.drawable.block_ads_disabled)
356 // Set the EasyPrivacy icon.
357 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
358 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
360 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
362 // Set the Fanboy lists icons.
363 if (fanboyAnnoyanceListEnabled) {
364 // Set the Fanboy annoyance list icon.
365 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
367 // Set the Fanboy social blocking list icon.
368 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
370 // Set the Fanboy annoyance list icon.
371 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
373 // Set the Fanboy social blocking list icon.
374 if (fanboySocialBlockingEnabled)
375 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
377 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
380 // Set the UltraList icon.
381 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
382 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
384 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
386 // Set the UltraPrivacy icon.
387 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
388 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
390 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
392 // Set the block all third-party requests icon.
393 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests), false))
394 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
396 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
398 // Set the Tracking Queries icon.
399 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
400 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
402 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
404 // Set the AMP Redirects icon.
405 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
406 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
408 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
410 // Set the search custom URL icon.
411 if (searchCustomURLPreference.isEnabled)
412 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
414 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
416 // Set the proxy icons according to the theme and status.
417 if (proxyString == ProxyHelper.NONE) { // Proxying is disabled.
418 // Set the main proxy icon to be disabled.
419 proxyPreference.setIcon(R.drawable.proxy_disabled)
421 // Set the custom proxy URL icon to be ghosted.
422 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
423 } else { // Proxying is enabled.
424 // Set the main proxy icon to be enabled.
425 proxyPreference.setIcon(R.drawable.proxy_enabled)
427 // Set the custom proxy URL icon according to its status.
428 if (proxyCustomUrlPreference.isEnabled)
429 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
431 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
434 // Set the full-screen browsing mode icons.
435 if (fullScreenBrowsingMode) { // Full-screen browsing mode is enabled.
436 // Set the full screen browsing mode preference icon.
437 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
439 // Set the hide app bar icon.
440 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
441 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
443 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
444 } else { // Full screen browsing mode is disabled.
446 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
447 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
450 // Set the clear everything icon.
451 if (clearEverything) {
452 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
454 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
457 // Set the clear cookies icon.
458 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
459 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
461 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
463 // Set the clear DOM storage icon.
464 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
465 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
467 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
469 // Set the clear form data icon if the API < 26. It has no effect on newer versions of Android.
470 if (Build.VERSION.SDK_INT < 26) {
471 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
472 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
474 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
477 // Set the clear logcat icon.
478 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
479 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
481 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
483 // Set the clear cache icon.
484 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
485 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
487 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
489 // Set the open intents in new tab icon.
490 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
491 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
493 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
495 // Set the swipe to refresh icon.
496 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
497 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
499 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
501 // Set the download with external app icon.
502 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
503 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
505 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
507 // Set the scroll app bar icon.
508 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
509 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
511 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
513 // Set the bottom app bar icon.
514 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
515 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
517 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
519 // Set the display additional app bar icons icon.
520 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
521 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
523 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
525 // Set the WebView theme icon.
526 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
527 when (webViewThemeEntryNumber) {
528 // The system default WebView theme is selected.
530 // Get the current theme status.
531 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
533 // Set the icon according to the app theme.
534 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
535 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
537 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
540 // The light WebView theme is selected.
543 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
546 // The dark WebView theme is selected.
549 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
552 } else { // The WebView theme preference is disabled.
553 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
556 // Set the wide viewport icon.
557 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
558 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
560 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
562 // Set the display webpage images icon.
563 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
564 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
566 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
569 // The listener should be unregistered when the app is paused.
570 override fun onPause() {
571 // Run the default commands.
574 // Get a handle for the shared preferences.
575 val sharedPreferences = preferenceScreen.sharedPreferences!!
577 // Unregister the shared preference listener.
578 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
581 // The listener should be re-registered when the app is resumed.
582 override fun onResume() {
583 // Run the default commands.
586 // Get a new shared preference change listener.
587 sharedPreferenceChangeListener = getSharedPreferenceChangeListener()
589 // Get a handle for the shared preferences.
590 val sharedPreferences = preferenceScreen.sharedPreferences!!
592 // Re-register the shared preference listener.
593 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
596 private fun getSharedPreferenceChangeListener(): OnSharedPreferenceChangeListener {
597 // Return the shared preference change listener.
598 return OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences, key: String? ->
600 getString(R.string.javascript_key) -> {
601 // Update the icons and the DOM storage preference status.
602 if (sharedPreferences.getBoolean(getString(R.string.javascript_key), false)) { // The JavaScript preference is enabled.
603 // Update the icon for the JavaScript preference.
604 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
606 // Update the status of the DOM storage preference.
607 domStoragePreference.isEnabled = true
609 // Update the icon for the DOM storage preference.
610 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
611 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
613 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
614 } else { // The JavaScript preference is disabled.
615 // Update the icon for the JavaScript preference.
616 javaScriptPreference.setIcon(R.drawable.privacy_mode)
618 // Update the status of the DOM storage preference.
619 domStoragePreference.isEnabled = false
621 // Set the icon for DOM storage preference to be ghosted.
622 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
626 getString(R.string.cookies_key) -> {
628 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
629 cookiesPreference.setIcon(R.drawable.cookies_enabled)
631 cookiesPreference.setIcon(R.drawable.cookies_disabled)
634 getString(R.string.dom_storage_key) -> {
636 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
637 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
639 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
642 getString(R.string.save_form_data_key) -> { // Saved form data can be removed once the minimum API >= 26.
644 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
645 formDataPreference.setIcon(R.drawable.form_data_enabled)
647 formDataPreference.setIcon(R.drawable.form_data_disabled)
650 getString(R.string.user_agent_key) -> {
651 // Get the new user agent name.
652 val newUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
654 // Get the array position for the new user agent name.
655 val newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName)
657 // Get the translated new user agent name.
658 val translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition]
660 // Populate the user agent summary.
661 when (newUserAgentArrayPosition) {
662 MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> {
663 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
664 userAgentPreference.summary = "$translatedNewUserAgentName:\n$defaultUserAgent"
666 // Disable the custom user agent preference.
667 customUserAgentPreference.isEnabled = false
669 // Set the custom user agent preference icon.
670 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
673 MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT -> {
674 // Set the summary text.
675 userAgentPreference.setSummary(R.string.custom_user_agent)
677 // Enable the custom user agent preference.
678 customUserAgentPreference.isEnabled = true
680 // Set the custom user agent preference icon.
681 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
685 // Get the user agent summary from the user agent data array.
686 userAgentPreference.summary = "$translatedNewUserAgentName:\n${userAgentDataArray[newUserAgentArrayPosition]}"
688 // Disable the custom user agent preference.
689 customUserAgentPreference.isEnabled = false
691 // Set the custom user agent preference icon.
692 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
697 getString(R.string.custom_user_agent_key) -> {
698 // Set the new custom user agent as the summary text for the preference.
699 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
702 getString(R.string.incognito_mode_key) -> {
704 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
705 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
707 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
710 getString(R.string.allow_screenshots_key) -> {
712 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
713 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
715 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
717 // Restart Privacy Browser.
718 restartPrivacyBrowser()
721 getString(R.string.easylist_key) -> {
723 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
724 easyListPreference.setIcon(R.drawable.block_ads_enabled)
726 easyListPreference.setIcon(R.drawable.block_ads_disabled)
729 getString(R.string.easyprivacy_key) -> {
731 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
732 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
734 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
737 getString(R.string.fanboys_annoyance_list_key) -> {
738 // Get the current Fanboy settings.
739 val currentFanboyAnnoyanceList = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
740 val currentFanboySocialBlockingList = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
742 // Update the Fanboy icons.
743 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
744 // Update the Fanboy's annoyance list icon.
745 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
747 // Update the Fanboy's social blocking list icon.
748 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
749 } else { // Fanboy's annoyance list is disabled.
750 // Update the Fanboy's annoyance list icon.
751 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
753 // Update the Fanboy's social blocking list icon.
754 if (currentFanboySocialBlockingList)
755 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
757 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
760 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
761 fanboySocialBlockingListPreference.isEnabled = !currentFanboyAnnoyanceList
764 getString(R.string.fanboys_social_blocking_list_key) -> {
766 if (sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true))
767 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
769 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
772 getString(R.string.ultralist_key) -> {
774 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
775 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
777 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
780 getString(R.string.ultraprivacy_key) -> {
782 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
783 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
785 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
788 getString(R.string.block_all_third_party_requests_key) -> {
790 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false)) {
791 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
793 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
797 getString(R.string.tracking_queries_key) -> {
799 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
800 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
802 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
805 getString(R.string.amp_redirects_key) -> {
807 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
808 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
810 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
813 getString(R.string.search_key) -> {
814 // Store the new search string.
815 val newSearchString = sharedPreferences.getString(getString(R.string.search_key), getString(R.string.search_default_value))
817 // Update the search and search custom URL preferences.
818 if (newSearchString == getString(R.string.custom_url_item)) { // A custom URL is selected.
819 // Set the summary text to `R.string.custom_url`, which is translated.
820 searchPreference.setSummary(R.string.custom_url)
822 // Enable the search custom URL preference.
823 searchCustomURLPreference.isEnabled = true
825 // Set the search custom URL preference icon.
826 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
827 } else { // A custom URL is not selected.
828 // Set the summary text to the new search string.
829 searchPreference.summary = newSearchString
831 // Disable the search custom URL Preference.
832 searchCustomURLPreference.isEnabled = false
834 // Set the search custom URL preference icon.
835 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
839 getString(R.string.search_custom_url_key) -> {
840 // Set the new search custom URL as the summary text for the preference.
841 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
844 getString(R.string.proxy_key) -> {
845 // Get the current proxy string.
846 val currentProxyString = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))
848 // Update the proxy preference summary text.
849 proxyPreference.summary = when (currentProxyString) {
850 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
851 ProxyHelper.TOR -> getString(R.string.tor_enabled)
852 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
853 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
854 else -> getString(R.string.no_proxy_enabled)
857 // Update the status of the custom URL preference.
858 proxyCustomUrlPreference.isEnabled = currentProxyString == ProxyHelper.CUSTOM
861 if (currentProxyString == ProxyHelper.NONE) { // Proxying is disabled.
862 // Set the main proxy icon to be disabled
863 proxyPreference.setIcon(R.drawable.proxy_disabled)
865 // Set the custom proxy URL icon to be ghosted.
866 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
867 } else { // Proxying is enabled.
868 // Set the main proxy icon to be enabled.
869 proxyPreference.setIcon(R.drawable.proxy_enabled)
871 /// Set the custom proxy URL icon according to its status.
872 if (proxyCustomUrlPreference.isEnabled)
873 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
875 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
879 getString(R.string.proxy_custom_url_key) -> {
880 // Set the summary text for the proxy custom URL.
881 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
884 getString(R.string.full_screen_browsing_mode_key) -> {
886 if (sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)) { // Full screen browsing is enabled.
887 // Set the full screen browsing mode preference icon.
888 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
890 // Set the hide app bar preference icon.
891 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
892 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
894 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
895 } else { // Full screen browsing is disabled.
897 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
898 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
902 getString(R.string.hide_app_bar_key) -> {
904 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
905 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
907 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
910 getString(R.string.clear_everything_key) -> {
911 // Store the new clear everything status
912 val newClearEverythingBoolean = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
914 // Update the status of the clear and exit preferences.
915 clearCookiesPreference.isEnabled = !newClearEverythingBoolean
916 clearDomStoragePreference.isEnabled = !newClearEverythingBoolean
917 clearFormDataPreference.isEnabled = !newClearEverythingBoolean // Clear form data can be removed once the minimum API >= 26.
918 clearLogcatPreference.isEnabled = !newClearEverythingBoolean
919 clearCachePreference.isEnabled = !newClearEverythingBoolean
921 // Update the clear everything preference icon.
922 if (newClearEverythingBoolean)
923 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
925 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
927 // Update the clear cookies preference icon.
928 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
929 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
931 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
933 // Update the clear dom storage preference icon.
934 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
935 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
937 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
939 // Update the clear form data preference icon if the API < 26.
940 if (Build.VERSION.SDK_INT < 26) {
941 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
942 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
944 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
947 // Update the clear logcat preference icon.
948 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
949 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
951 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
953 // Update the clear cache preference icon.
954 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
955 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
957 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
960 getString(R.string.clear_cookies_key) -> {
962 if (sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
963 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
965 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
968 getString(R.string.clear_dom_storage_key) -> {
970 if (sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
971 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
973 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
976 getString(R.string.clear_form_data_key) -> {
978 if (sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
979 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
981 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
984 getString(R.string.clear_logcat_key) -> {
986 if (sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
987 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
989 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
992 getString(R.string.clear_cache_key) -> {
994 if (sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
995 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
997 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
1000 getString(R.string.homepage_key) -> {
1001 // Set the new homepage URL as the summary text for the Homepage preference.
1002 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
1005 getString(R.string.font_size_key) -> {
1006 // Update the font size summary text.
1007 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
1010 getString(R.string.open_intents_in_new_tab_key) -> {
1012 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
1013 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
1015 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
1018 getString(R.string.swipe_to_refresh_key) -> {
1020 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
1021 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
1023 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
1026 getString(R.string.download_with_external_app_key) -> {
1028 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
1029 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
1031 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
1034 getString(R.string.scroll_app_bar_key) -> {
1036 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
1037 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
1039 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
1042 getString(R.string.bottom_app_bar_key) -> {
1044 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
1045 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
1047 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
1049 // Restart Privacy Browser.
1050 restartPrivacyBrowser()
1053 getString(R.string.display_additional_app_bar_icons_key) -> {
1055 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
1056 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
1058 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
1061 getString(R.string.app_theme_key) -> {
1062 // Get the app theme entry number that matches the current app theme.
1063 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
1064 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
1065 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1066 else -> 0 // The system default theme is selected.
1069 // Update the system according to the new theme.
1070 when (appThemeEntryNumber) {
1071 0 -> { // The system default theme is selected.
1072 // Update the theme preference summary text.
1073 appThemePreference.summary = appThemeEntriesStringArray[0]
1075 // Apply the new theme.
1076 if (Build.VERSION.SDK_INT >= 28) { // The system default theme is supported.
1077 // Follow the system default theme.
1078 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
1079 } else { // The system default theme is not supported.
1080 // Follow the battery saver mode.
1081 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
1085 1 -> { // The light theme is selected.
1086 // Update the theme preference summary text.
1087 appThemePreference.summary = appThemeEntriesStringArray[1]
1089 // Apply the new theme.
1090 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1093 2 -> { // The dark theme is selected.
1094 // Update the theme preference summary text.
1095 appThemePreference.summary = appThemeEntriesStringArray[2]
1097 // Apply the new theme.
1098 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
1102 // Enable the WebView theme preference if the app theme is not set to light. Google does not allow light themes to display dark WebViews.
1103 webViewThemePreference.isEnabled = (appThemeEntryNumber != 1)
1105 // Get the webView theme entry number that matches the new WebView theme.
1106 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1107 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1108 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1109 else -> 0 // The system default theme is selected.
1112 // Update the WebView theme icon.
1113 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
1114 when (webViewThemeEntryNumber) {
1115 // The system default WebView theme is selected.
1117 // Get the current theme status.
1118 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1120 // Set the icon according to the app theme.
1121 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1122 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1124 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1127 // The light WebView theme is selected.
1130 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1133 // The dark WebView theme is selected.
1136 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1139 } else { // The WebView theme preference is disabled.
1140 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
1144 getString(R.string.webview_theme_key) -> {
1145 // Get the webView theme entry number that matches the new WebView theme.
1146 val newWebViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1147 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1148 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1149 else -> 0 // The system default theme is selected.
1152 // Update the WebView theme icon.
1153 when (newWebViewThemeEntryNumber) {
1154 // The system default WebView theme is selected.
1156 // Get the current theme status.
1157 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1160 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1161 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1163 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1166 // The light WebView theme is selected.
1169 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1172 // The dark WebView theme is selected.
1175 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1179 // Set the current theme as the summary text for the preference.
1180 webViewThemePreference.summary = webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]
1183 getString(R.string.wide_viewport_key) -> {
1185 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
1186 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
1188 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
1191 getString(R.string.display_webpage_images_key) -> {
1193 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
1194 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
1196 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
1202 private fun restartPrivacyBrowser() {
1203 // Create an intent to restart Privacy Browser.
1204 val restartIntent = requireActivity().parentActivityIntent!!
1206 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1207 restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
1209 // Create a handler to restart the activity.
1210 val restartHandler = Handler(Looper.getMainLooper())
1212 // Create a runnable to restart the activity.
1213 val restartRunnable = Runnable {
1214 // Restart the activity.
1215 startActivity(restartIntent)
1217 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1221 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1222 restartHandler.postDelayed(restartRunnable, 400)