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 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
177 fanboySocialBlockingListPreference.isEnabled = !fanboyAnnoyanceListEnabled
180 // Inflate a WebView to get the default user agent.
181 val inflater = requireActivity().layoutInflater
183 // `@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.
184 @SuppressLint("InflateParams") val bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false)
186 // Get a handle for the bare WebView.
187 val bareWebView = bareWebViewLayout.findViewById<WebView>(R.id.bare_webview)
189 // Get the default user agent.
190 defaultUserAgent = bareWebView.settings.userAgentString
192 // Get the user agent arrays.
193 userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item)
194 translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names)
195 userAgentDataArray = resources.getStringArray(R.array.user_agent_data)
197 // Populate the user agent summary.
198 when (val userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName)) {
199 // The user agent name is not on the canonical list.
200 // 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.
201 MainWebViewActivity.UNRECOGNIZED_USER_AGENT -> userAgentPreference.summary = userAgentName
203 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
204 MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n$defaultUserAgent"
206 // Display the custom user agent.
207 MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT -> userAgentPreference.setSummary(R.string.custom_user_agent)
209 // Get the user agent summary from the user agent data array.
210 else -> userAgentPreference.summary = "${translatedUserAgentNamesArray[userAgentArrayPosition]}:\n${userAgentDataArray[userAgentArrayPosition]}"
213 // Set the summary text for the custom user agent preference.
214 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
216 // Only enable the custom user agent preference if the user agent is set to custom.
217 customUserAgentPreference.isEnabled = (userAgentPreference.summary == getString(R.string.custom_user_agent))
219 // Set the search URL as the summary text for the search preference when the preference screen is loaded.
220 if (searchString == getString(R.string.custom_url_item)) {
221 // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
222 searchPreference.setSummary(R.string.custom_url)
224 // Set the array value as the summary text.
225 searchPreference.summary = searchString
228 // Set the summary text for the search custom URL (the default is `""`).
229 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
231 // Only enable the search custom URL preference if the search is set to a custom URL.
232 searchCustomURLPreference.isEnabled = (searchString == getString(R.string.custom_url_item))
234 // Set the summary text for the proxy preference.
235 proxyPreference.summary = when (proxyString) {
236 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
237 ProxyHelper.TOR -> getString(R.string.tor_enabled)
238 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
239 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
240 else -> getString(R.string.no_proxy_enabled)
243 // Set the summary text for the custom proxy URL.
244 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
246 // Only enable the custom proxy URL if a custom proxy is selected.
247 proxyCustomUrlPreference.isEnabled = proxyString == ProxyHelper.CUSTOM
249 // Set the status of the clear and exit preferences.
250 clearCookiesPreference.isEnabled = !clearEverything
251 clearDomStoragePreference.isEnabled = !clearEverything
252 clearFormDataPreference.isEnabled = !clearEverything // Clear form data can be removed once the minimum API is >= 26.
253 clearLogcatPreference.isEnabled = !clearEverything
254 clearCachePreference.isEnabled = !clearEverything
256 // Set the homepage URL as the summary text for the homepage preference.
257 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
259 // Set the font size as the summary text for the preference.
260 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
262 // Get the app theme string arrays.
263 appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries)
264 appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values)
266 // Get the app theme entry number that matches the current app theme.
267 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
268 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
269 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
270 else -> 0 // The system default theme is selected.
273 // Set the current theme as the summary text for the preference.
274 appThemePreference.summary = appThemeEntriesStringArray[appThemeEntryNumber]
276 // Enable the WebView theme preference if the API < 33 or the app theme is not set to light. Google no longer allows light themes to display dark WebViews.
277 webViewThemePreference.isEnabled = ((Build.VERSION.SDK_INT < 33) || (appThemeEntryNumber != 1))
279 // Get the WebView theme string arrays.
280 webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries)
281 webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values)
283 // Get the WebView theme entry number that matches the current WebView theme.
284 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
285 webViewThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
286 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
287 else -> 0 // The system default theme is selected.
290 // Set the current theme as the summary text for the preference.
291 webViewThemePreference.summary = webViewThemeEntriesStringArray[webViewThemeEntryNumber]
293 // Set the JavaScript icon.
294 if (javaScriptEnabled)
295 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
297 javaScriptPreference.setIcon(R.drawable.privacy_mode)
299 // Set the cookies icon.
300 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
301 cookiesPreference.setIcon(R.drawable.cookies_enabled)
303 cookiesPreference.setIcon(R.drawable.cookies_disabled)
305 // Set the DOM storage icon.
306 if (javaScriptEnabled) { // JavaScript is enabled.
307 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false)) // DOM storage is enabled.
308 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
309 else // DOM storage is disabled.
310 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
311 } else { // JavaScript is disabled. DOM storage should be ghosted.
312 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
315 // Set the save form data icon if API < 26. Save form data has no effect on API >= 26.
316 if (Build.VERSION.SDK_INT < 26) {
317 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
318 formDataPreference.setIcon(R.drawable.form_data_enabled)
320 formDataPreference.setIcon(R.drawable.form_data_disabled)
323 // Set the custom user agent icon.
324 if (customUserAgentPreference.isEnabled)
325 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
327 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
329 // Set the incognito mode icon.
330 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
331 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
333 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
335 // Set the allow screenshots icon.
336 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
337 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
339 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
341 // Set the EasyList icon.
342 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
343 easyListPreference.setIcon(R.drawable.block_ads_enabled)
345 easyListPreference.setIcon(R.drawable.block_ads_disabled)
347 // Set the EasyPrivacy icon.
348 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
349 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
351 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
353 // Set the Fanboy lists icons.
354 if (fanboyAnnoyanceListEnabled) {
355 // Set the Fanboy annoyance list icon.
356 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
358 // Set the Fanboy social blocking list icon.
359 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
361 // Set the Fanboy annoyance list icon.
362 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
364 // Set the Fanboy social blocking list icon.
365 if (fanboySocialBlockingEnabled)
366 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
368 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
371 // Set the UltraList icon.
372 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
373 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
375 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
377 // Set the UltraPrivacy icon.
378 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
379 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
381 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
383 // Set the block all third-party requests icon.
384 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests), false))
385 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
387 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
389 // Set the Tracking Queries icon.
390 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
391 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
393 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
395 // Set the AMP Redirects icon.
396 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
397 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
399 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
401 // Set the search custom URL icon.
402 if (searchCustomURLPreference.isEnabled)
403 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
405 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
407 // Set the proxy icons according to the theme and status.
408 if (proxyString == ProxyHelper.NONE) { // Proxying is disabled.
409 // Set the main proxy icon to be disabled.
410 proxyPreference.setIcon(R.drawable.proxy_disabled)
412 // Set the custom proxy URL icon to be ghosted.
413 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
414 } else { // Proxying is enabled.
415 // Set the main proxy icon to be enabled.
416 proxyPreference.setIcon(R.drawable.proxy_enabled)
418 // Set the custom proxy URL icon according to its status.
419 if (proxyCustomUrlPreference.isEnabled)
420 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
422 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
425 // Set the full-screen browsing mode icons.
426 if (fullScreenBrowsingMode) { // Full-screen browsing mode is enabled.
427 // Set the full screen browsing mode preference icon.
428 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
430 // Set the hide app bar icon.
431 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
432 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
434 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
435 } else { // Full screen browsing mode is disabled.
437 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
438 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
441 // Set the clear everything icon.
442 if (clearEverything) {
443 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
445 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
448 // Set the clear cookies icon.
449 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
450 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
452 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
454 // Set the clear DOM storage icon.
455 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
456 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
458 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
460 // Set the clear form data icon if the API < 26. It has no effect on newer versions of Android.
461 if (Build.VERSION.SDK_INT < 26) {
462 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
463 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
465 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
468 // Set the clear logcat icon.
469 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
470 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
472 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
474 // Set the clear cache icon.
475 if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
476 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
478 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
480 // Set the open intents in new tab icon.
481 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
482 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
484 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
486 // Set the swipe to refresh icon.
487 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
488 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
490 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
492 // Set the download with external app icon.
493 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
494 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
496 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
498 // Set the scroll app bar icon.
499 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
500 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
502 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
504 // Set the bottom app bar icon.
505 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
506 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
508 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
510 // Set the display additional app bar icons icon.
511 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
512 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
514 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
516 // Set the WebView theme icon.
517 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
518 when (webViewThemeEntryNumber) {
519 // The system default WebView theme is selected.
521 // Get the current theme status.
522 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
524 // Set the icon according to the app theme.
525 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
526 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
528 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
531 // The light WebView theme is selected.
534 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
537 // The dark WebView theme is selected.
540 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
543 } else { // The WebView theme preference is disabled.
544 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
547 // Set the wide viewport icon.
548 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
549 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
551 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
553 // Set the display webpage images icon.
554 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
555 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
557 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
560 // The listener should be unregistered when the app is paused.
561 override fun onPause() {
562 // Run the default commands.
565 // Get a handle for the shared preferences.
566 val sharedPreferences = preferenceScreen.sharedPreferences!!
568 // Unregister the shared preference listener.
569 sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
572 // The listener should be re-registered when the app is resumed.
573 override fun onResume() {
574 // Run the default commands.
577 // Get a new shared preference change listener.
578 sharedPreferenceChangeListener = getSharedPreferenceChangeListener()
580 // Get a handle for the shared preferences.
581 val sharedPreferences = preferenceScreen.sharedPreferences!!
583 // Re-register the shared preference listener.
584 sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
587 private fun getSharedPreferenceChangeListener(): OnSharedPreferenceChangeListener {
588 // Return the shared preference change listener.
589 return OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences, key: String? ->
591 getString(R.string.javascript_key) -> {
592 // Update the icons and the DOM storage preference status.
593 if (sharedPreferences.getBoolean(getString(R.string.javascript_key), false)) { // The JavaScript preference is enabled.
594 // Update the icon for the JavaScript preference.
595 javaScriptPreference.setIcon(R.drawable.javascript_enabled)
597 // Update the status of the DOM storage preference.
598 domStoragePreference.isEnabled = true
600 // Update the icon for the DOM storage preference.
601 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
602 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
604 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
605 } else { // The JavaScript preference is disabled.
606 // Update the icon for the JavaScript preference.
607 javaScriptPreference.setIcon(R.drawable.privacy_mode)
609 // Update the status of the DOM storage preference.
610 domStoragePreference.isEnabled = false
612 // Set the icon for DOM storage preference to be ghosted.
613 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted)
617 getString(R.string.cookies_key) -> {
619 if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false))
620 cookiesPreference.setIcon(R.drawable.cookies_enabled)
622 cookiesPreference.setIcon(R.drawable.cookies_disabled)
625 getString(R.string.dom_storage_key) -> {
627 if (sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false))
628 domStoragePreference.setIcon(R.drawable.dom_storage_enabled)
630 domStoragePreference.setIcon(R.drawable.dom_storage_disabled)
633 getString(R.string.save_form_data_key) -> { // Saved form data can be removed once the minimum API >= 26.
635 if (sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false))
636 formDataPreference.setIcon(R.drawable.form_data_enabled)
638 formDataPreference.setIcon(R.drawable.form_data_disabled)
641 getString(R.string.user_agent_key) -> {
642 // Get the new user agent name.
643 val newUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
645 // Get the array position for the new user agent name.
646 val newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName)
648 // Get the translated new user agent name.
649 val translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition]
651 // Populate the user agent summary.
652 when (newUserAgentArrayPosition) {
653 MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> {
654 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
655 userAgentPreference.summary = "$translatedNewUserAgentName:\n$defaultUserAgent"
657 // Disable the custom user agent preference.
658 customUserAgentPreference.isEnabled = false
660 // Set the custom user agent preference icon.
661 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
664 MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT -> {
665 // Set the summary text.
666 userAgentPreference.setSummary(R.string.custom_user_agent)
668 // Enable the custom user agent preference.
669 customUserAgentPreference.isEnabled = true
671 // Set the custom user agent preference icon.
672 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled)
676 // Get the user agent summary from the user agent data array.
677 userAgentPreference.summary = "$translatedNewUserAgentName:\n${userAgentDataArray[newUserAgentArrayPosition]}"
679 // Disable the custom user agent preference.
680 customUserAgentPreference.isEnabled = false
682 // Set the custom user agent preference icon.
683 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted)
688 getString(R.string.custom_user_agent_key) -> {
689 // Set the new custom user agent as the summary text for the preference.
690 customUserAgentPreference.summary = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value))
693 getString(R.string.incognito_mode_key) -> {
695 if (sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false))
696 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled)
698 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled)
701 getString(R.string.allow_screenshots_key) -> {
703 if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false))
704 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled)
706 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled)
708 // Restart Privacy Browser.
709 restartPrivacyBrowser()
712 getString(R.string.easylist_key) -> {
714 if (sharedPreferences.getBoolean(getString(R.string.easylist_key), true))
715 easyListPreference.setIcon(R.drawable.block_ads_enabled)
717 easyListPreference.setIcon(R.drawable.block_ads_disabled)
720 getString(R.string.easyprivacy_key) -> {
722 if (sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true))
723 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
725 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
728 getString(R.string.fanboys_annoyance_list_key) -> {
729 // Get the current Fanboy settings.
730 val currentFanboyAnnoyanceList = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true)
731 val currentFanboySocialBlockingList = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true)
733 // Update the Fanboy icons.
734 if (currentFanboyAnnoyanceList) { // Fanboy's annoyance list is enabled.
735 // Update the Fanboy's annoyance list icon.
736 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled)
738 // Update the Fanboy's social blocking list icon.
739 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted)
740 } else { // Fanboy's annoyance list is disabled.
741 // Update the Fanboy's annoyance list icon.
742 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled)
744 // Update the Fanboy's social blocking list icon.
745 if (currentFanboySocialBlockingList)
746 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
748 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
751 // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
752 fanboySocialBlockingListPreference.isEnabled = !currentFanboyAnnoyanceList
755 getString(R.string.fanboys_social_blocking_list_key) -> {
757 if (sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true))
758 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled)
760 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled)
763 getString(R.string.ultralist_key) -> {
765 if (sharedPreferences.getBoolean(getString(R.string.ultralist_key), true))
766 ultraListPreference.setIcon(R.drawable.block_ads_enabled)
768 ultraListPreference.setIcon(R.drawable.block_ads_disabled)
771 getString(R.string.ultraprivacy_key) -> {
773 if (sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true))
774 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled)
776 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled)
779 getString(R.string.block_all_third_party_requests_key) -> {
781 if (sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false)) {
782 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled)
784 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled)
788 getString(R.string.tracking_queries_key) -> {
790 if (sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true))
791 trackingQueriesPreference.setIcon(R.drawable.modify_url_enabled)
793 trackingQueriesPreference.setIcon(R.drawable.modify_url_disabled)
796 getString(R.string.amp_redirects_key) -> {
798 if (sharedPreferences.getBoolean(getString(R.string.amp_redirects_key), true))
799 ampRedirectsPreference.setIcon(R.drawable.modify_url_enabled)
801 ampRedirectsPreference.setIcon(R.drawable.modify_url_disabled)
804 getString(R.string.search_key) -> {
805 // Store the new search string.
806 val newSearchString = sharedPreferences.getString(getString(R.string.search_key), getString(R.string.search_default_value))
808 // Update the search and search custom URL preferences.
809 if (newSearchString == getString(R.string.custom_url_item)) { // A custom URL is selected.
810 // Set the summary text to `R.string.custom_url`, which is translated.
811 searchPreference.setSummary(R.string.custom_url)
813 // Enable the search custom URL preference.
814 searchCustomURLPreference.isEnabled = true
816 // Set the search custom URL preference icon.
817 searchCustomURLPreference.setIcon(R.drawable.search_custom_enabled)
818 } else { // A custom URL is not selected.
819 // Set the summary text to the new search string.
820 searchPreference.summary = newSearchString
822 // Disable the search custom URL Preference.
823 searchCustomURLPreference.isEnabled = false
825 // Set the search custom URL preference icon.
826 searchCustomURLPreference.setIcon(R.drawable.search_custom_ghosted)
830 getString(R.string.search_custom_url_key) -> {
831 // Set the new search custom URL as the summary text for the preference.
832 searchCustomURLPreference.summary = sharedPreferences.getString(getString(R.string.search_custom_url_key), getString(R.string.search_custom_url_default_value))
835 getString(R.string.proxy_key) -> {
836 // Get the current proxy string.
837 val currentProxyString = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))
839 // Update the proxy preference summary text.
840 proxyPreference.summary = when (currentProxyString) {
841 ProxyHelper.NONE -> getString(R.string.no_proxy_enabled)
842 ProxyHelper.TOR -> getString(R.string.tor_enabled)
843 ProxyHelper.I2P -> getString(R.string.i2p_enabled)
844 ProxyHelper.CUSTOM -> getString(R.string.custom_proxy)
845 else -> getString(R.string.no_proxy_enabled)
848 // Update the status of the custom URL preference.
849 proxyCustomUrlPreference.isEnabled = currentProxyString == ProxyHelper.CUSTOM
852 if (currentProxyString == ProxyHelper.NONE) { // Proxying is disabled.
853 // Set the main proxy icon to be disabled
854 proxyPreference.setIcon(R.drawable.proxy_disabled)
856 // Set the custom proxy URL icon to be ghosted.
857 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
858 } else { // Proxying is enabled.
859 // Set the main proxy icon to be enabled.
860 proxyPreference.setIcon(R.drawable.proxy_enabled)
862 /// Set the custom proxy URL icon according to its status.
863 if (proxyCustomUrlPreference.isEnabled)
864 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled)
866 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted)
870 getString(R.string.proxy_custom_url_key) -> {
871 // Set the summary text for the proxy custom URL.
872 proxyCustomUrlPreference.summary = sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value))
875 getString(R.string.full_screen_browsing_mode_key) -> {
877 if (sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)) { // Full screen browsing is enabled.
878 // Set the full screen browsing mode preference icon.
879 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled)
881 // Set the hide app bar preference icon.
882 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
883 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
885 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
886 } else { // Full screen browsing is disabled.
888 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled)
889 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted)
893 getString(R.string.hide_app_bar_key) -> {
895 if (sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true))
896 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled)
898 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled)
901 getString(R.string.clear_everything_key) -> {
902 // Store the new clear everything status
903 val newClearEverythingBoolean = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
905 // Update the status of the clear and exit preferences.
906 clearCookiesPreference.isEnabled = !newClearEverythingBoolean
907 clearDomStoragePreference.isEnabled = !newClearEverythingBoolean
908 clearFormDataPreference.isEnabled = !newClearEverythingBoolean // Clear form data can be removed once the minimum API >= 26.
909 clearLogcatPreference.isEnabled = !newClearEverythingBoolean
910 clearCachePreference.isEnabled = !newClearEverythingBoolean
912 // Update the clear everything preference icon.
913 if (newClearEverythingBoolean)
914 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled)
916 clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled)
918 // Update the clear cookies preference icon.
919 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
920 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
922 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
924 // Update the clear dom storage preference icon.
925 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
926 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
928 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
930 // Update the clear form data preference icon if the API < 26.
931 if (Build.VERSION.SDK_INT < 26) {
932 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
933 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
935 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
938 // Update the clear logcat preference icon.
939 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
940 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
942 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
944 // Update the clear cache preference icon.
945 if (newClearEverythingBoolean || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
946 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
948 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
951 getString(R.string.clear_cookies_key) -> {
953 if (sharedPreferences.getBoolean(getString(R.string.clear_cookies_key), true))
954 clearCookiesPreference.setIcon(R.drawable.clear_cookies_enabled)
956 clearCookiesPreference.setIcon(R.drawable.clear_cookies_disabled)
959 getString(R.string.clear_dom_storage_key) -> {
961 if (sharedPreferences.getBoolean(getString(R.string.clear_dom_storage_key), true))
962 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_enabled)
964 clearDomStoragePreference.setIcon(R.drawable.clear_dom_storage_disabled)
967 getString(R.string.clear_form_data_key) -> {
969 if (sharedPreferences.getBoolean(getString(R.string.clear_form_data_key), true))
970 clearFormDataPreference.setIcon(R.drawable.clear_form_data_enabled)
972 clearFormDataPreference.setIcon(R.drawable.clear_form_data_disabled)
975 getString(R.string.clear_logcat_key) -> {
977 if (sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true))
978 clearLogcatPreference.setIcon(R.drawable.clear_logcat_enabled)
980 clearLogcatPreference.setIcon(R.drawable.clear_logcat_disabled)
983 getString(R.string.clear_cache_key) -> {
985 if (sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true))
986 clearCachePreference.setIcon(R.drawable.clear_cache_enabled)
988 clearCachePreference.setIcon(R.drawable.clear_cache_disabled)
991 getString(R.string.homepage_key) -> {
992 // Set the new homepage URL as the summary text for the Homepage preference.
993 homepagePreference.summary = sharedPreferences.getString(getString(R.string.homepage_key), getString(R.string.homepage_default_value))
996 getString(R.string.font_size_key) -> {
997 // Update the font size summary text.
998 fontSizePreference.summary = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + "%"
1001 getString(R.string.open_intents_in_new_tab_key) -> {
1003 if (sharedPreferences.getBoolean(getString(R.string.open_intents_in_new_tab_key), true))
1004 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled)
1006 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled)
1009 getString(R.string.swipe_to_refresh_key) -> {
1011 if (sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true))
1012 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled)
1014 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled)
1017 getString(R.string.download_with_external_app_key) -> {
1019 if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false))
1020 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled)
1022 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled)
1025 getString(R.string.scroll_app_bar_key) -> {
1027 if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true))
1028 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled)
1030 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled)
1033 getString(R.string.bottom_app_bar_key) -> {
1035 if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false))
1036 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled)
1038 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled)
1040 // Restart Privacy Browser.
1041 restartPrivacyBrowser()
1044 getString(R.string.display_additional_app_bar_icons_key) -> {
1046 if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false))
1047 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled)
1049 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled)
1052 getString(R.string.app_theme_key) -> {
1053 // Get the app theme entry number that matches the current app theme.
1054 val appThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.app_theme_key), getString(R.string.app_theme_default_value))) {
1055 appThemeEntryValuesStringArray[1] -> 1 // The light theme is selected.
1056 appThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1057 else -> 0 // The system default theme is selected.
1060 // Update the system according to the new theme.
1061 when (appThemeEntryNumber) {
1062 0 -> { // The system default theme is selected.
1063 // Update the theme preference summary text.
1064 appThemePreference.summary = appThemeEntriesStringArray[0]
1066 // Apply the new theme.
1067 if (Build.VERSION.SDK_INT >= 28) { // The system default theme is supported.
1068 // Follow the system default theme.
1069 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
1070 } else { // The system default theme is not supported.
1071 // Follow the battery saver mode.
1072 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY)
1076 1 -> { // The light theme is selected.
1077 // Update the theme preference summary text.
1078 appThemePreference.summary = appThemeEntriesStringArray[1]
1080 // Apply the new theme.
1081 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
1084 2 -> { // The dark theme is selected.
1085 // Update the theme preference summary text.
1086 appThemePreference.summary = appThemeEntriesStringArray[2]
1088 // Apply the new theme.
1089 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
1093 // Enable the WebView theme preference if the API < 33 or the app theme is set to light.
1094 webViewThemePreference.isEnabled = ((Build.VERSION.SDK_INT < 33) || (appThemeEntryNumber != 1))
1096 // Get the webView theme entry number that matches the new WebView theme.
1097 val webViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1098 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1099 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1100 else -> 0 // The system default theme is selected.
1103 // Update the WebView theme icon.
1104 if (webViewThemePreference.isEnabled) { // The WebView theme preference is enabled.
1105 when (webViewThemeEntryNumber) {
1106 // The system default WebView theme is selected.
1108 // Get the current theme status.
1109 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1111 // Set the icon according to the app theme.
1112 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1113 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1115 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1118 // The light WebView theme is selected.
1121 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1124 // The dark WebView theme is selected.
1127 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1130 } else { // The WebView theme preference is disabled.
1131 webViewThemePreference.setIcon(R.drawable.webview_theme_ghosted)
1135 getString(R.string.webview_theme_key) -> {
1136 // Get the webView theme entry number that matches the new WebView theme.
1137 val newWebViewThemeEntryNumber: Int = when (sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))) {
1138 webViewThemeEntriesStringArray[1] -> 1 // The light theme is selected.
1139 webViewThemeEntryValuesStringArray[2] -> 2 // The dark theme is selected.
1140 else -> 0 // The system default theme is selected.
1143 // Update the WebView theme icon.
1144 when (newWebViewThemeEntryNumber) {
1145 // The system default WebView theme is selected.
1147 // Get the current theme status.
1148 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
1151 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO)
1152 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1154 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1157 // The light WebView theme is selected.
1160 webViewThemePreference.setIcon(R.drawable.webview_light_theme)
1163 // The dark WebView theme is selected.
1166 webViewThemePreference.setIcon(R.drawable.webview_dark_theme)
1170 // Set the current theme as the summary text for the preference.
1171 webViewThemePreference.summary = webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]
1174 getString(R.string.wide_viewport_key) -> {
1176 if (sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true))
1177 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled)
1179 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled)
1182 getString(R.string.display_webpage_images_key) -> {
1184 if (sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true))
1185 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled)
1187 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled)
1193 private fun restartPrivacyBrowser() {
1194 // Create an intent to restart Privacy Browser.
1195 val restartIntent = requireActivity().parentActivityIntent!!
1197 // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack. It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1198 restartIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
1200 // Create a handler to restart the activity.
1201 val restartHandler = Handler(Looper.getMainLooper())
1203 // Create a runnable to restart the activity.
1204 val restartRunnable = Runnable {
1205 // Restart the activity.
1206 startActivity(restartIntent)
1208 // Kill this instance of Privacy Browser. Otherwise, the app exhibits sporadic behavior after the restart.
1212 // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1213 restartHandler.postDelayed(restartRunnable, 400)