]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java
Release 3.8.
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / fragments / SettingsFragment.java
1 /*
2  * Copyright © 2016-2021 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
6  * Privacy Browser 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.
10  *
11  * Privacy Browser 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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.fragments;
21
22 import android.annotation.SuppressLint;
23 import android.app.Activity;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.res.Configuration;
28 import android.content.res.Resources;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.view.LayoutInflater;
34 import android.view.View;
35 import android.webkit.WebView;
36 import android.widget.ArrayAdapter;
37
38 import androidx.appcompat.app.AppCompatDelegate;
39 import androidx.preference.Preference;
40 import androidx.preference.PreferenceCategory;
41 import androidx.preference.PreferenceFragmentCompat;
42
43 import com.stoutner.privacybrowser.R;
44 import com.stoutner.privacybrowser.activities.MainWebViewActivity;
45 import com.stoutner.privacybrowser.helpers.ProxyHelper;
46
47 public class SettingsFragment extends PreferenceFragmentCompat {
48     // Declare the class variables.
49     private int currentThemeStatus;
50     private String defaultUserAgent;
51     private ArrayAdapter<CharSequence> userAgentNamesArray;
52     private String[] translatedUserAgentNamesArray;
53     private String[] userAgentDataArray;
54     private String[] appThemeEntriesStringArray;
55     private String[] appThemeEntryValuesStringArray;
56     private String[] webViewThemeEntriesStringArray;
57     private String[] webViewThemeEntryValuesStringArray;
58     private SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener;
59
60     // Declare the class views.
61     private Preference javaScriptPreference;
62     private Preference cookiesPreference;
63     private Preference domStoragePreference;
64     private Preference formDataPreference;  // The form data preference can be removed once the minimum API >= 26.
65     private Preference userAgentPreference;
66     private Preference customUserAgentPreference;
67     private Preference incognitoModePreference;
68     private Preference allowScreenshotsPreference;
69     private Preference easyListPreference;
70     private Preference easyPrivacyPreference;
71     private Preference fanboyAnnoyanceListPreference;
72     private Preference fanboySocialBlockingListPreference;
73     private Preference ultraListPreference;
74     private Preference ultraPrivacyPreference;
75     private Preference blockAllThirdPartyRequestsPreference;
76     private Preference googleAnalyticsPreference;
77     private Preference facebookClickIdsPreference;
78     private Preference twitterAmpRedirectsPreference;
79     private Preference searchPreference;
80     private Preference searchCustomURLPreference;
81     private Preference proxyPreference;
82     private Preference proxyCustomUrlPreference;
83     private Preference fullScreenBrowsingModePreference;
84     private Preference hideAppBarPreference;
85     private Preference clearEverythingPreference;
86     private Preference clearCookiesPreference;
87     private Preference clearDomStoragePreference;
88     private Preference clearFormDataPreference;  // The clear form data preference can be removed once the minimum API >= 26.
89     private Preference clearLogcatPreference;
90     private Preference clearCachePreference;
91     private Preference homepagePreference;
92     private Preference fontSizePreference;
93     private Preference openIntentsInNewTabPreference;
94     private Preference swipeToRefreshPreference;
95     private Preference downloadWithExternalAppPreference;
96     private Preference scrollAppBarPreference;
97     private Preference bottomAppBarPreference;
98     private Preference displayAdditionalAppBarIconsPreference;
99     private Preference appThemePreference;
100     private Preference webViewThemePreference;
101     private Preference wideViewportPreference;
102     private Preference displayWebpageImagesPreference;
103
104     @Override
105     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
106         // Load the preferences from the XML file.
107         setPreferencesFromResource(R.xml.preferences, rootKey);
108
109         // Get a handle for the activity.
110         Activity activity = getActivity();
111
112         // Remove the lint warning below that `getApplicationContext()` might produce a null pointer exception.
113         assert activity != null;
114
115         // Get a handle for the resources.
116         Resources resources = getResources();
117
118         // Get the current theme status.
119         currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
120
121         // // Get a handle for the shared preferences.
122         SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
123
124         // Get handles for the preferences.
125         javaScriptPreference = findPreference("javascript");
126         cookiesPreference = findPreference(getString(R.string.cookies_key));
127         domStoragePreference = findPreference("dom_storage");
128         formDataPreference = findPreference("save_form_data");  // The form data preference can be removed once the minimum API >= 26.
129         userAgentPreference = findPreference("user_agent");
130         customUserAgentPreference = findPreference("custom_user_agent");
131         incognitoModePreference = findPreference("incognito_mode");
132         allowScreenshotsPreference = findPreference(getString(R.string.allow_screenshots_key));
133         easyListPreference = findPreference("easylist");
134         easyPrivacyPreference = findPreference("easyprivacy");
135         fanboyAnnoyanceListPreference = findPreference("fanboys_annoyance_list");
136         fanboySocialBlockingListPreference = findPreference("fanboys_social_blocking_list");
137         ultraListPreference = findPreference("ultralist");
138         ultraPrivacyPreference = findPreference("ultraprivacy");
139         blockAllThirdPartyRequestsPreference = findPreference("block_all_third_party_requests");
140         googleAnalyticsPreference = findPreference("google_analytics");
141         facebookClickIdsPreference = findPreference("facebook_click_ids");
142         twitterAmpRedirectsPreference = findPreference("twitter_amp_redirects");
143         searchPreference = findPreference("search");
144         searchCustomURLPreference = findPreference("search_custom_url");
145         proxyPreference = findPreference("proxy");
146         proxyCustomUrlPreference = findPreference("proxy_custom_url");
147         fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
148         hideAppBarPreference = findPreference("hide_app_bar");
149         clearEverythingPreference = findPreference("clear_everything");
150         clearCookiesPreference = findPreference("clear_cookies");
151         clearDomStoragePreference = findPreference("clear_dom_storage");
152         clearFormDataPreference = findPreference("clear_form_data");  // The clear form data preference can be removed once the minimum API >= 26.
153         clearLogcatPreference = findPreference(getString(R.string.clear_logcat_key));
154         clearCachePreference = findPreference("clear_cache");
155         homepagePreference = findPreference("homepage");
156         fontSizePreference = findPreference("font_size");
157         openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
158         swipeToRefreshPreference = findPreference("swipe_to_refresh");
159         downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key));
160         scrollAppBarPreference = findPreference("scroll_app_bar");
161         bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key));
162         displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key));
163         appThemePreference = findPreference("app_theme");
164         webViewThemePreference = findPreference("webview_theme");
165         wideViewportPreference = findPreference("wide_viewport");
166         displayWebpageImagesPreference = findPreference("display_webpage_images");
167
168         // Remove the lint warnings below that the preferences might be null.
169         assert javaScriptPreference != null;
170         assert cookiesPreference != null;
171         assert domStoragePreference != null;
172         assert formDataPreference != null;
173         assert userAgentPreference != null;
174         assert customUserAgentPreference != null;
175         assert incognitoModePreference != null;
176         assert allowScreenshotsPreference != null;
177         assert easyListPreference != null;
178         assert easyPrivacyPreference != null;
179         assert fanboyAnnoyanceListPreference != null;
180         assert fanboySocialBlockingListPreference != null;
181         assert ultraListPreference != null;
182         assert ultraPrivacyPreference != null;
183         assert blockAllThirdPartyRequestsPreference != null;
184         assert googleAnalyticsPreference != null;
185         assert facebookClickIdsPreference != null;
186         assert twitterAmpRedirectsPreference != null;
187         assert searchPreference != null;
188         assert searchCustomURLPreference != null;
189         assert proxyPreference != null;
190         assert proxyCustomUrlPreference != null;
191         assert fullScreenBrowsingModePreference != null;
192         assert hideAppBarPreference != null;
193         assert clearEverythingPreference != null;
194         assert clearCookiesPreference != null;
195         assert clearDomStoragePreference != null;
196         assert clearFormDataPreference != null;
197         assert clearLogcatPreference != null;
198         assert clearCachePreference != null;
199         assert homepagePreference != null;
200         assert fontSizePreference != null;
201         assert openIntentsInNewTabPreference != null;
202         assert swipeToRefreshPreference != null;
203         assert downloadWithExternalAppPreference != null;
204         assert scrollAppBarPreference != null;
205         assert bottomAppBarPreference != null;
206         assert displayAdditionalAppBarIconsPreference != null;
207         assert appThemePreference != null;
208         assert webViewThemePreference != null;
209         assert wideViewportPreference != null;
210         assert displayWebpageImagesPreference != null;
211
212         // Set the preference dependencies.
213         hideAppBarPreference.setDependency("full_screen_browsing_mode");
214         domStoragePreference.setDependency("javascript");
215
216         // Get strings from the preferences.
217         String userAgentName = sharedPreferences.getString("user_agent", getString(R.string.user_agent_default_value));
218         String searchString = sharedPreferences.getString("search", getString(R.string.search_default_value));
219         String proxyString = sharedPreferences.getString("proxy", getString(R.string.proxy_default_value));
220
221         // Get booleans that are used in multiple places from the preferences.
222         boolean javaScriptEnabled = sharedPreferences.getBoolean("javascript", false);
223         boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
224         boolean fanboySocialBlockingEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
225         boolean fullScreenBrowsingMode = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
226         boolean clearEverything = sharedPreferences.getBoolean("clear_everything", true);
227
228         // Remove the form data preferences if the API is >= 26 as they no longer do anything.
229         if (Build.VERSION.SDK_INT >= 26) {
230             // Get handles for the categories.
231             PreferenceCategory privacyCategory = findPreference("privacy");
232             PreferenceCategory clearAndExitCategory = findPreference("clear_and_exit");
233
234             // Remove the incorrect lint warnings below that the preference categories might be null.
235             assert privacyCategory != null;
236             assert clearAndExitCategory != null;
237
238             // Remove the form data preferences.
239             privacyCategory.removePreference(formDataPreference);
240             clearAndExitCategory.removePreference(clearFormDataPreference);
241         }
242
243         // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
244         fanboySocialBlockingListPreference.setEnabled(!fanboyAnnoyanceListEnabled);
245
246
247         // Inflate a WebView to get the default user agent.
248         LayoutInflater inflater = getActivity().getLayoutInflater();
249
250         // `@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.
251         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
252
253         // Get a handle for a bare WebView.
254         WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
255
256         // Get the default user agent.
257         defaultUserAgent = bareWebView.getSettings().getUserAgentString();
258
259         // Get the user agent arrays.
260         userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item);
261         translatedUserAgentNamesArray = resources.getStringArray(R.array.translated_user_agent_names);
262         userAgentDataArray = resources.getStringArray(R.array.user_agent_data);
263
264         // Get the array position of the user agent name.
265         int userAgentArrayPosition = userAgentNamesArray.getPosition(userAgentName);
266
267         // Populate the user agent summary.
268         switch (userAgentArrayPosition) {
269             case MainWebViewActivity.UNRECOGNIZED_USER_AGENT:  // The user agent name is not on the canonical list.
270                 // 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.
271                 userAgentPreference.setSummary(userAgentName);
272                 break;
273
274             case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
275                 // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
276                 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + defaultUserAgent);
277                 break;
278
279             case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
280                 // Set the summary text.
281                 userAgentPreference.setSummary(R.string.custom_user_agent);
282                 break;
283
284             default:
285                 // Get the user agent summary from the user agent data array.
286                 userAgentPreference.setSummary(translatedUserAgentNamesArray[userAgentArrayPosition] + ":\n" + userAgentDataArray[userAgentArrayPosition]);
287         }
288
289         // Set the summary text for the custom user agent preference.
290         customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", getString(R.string.custom_user_agent_default_value)));
291
292         // Only enable the custom user agent preference if the user agent is set to `Custom`.
293         customUserAgentPreference.setEnabled(userAgentPreference.getSummary().equals(getString(R.string.custom_user_agent)));
294
295
296         // Set the search URL as the summary text for the search preference when the preference screen is loaded.
297         if (searchString.equals("Custom URL")) {
298             // Use R.string.custom_url, which will be translated, instead of the array value, which will not.
299             searchPreference.setSummary(R.string.custom_url);
300         } else {
301             // Set the array value as the summary text.
302             searchPreference.setSummary(searchString);
303         }
304
305         // Set the summary text for the search custom URL (the default is `""`).
306         searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", getString(R.string.search_custom_url_default_value)));
307
308         // Only enable the search custom URL preference if the search is set to `Custom URL`.
309         searchCustomURLPreference.setEnabled(searchString.equals("Custom URL"));
310
311
312         // Set the summary text for the proxy preference when the preference screen is loaded.
313         switch (proxyString) {
314             case ProxyHelper.NONE:
315                 proxyPreference.setSummary(getString(R.string.no_proxy_enabled));
316                 break;
317
318             case ProxyHelper.TOR:
319                 if (Build.VERSION.SDK_INT == 19) {  // Proxying through SOCKS doesn't work on Android KitKat.
320                     proxyPreference.setSummary(getString(R.string.tor_enabled_kitkat));
321                 } else {
322                     proxyPreference.setSummary(getString(R.string.tor_enabled));
323                 }
324                 break;
325
326             case ProxyHelper.I2P:
327                 proxyPreference.setSummary(getString(R.string.i2p_enabled));
328                 break;
329
330             case ProxyHelper.CUSTOM:
331                 proxyPreference.setSummary(getString(R.string.custom_proxy));
332                 break;
333         }
334
335         // Set the summary text for the custom proxy URL.
336         proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
337
338         // Only enable the custom proxy URL if a custom proxy is selected.
339         proxyCustomUrlPreference.setEnabled(proxyString.equals("Custom"));
340
341
342         // Set the status of the clear and exit preferences.
343         clearCookiesPreference.setEnabled(!clearEverything);
344         clearDomStoragePreference.setEnabled(!clearEverything);
345         clearFormDataPreference.setEnabled(!clearEverything);  // The form data line can be removed once the minimum API is >= 26.
346         clearLogcatPreference.setEnabled(!clearEverything);
347         clearCachePreference.setEnabled(!clearEverything);
348
349
350         // Set the homepage URL as the summary text for the homepage preference.
351         homepagePreference.setSummary(sharedPreferences.getString("homepage", getString(R.string.homepage_default_value)));
352
353
354         // Set the font size as the summary text for the preference.
355         fontSizePreference.setSummary(sharedPreferences.getString("font_size", getString(R.string.font_size_default_value)) + "%");
356
357
358         // Get the app theme string arrays.
359         appThemeEntriesStringArray = resources.getStringArray(R.array.app_theme_entries);
360         appThemeEntryValuesStringArray = resources.getStringArray(R.array.app_theme_entry_values);
361
362         // Get the current app theme.
363         String currentAppTheme = sharedPreferences.getString("app_theme", getString(R.string.app_theme_default_value));
364
365         // Define an app theme entry number.
366         int appThemeEntryNumber;
367
368         // Get the app theme entry number that matches the current app theme.  A switch statement cannot be used because the theme entry values string array is not a compile time constant.
369         if (currentAppTheme.equals(appThemeEntryValuesStringArray[1])) {  // The light theme is selected.
370             // Store the app theme entry number.
371             appThemeEntryNumber = 1;
372         } else if (currentAppTheme.equals(appThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
373             // Store the app theme entry number.
374             appThemeEntryNumber = 2;
375         } else {  // The system default theme is selected.
376             // Store the app theme entry number.
377             appThemeEntryNumber = 0;
378         }
379
380         // Set the current theme as the summary text for the preference.
381         appThemePreference.setSummary(appThemeEntriesStringArray[appThemeEntryNumber]);
382
383
384         // Get the WebView theme string arrays.
385         webViewThemeEntriesStringArray = resources.getStringArray(R.array.webview_theme_entries);
386         webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values);
387
388         // Get the current WebView theme.
389         String currentWebViewTheme = sharedPreferences.getString("webview_theme", getString(R.string.webview_theme_default_value));
390
391         // Define a WebView theme entry number.
392         int webViewThemeEntryNumber;
393
394         // Get the WebView theme entry number that matches the current WebView theme.  A switch statement cannot be used because the WebView theme entry values string array is not a compile time constant.
395         if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[1])) {  // The light theme is selected.
396             // Store the WebView theme entry number.
397             webViewThemeEntryNumber = 1;
398         } else if (currentWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
399             // Store the WebView theme entry number.
400             webViewThemeEntryNumber = 2;
401         } else {  // The system default theme is selected.
402             // Store the WebView theme entry number.
403             webViewThemeEntryNumber = 0;
404         }
405
406         // Set the visibility of the WebView theme preference.
407         if (Build.VERSION.SDK_INT < 21) {  // The device is running API 19.
408             // Get a handle for the general category.
409             PreferenceCategory generalCategory = findPreference("general");
410
411             // Remove the incorrect lint warning below that the general preference category might be null.
412             assert generalCategory != null;
413
414             // Remove the WebView theme preference.
415             generalCategory.removePreference(webViewThemePreference);
416         } else {  // The device is running API >= 21
417             // Set the current theme as the summary text for the preference.
418             webViewThemePreference.setSummary(webViewThemeEntriesStringArray[webViewThemeEntryNumber]);
419         }
420
421
422         // Set the JavaScript icon.
423         if (javaScriptEnabled) {
424             javaScriptPreference.setIcon(R.drawable.javascript_enabled);
425         } else {
426             javaScriptPreference.setIcon(R.drawable.privacy_mode);
427         }
428
429         // Set the cookies icon.
430         if (sharedPreferences.getBoolean(getString(R.string.cookies_key), false)) {
431             cookiesPreference.setIcon(R.drawable.cookies_enabled);
432         } else {
433             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
434                 cookiesPreference.setIcon(R.drawable.cookies_disabled_day);
435             } else {
436                 cookiesPreference.setIcon(R.drawable.cookies_disabled_night);
437             }
438         }
439
440         // Set the DOM storage icon.
441         if (javaScriptEnabled) {  // The preference is enabled.
442             if (sharedPreferences.getBoolean("dom_storage", false)) {  // DOM storage is enabled.
443                 domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
444             } else {  // DOM storage is disabled.
445                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
446                     domStoragePreference.setIcon(R.drawable.dom_storage_disabled_day);
447                 } else {
448                     domStoragePreference.setIcon(R.drawable.dom_storage_disabled_night);
449                 }
450             }
451         } else {  // The preference is disabled.  The icon should be ghosted.
452             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
453                 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_day);
454             } else {
455                 domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_night);
456             }
457         }
458
459         // Set the save form data icon if API < 26.  Save form data has no effect on API >= 26.
460         if (Build.VERSION.SDK_INT < 26) {
461             if (sharedPreferences.getBoolean("save_form_data", false)) {
462                 formDataPreference.setIcon(R.drawable.form_data_enabled);
463             } else {
464                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
465                     formDataPreference.setIcon(R.drawable.form_data_disabled_day);
466                 } else {
467                     formDataPreference.setIcon(R.drawable.form_data_disabled_night);
468                 }
469             }
470         }
471
472         // Set the custom user agent icon.
473         if (customUserAgentPreference.isEnabled()) {
474             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
475                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_day);
476             } else {
477                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_night);
478             }
479         } else {
480             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
481                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_day);
482             } else {
483                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_night);
484             }
485         }
486
487         // Set the incognito mode icon.
488         if (sharedPreferences.getBoolean("incognito_mode", false)) {
489             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
490                 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_night);
491             } else {
492                 incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_day);
493             }
494         } else {
495             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
496                 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_night);
497             } else {
498                 incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_day);
499             }
500         }
501
502         // Set the allow screenshots icon.
503         if (sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)) {
504             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
505                 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_day);
506             } else {
507                 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_night);
508             }
509         } else {
510             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
511                 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_day);
512             } else {
513                 allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_night);
514             }
515         }
516
517         // Set the EasyList icon.
518         if (sharedPreferences.getBoolean("easylist", true)) {
519             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
520                 easyListPreference.setIcon(R.drawable.block_ads_enabled_night);
521             } else {
522                 easyListPreference.setIcon(R.drawable.block_ads_enabled_day);
523             }
524         } else {
525             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
526                 easyListPreference.setIcon(R.drawable.block_ads_disabled_night);
527             } else {
528                 easyListPreference.setIcon(R.drawable.block_ads_disabled_day);
529             }
530         }
531
532         // Set the EasyPrivacy icon.
533         if (sharedPreferences.getBoolean("easyprivacy", true)) {
534             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
535                 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
536             } else {
537                 easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
538             }
539         } else {
540             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
541                 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
542             } else {
543                 easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
544             }
545         }
546
547         // Set the Fanboy lists icons.
548         if (fanboyAnnoyanceListEnabled) {
549             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
550                 // Set the Fanboy annoyance list icon.
551                 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_night);
552
553                 // Set the Fanboy social blocking list icon.
554                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_night);
555             } else {
556                 // Set the Fanboy annoyance list icon.
557                 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_day);
558
559                 // Set the Fanboy social blocking list icon.
560                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_day);
561             }
562         } else {
563             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
564                 // Set the Fanboy annoyance list icon.
565                 fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_night);
566
567                 // Set the Fanboy social blocking list icon.
568                 if (fanboySocialBlockingEnabled) {
569                     fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_night);
570                 } else {
571                     fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_night);
572                 }
573             } else {
574                 // Set the Fanboy annoyance list icon.
575                 fanboyAnnoyanceListPreference.setIcon(R.drawable.block_ads_disabled_day);
576
577                 // Set the Fanboy social blocking list icon.
578                 if (fanboySocialBlockingEnabled) {
579                     fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_day);
580                 } else {
581                     fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_day);
582                 }
583             }
584         }
585
586         // Set the UltraList icon.
587         if (sharedPreferences.getBoolean("ultralist", true)){
588             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
589                 ultraListPreference.setIcon(R.drawable.block_ads_enabled_night);
590             } else {
591                 ultraListPreference.setIcon(R.drawable.block_ads_enabled_day);
592             }
593         } else {
594             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
595                 ultraListPreference.setIcon(R.drawable.block_ads_disabled_night);
596             } else {
597                 ultraListPreference.setIcon(R.drawable.block_ads_disabled_day);
598             }
599         }
600
601         // Set the UltraPrivacy icon.
602         if (sharedPreferences.getBoolean("ultraprivacy", true)) {
603             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
604                 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
605             } else {
606                 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
607             }
608         } else {
609             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
610                 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
611             } else {
612                 ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
613             }
614         }
615
616         // Set the block all third-party requests icon.
617         if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
618             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
619                 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_night);
620             } else {
621                 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_day);
622             }
623         } else {
624             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
625                 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_night);
626             } else {
627                 blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_day);
628             }
629         }
630
631         // Set the Google Analytics icon according to the theme.
632         if (sharedPreferences.getBoolean("google_analytics", true)) {
633             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
634                 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_night);
635             } else {
636                 googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_day);
637             }
638         } else {
639             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
640                 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_night);
641             } else {
642                 googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_day);
643             }
644         }
645
646         // Set the Facebook Click IDs icon according to the theme.
647         if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
648             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
649                 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_night);
650             } else {
651                 facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_day);
652             }
653         } else {
654             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
655                 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_night);
656             } else {
657                 facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_day);
658             }
659         }
660
661         // Set the Twitter AMP redirects icon according to the theme.
662         if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
663             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
664                 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_night);
665             } else {
666                 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_day);
667             }
668         } else {
669             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
670                 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_night);
671             } else {
672                 twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_day);
673             }
674         }
675
676         // Set the search custom URL icon.
677         if (searchCustomURLPreference.isEnabled()) {
678             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
679                 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_night);
680             } else {
681                 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_day);
682             }
683         } else {
684             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
685                 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_night);
686             } else {
687                 searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_day);
688             }
689         }
690
691         // Set the Proxy icons according to the theme and status.
692         if (proxyString.equals("None")) {  // Proxying is disabled.
693             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
694                 // Set the main proxy icon to be disabled.
695                 proxyPreference.setIcon(R.drawable.proxy_disabled_night);
696
697                 // Set the custom proxy URL icon to be ghosted.
698                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
699             } else {  // Light theme.
700                 // Set the main proxy icon to be disabled.
701                 proxyPreference.setIcon(R.drawable.proxy_disabled_day);
702
703                 // Set the custom proxy URL icon to be ghosted.
704                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
705             }
706         } else {  // Proxying is enabled.
707             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
708                 // Set the main proxy icon to be enabled.
709                 proxyPreference.setIcon(R.drawable.proxy_enabled_night);
710
711                 // Set the custom proxy URL icon according to its status.
712                 if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
713                     proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_night);
714                 } else {  // Custom proxy is disabled.
715                     proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
716                 }
717             } else {  // Light theme.
718                 // Set the main proxy icon to be enabled.
719                 proxyPreference.setIcon(R.drawable.proxy_enabled_day);
720
721                 // Set the custom proxy URL icon according to its status.
722                 if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
723                     proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_day);
724                 } else {  // Custom proxy is disabled.
725                     proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
726                 }
727             }
728         }
729
730         // Set the full screen browsing mode icons.
731         if (fullScreenBrowsingMode) {  // Full screen browsing mode is enabled.
732             // Set the `fullScreenBrowsingModePreference` icon according to the theme.
733             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
734                 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_night);
735             } else {
736                 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_day);
737             }
738
739             // Set the hide app bar icon.
740             if (sharedPreferences.getBoolean("hide_app_bar", true)) {  // Hide app bar is enabled.
741                 // Set the icon according to the theme.
742                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
743                     hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
744                 } else {
745                     hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
746                 }
747             } else {  // Hide app bar is disabled.
748                 // Set the icon according to the theme.
749                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
750                     hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
751                 } else {
752                     hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
753                 }
754             }
755         } else {  // Full screen browsing mode is disabled.
756             // Set the icons according to the theme.
757             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
758                 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_night);
759                 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_night);
760             } else {
761                 fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_day);
762                 hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_day);
763             }
764         }
765
766         // Set the clear everything preference icon.
767         if (clearEverything) {
768             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
769                 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_day);
770             } else {
771                 clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_night);
772             }
773         } else {
774             clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
775         }
776
777         // Set the clear cookies preference icon.
778         if (clearEverything || sharedPreferences.getBoolean("clear_cookies", true)) {
779             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
780                 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_day);
781             } else {
782                 clearCookiesPreference.setIcon(R.drawable.cookies_cleared_night);
783             }
784         } else {
785             clearCookiesPreference.setIcon(R.drawable.cookies_warning);
786         }
787
788         // Set the clear DOM storage preference icon.
789         if (clearEverything || sharedPreferences.getBoolean("clear_dom_storage", true)) {
790             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
791                 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_night);
792             } else {
793                 clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_day);
794             }
795         } else {
796             clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
797         }
798
799         // Set the clear form data preference icon if the API < 26.  It has no effect on newer versions of Android.
800         if (Build.VERSION.SDK_INT < 26) {
801             if (clearEverything || sharedPreferences.getBoolean("clear_form_data", true)) {
802                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
803                     clearFormDataPreference.setIcon(R.drawable.form_data_cleared_night);
804                 } else {
805                     clearFormDataPreference.setIcon(R.drawable.form_data_cleared_day);
806                 }
807             } else {
808                 clearFormDataPreference.setIcon(R.drawable.form_data_warning);
809             }
810         }
811
812         // Set the clear logcat preference icon.
813         if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_logcat_key), true)) {
814             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
815                 clearLogcatPreference.setIcon(R.drawable.bug_cleared_day);
816             } else {
817                 clearLogcatPreference.setIcon(R.drawable.bug_cleared_night);
818             }
819         } else {
820             clearLogcatPreference.setIcon(R.drawable.bug_warning);
821         }
822
823         // Set the clear cache preference icon.
824         if (clearEverything || sharedPreferences.getBoolean("clear_cache", true)) {
825             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
826                 clearCachePreference.setIcon(R.drawable.cache_cleared_night);
827             } else {
828                 clearCachePreference.setIcon(R.drawable.cache_cleared_day);
829             }
830         } else {
831             clearCachePreference.setIcon(R.drawable.cache_warning);
832         }
833
834         // Set the open intents in new tab preference icon.
835         if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
836             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
837                 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_night);
838             } else {
839                 openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_day);
840             }
841         } else {
842             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
843                 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_night);
844             } else {
845                 openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_day);
846             }
847         }
848
849         // Set the swipe to refresh preference icon.
850         if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
851             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
852                 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_day);
853             } else {
854                 swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_night);
855             }
856         } else {
857             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
858                 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_day);
859             } else {
860                 swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_night);
861             }
862         }
863
864         // Set the download with external app preference icon.
865         if (sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false)) {
866             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
867                 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_day);
868             } else {
869                 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_night);
870             }
871         } else {
872             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
873                 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_day);
874             } else {
875                 downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_night);
876             }
877         }
878
879         // Set the scroll app bar preference icon.
880         if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
881             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
882                 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
883             } else {
884                 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
885             }
886         } else {
887             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
888                 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
889             } else {
890                 scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
891             }
892         }
893
894         // Set the bottom app bar preference icon.
895         if (sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)) {
896             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
897                 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_day);
898             } else {
899                 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_night);
900             }
901         } else {
902             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
903                 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_day);
904             } else {
905                 bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_night);
906             }
907         }
908
909         // Set the display additional app bar icons preference icon.
910         if (sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false)) {
911             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
912                 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_day);
913             } else {
914                 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_night);
915             }
916         } else {
917             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
918                 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_day);
919             } else {
920                 displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_night);
921             }
922         }
923
924         // Set the WebView theme preference icon.
925         switch (webViewThemeEntryNumber) {
926             case 0:  // The system default WebView theme is selected.
927                 // Set the icon according to the app theme.
928                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
929                     webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
930                 } else {
931                     webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
932                 }
933                 break;
934
935             case 1:  // The light WebView theme is selected.
936                 // Set the icon according to the app theme.
937                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
938                     webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
939                 } else {
940                     webViewThemePreference.setIcon(R.drawable.webview_light_theme_night);
941                 }
942                 break;
943
944             case 2:  // The dark WebView theme is selected.
945                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
946                     webViewThemePreference.setIcon(R.drawable.webview_dark_theme_day);
947                 } else {
948                     webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
949                 }
950                 break;
951         }
952
953         // Set the wide viewport preference icon.
954         if (sharedPreferences.getBoolean("wide_viewport", true)) {
955             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
956                 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_night);
957             } else {
958                 wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_day);
959             }
960         } else {
961             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
962                 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_night);
963             } else {
964                 wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_day);
965             }
966         }
967
968         // Set the display webpage images preference icon.
969         if (sharedPreferences.getBoolean("display_webpage_images", true)) {
970             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
971                 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_night);
972             } else {
973                 displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_day);
974             }
975         } else {
976             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
977                 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_night);
978             } else {
979                 displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_day);
980             }
981         }
982
983         // Get the shared preferences change listener.
984         sharedPreferenceChangeListener = getSharedPreferencesChangeListener(requireContext());
985
986         // Register the listener.
987         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
988     }
989
990     // The listener should be unregistered when the app is paused.
991     @Override
992     public void onPause() {
993         // Run the default commands.
994         super.onPause();
995
996         // Get a handle for the shared preferences.
997         SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
998
999         // Unregister the shared preferences listener.
1000         sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
1001     }
1002
1003     // The listener should be re-registered when the app is resumed.
1004     @Override
1005     public void onResume() {
1006         // Run the default commands.
1007         super.onResume();
1008
1009         // Get a new shared preferences change listener.
1010         sharedPreferenceChangeListener = getSharedPreferencesChangeListener(requireContext());
1011
1012         // Get a handle for the shared preferences.
1013         SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
1014
1015         // Re-register the shared preferences listener.
1016         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
1017     }
1018
1019     // The context must be passed to the shared preference change listener or else any calls to the system `getString()` will crash if the app has been restarted.
1020     private SharedPreferences.OnSharedPreferenceChangeListener getSharedPreferencesChangeListener(Context context) {
1021         // Return the shared preference change listener.
1022         return (SharedPreferences sharedPreferences, String key) -> {
1023             switch (key) {
1024                 case "javascript":
1025                     // Update the icons and the DOM storage preference status.
1026                     if (sharedPreferences.getBoolean("javascript", false)) {  // The JavaScript preference is enabled.
1027                         // Update the icon for the JavaScript preference.
1028                         javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1029
1030                         // Update the status of the DOM storage preference.
1031                         domStoragePreference.setEnabled(true);
1032
1033                         // Update the icon for the DOM storage preference.
1034                         if (sharedPreferences.getBoolean("dom_storage", false)) {
1035                             domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1036                         } else {
1037                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1038                                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_day);
1039                             } else {
1040                                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_night);
1041                             }
1042                         }
1043                     } else {  // The JavaScript preference is disabled.
1044                         // Update the icon for the JavaScript preference.
1045                         javaScriptPreference.setIcon(R.drawable.privacy_mode);
1046
1047                         // Update the status of the DOM storage preference.
1048                         domStoragePreference.setEnabled(false);
1049
1050                         // Set the icon for DOM storage preference to be ghosted.
1051                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1052                             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_day);
1053                         } else {
1054                             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_night);
1055                         }
1056                     }
1057                     break;
1058
1059                 case "cookies":
1060                     // Update the icon.
1061                     if (sharedPreferences.getBoolean(context.getString(R.string.cookies_key), false)) {
1062                         cookiesPreference.setIcon(R.drawable.cookies_enabled);
1063                     } else {
1064                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1065                             cookiesPreference.setIcon(R.drawable.cookies_disabled_day);
1066                         } else {
1067                             cookiesPreference.setIcon(R.drawable.cookies_disabled_night);
1068                         }
1069                     }
1070                     break;
1071
1072                 case "dom_storage":
1073                     // Update the icon.
1074                     if (sharedPreferences.getBoolean("dom_storage", false)) {
1075                         domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1076                     } else {
1077                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1078                             domStoragePreference.setIcon(R.drawable.dom_storage_disabled_day);
1079                         } else {
1080                             domStoragePreference.setIcon(R.drawable.dom_storage_disabled_night);
1081                         }
1082                     }
1083                     break;
1084
1085                 // Save form data can be removed once the minimum API >= 26.
1086                 case "save_form_data":
1087                     // Update the icon.
1088                     if (sharedPreferences.getBoolean("save_form_data", false)) {
1089                         formDataPreference.setIcon(R.drawable.form_data_enabled);
1090                     } else {
1091                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1092                             formDataPreference.setIcon(R.drawable.form_data_disabled_day);
1093                         } else {
1094                             formDataPreference.setIcon(R.drawable.form_data_disabled_night);
1095                         }
1096                     }
1097                     break;
1098
1099                 case "user_agent":
1100                     // Get the new user agent name.
1101                     String newUserAgentName = sharedPreferences.getString("user_agent", context.getString(R.string.user_agent_default_value));
1102
1103                     // Get the array position for the new user agent name.
1104                     int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
1105
1106                     // Get the translated new user agent name.
1107                     String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
1108
1109                     // Populate the user agent summary.
1110                     switch (newUserAgentArrayPosition) {
1111                         case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1112                             // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
1113                             userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + defaultUserAgent);
1114
1115                             // Disable the custom user agent preference.
1116                             customUserAgentPreference.setEnabled(false);
1117
1118                             // Set the custom user agent preference icon according to the theme.
1119                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1120                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_night);
1121                             } else {
1122                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_day);
1123                             }
1124                             break;
1125
1126                         case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1127                             // Set the summary text.
1128                             userAgentPreference.setSummary(R.string.custom_user_agent);
1129
1130                             // Enable the custom user agent preference.
1131                             customUserAgentPreference.setEnabled(true);
1132
1133                             // Set the custom user agent preference icon according to the theme.
1134                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1135                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_night);
1136                             } else {
1137                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_day);
1138                             }
1139                             break;
1140
1141                         default:
1142                             // Get the user agent summary from the user agent data array.
1143                             userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1144
1145                             // Disable the custom user agent preference.
1146                             customUserAgentPreference.setEnabled(false);
1147
1148                             // Set the custom user agent preference icon according to the theme.
1149                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1150                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_night);
1151                             } else {
1152                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_day);
1153                             }
1154                     }
1155                     break;
1156
1157                 case "custom_user_agent":
1158                     // Set the new custom user agent as the summary text for the preference.
1159                     customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", context.getString(R.string.custom_user_agent_default_value)));
1160                     break;
1161
1162                 case "incognito_mode":
1163                     // Update the icon.
1164                     if (sharedPreferences.getBoolean("incognito_mode", false)) {
1165                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1166                             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_night);
1167                         } else {
1168                             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_day);
1169                         }
1170                     } else {
1171                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1172                             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_night);
1173                         } else {
1174                             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_day);
1175                         }
1176                     }
1177                     break;
1178
1179                 case "allow_screenshots":
1180                     // Update the icon.
1181                     if (sharedPreferences.getBoolean(context.getString(R.string.allow_screenshots_key), false)) {
1182                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1183                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_day);
1184                         } else {
1185                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_night);
1186                         }
1187                     } else {
1188                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1189                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_day);
1190                         } else {
1191                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_night);
1192                         }
1193                     }
1194
1195                     // Restart Privacy Browser.
1196                     restartPrivacyBrowser();
1197                     break;
1198
1199                 case "easylist":
1200                     // Update the icon.
1201                     if (sharedPreferences.getBoolean("easylist", true)) {
1202                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1203                             easyListPreference.setIcon(R.drawable.block_ads_enabled_night);
1204                         } else {
1205                             easyListPreference.setIcon(R.drawable.block_ads_enabled_day);
1206                         }
1207                     } else {
1208                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1209                             easyListPreference.setIcon(R.drawable.block_ads_disabled_night);
1210                         } else {
1211                             easyListPreference.setIcon(R.drawable.block_ads_disabled_day);
1212                         }
1213                     }
1214                     break;
1215
1216                 case "easyprivacy":
1217                     // Update the icon.
1218                     if (sharedPreferences.getBoolean("easyprivacy", true)) {
1219                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1220                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
1221                         } else {
1222                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
1223                         }
1224                     } else {
1225                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1226                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
1227                         } else {
1228                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
1229                         }
1230                     }
1231                     break;
1232
1233                 case "fanboys_annoyance_list":
1234                     boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1235                     boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1236
1237                     // Update the Fanboy icons.
1238                     if (currentFanboyAnnoyanceList) {  // Fanboy's annoyance list is enabled.
1239                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1240                             // Update the Fanboy's annoyance list icon.
1241                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_night);
1242
1243                             // Update the Fanboy's social blocking list icon.
1244                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_night);
1245                         } else {
1246                             // Update the Fanboy's annoyance list icon.
1247                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_day);
1248
1249                             // Update the Fanboy's social blocking list icon.
1250                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_day);
1251                         }
1252                     } else {  // Fanboy's annoyance list is disabled.
1253                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1254                             // Update the Fanboy's annoyance list icon.
1255                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_night);
1256
1257                             // Update the Fanboy's social blocking list icon.
1258                             if (currentFanboySocialBlockingList) {
1259                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_night);
1260                             } else {
1261                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_night);
1262                             }
1263                         } else {
1264                             // Update the Fanboy's annoyance list icon.
1265                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_day);
1266
1267                             // Update the Fanboy's social blocking list icon.
1268                             if (currentFanboySocialBlockingList) {
1269                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_day);
1270                             } else {
1271                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_day);
1272                             }
1273                         }
1274                     }
1275
1276                     // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1277                     fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1278                     break;
1279
1280                 case "fanboys_social_blocking_list":
1281                     // Update the icon.
1282                     if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1283                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1284                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_night);
1285                         } else {
1286                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_day);
1287                         }
1288                     } else {
1289                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1290                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_night);
1291                         } else {
1292                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_day);
1293                         }
1294                     }
1295                     break;
1296
1297                 case "ultralist":
1298                     // Update the icon.
1299                     if (sharedPreferences.getBoolean("ultralist", true)) {
1300                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1301                             ultraListPreference.setIcon(R.drawable.block_ads_enabled_night);
1302                         } else {
1303                             ultraListPreference.setIcon(R.drawable.block_ads_enabled_day);
1304                         }
1305                     } else {
1306                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1307                             ultraListPreference.setIcon(R.drawable.block_ads_disabled_night);
1308                         } else {
1309                             ultraListPreference.setIcon(R.drawable.block_ads_disabled_day);
1310                         }
1311                     }
1312                     break;
1313
1314                 case "ultraprivacy":
1315                     // Update the icon.
1316                     if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1317                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1318                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
1319                         } else {
1320                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
1321                         }
1322                     } else {
1323                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1324                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
1325                         } else {
1326                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
1327                         }
1328                     }
1329                     break;
1330
1331                 case "block_all_third_party_requests":
1332                     // Update the icon.
1333                     if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1334                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1335                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_night);
1336                         } else {
1337                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_day);
1338                         }
1339                     } else {
1340                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1341                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_night);
1342                         } else {
1343                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_day);
1344                         }
1345                     }
1346                     break;
1347
1348                 case "google_analytics":
1349                     // Update the icon.
1350                     if (sharedPreferences.getBoolean("google_analytics", true)) {
1351                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1352                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_night);
1353                         } else {
1354                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_day);
1355                         }
1356                     } else {
1357                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1358                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_night);
1359                         } else {
1360                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_day);
1361                         }
1362                     }
1363                     break;
1364
1365                 case "facebook_click_ids":
1366                     // Update the icon.
1367                     if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1368                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1369                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_night);
1370                         } else {
1371                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_day);
1372                         }
1373                     } else {
1374                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1375                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_night);
1376                         } else {
1377                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_day);
1378                         }
1379                     }
1380                     break;
1381
1382                 case "twitter_amp_redirects":
1383                     // Update the icon.
1384                     if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1385                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1386                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_night);
1387                         } else {
1388                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_day);
1389                         }
1390                     } else {
1391                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1392                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_night);
1393                         } else {
1394                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_day);
1395                         }
1396                     }
1397                     break;
1398
1399                 case "search":
1400                     // Store the new search string.
1401                     String newSearchString = sharedPreferences.getString("search", context.getString(R.string.search_default_value));
1402
1403                     // Update the search and search custom URL preferences.
1404                     if (newSearchString.equals("Custom URL")) {  // `Custom URL` is selected.
1405                         // Set the summary text to `R.string.custom_url`, which is translated.
1406                         searchPreference.setSummary(R.string.custom_url);
1407
1408                         // Enable `searchCustomURLPreference`.
1409                         searchCustomURLPreference.setEnabled(true);
1410
1411                         // Set the `searchCustomURLPreference` according to the theme.
1412                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1413                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_night);
1414                         } else {
1415                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_day);
1416                         }
1417                     } else {  // `Custom URL` is not selected.
1418                         // Set the summary text to `newSearchString`.
1419                         searchPreference.setSummary(newSearchString);
1420
1421                         // Disable `searchCustomURLPreference`.
1422                         searchCustomURLPreference.setEnabled(false);
1423
1424                         // Set the `searchCustomURLPreference` according to the theme.
1425                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1426                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_night);
1427                         } else {
1428                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_day);
1429                         }
1430                     }
1431                     break;
1432
1433                 case "search_custom_url":
1434                     // Set the new search custom URL as the summary text for the preference.
1435                     searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", context.getString(R.string.search_custom_url_default_value)));
1436                     break;
1437
1438                 case "proxy":
1439                     // Get current proxy string.
1440                     String currentProxyString = sharedPreferences.getString("proxy", context.getString(R.string.proxy_default_value));
1441
1442                     // Update the summary text for the proxy preference.
1443                     switch (currentProxyString) {
1444                         case ProxyHelper.NONE:
1445                             proxyPreference.setSummary(context.getString(R.string.no_proxy_enabled));
1446                             break;
1447
1448                         case ProxyHelper.TOR:
1449                             if (Build.VERSION.SDK_INT == 19) {  // Proxying through SOCKS doesn't work on Android KitKat.
1450                                 proxyPreference.setSummary(context.getString(R.string.tor_enabled_kitkat));
1451                             } else {
1452                                 proxyPreference.setSummary(context.getString(R.string.tor_enabled));
1453                             }
1454                             break;
1455
1456                         case ProxyHelper.I2P:
1457                             proxyPreference.setSummary(context.getString(R.string.i2p_enabled));
1458                             break;
1459
1460                         case ProxyHelper.CUSTOM:
1461                             proxyPreference.setSummary(context.getString(R.string.custom_proxy));
1462                             break;
1463                     }
1464
1465                     // Update the status of the custom URL preference.
1466                     proxyCustomUrlPreference.setEnabled(currentProxyString.equals("Custom"));
1467
1468                     // Update the icons.
1469                     if (currentProxyString.equals("None")) {  // Proxying is disabled.
1470                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
1471                             // Set the main proxy icon to be disabled
1472                             proxyPreference.setIcon(R.drawable.proxy_disabled_night);
1473
1474                             // Set the custom proxy URL icon to be ghosted.
1475                             proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
1476                         } else {  // Light theme.
1477                             // Set the main proxy icon to be disabled.
1478                             proxyPreference.setIcon(R.drawable.proxy_disabled_day);
1479
1480                             // Set the custom proxy URL icon to be ghosted.
1481                             proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
1482                         }
1483                     } else {  // Proxying is enabled.
1484                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
1485                             // Set the main proxy icon to be enabled.
1486                             proxyPreference.setIcon(R.drawable.proxy_enabled_night);
1487
1488                             /// Set the custom proxy URL icon according to its status.
1489                             if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
1490                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_night);
1491                             } else {  // Custom proxy is disabled.
1492                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
1493                             }
1494                         } else {  // Light theme.
1495                             // Set the main proxy icon to be enabled.
1496                             proxyPreference.setIcon(R.drawable.proxy_enabled_day);
1497
1498                             // Set the custom proxy URL icon according to its status.
1499                             if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
1500                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_day);
1501                             } else {  // Custom proxy is disabled.
1502                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
1503                             }
1504                         }
1505                     }
1506                     break;
1507
1508                 case "proxy_custom_url":
1509                     // Set the summary text for the proxy custom URL.
1510                     proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value)));
1511                     break;
1512
1513                 case "full_screen_browsing_mode":
1514                     if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) {  // Full screen browsing is enabled.
1515                         // Set the full screen browsing mode preference icon according to the theme.
1516                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1517                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_night);
1518                         } else {
1519                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_day);
1520                         }
1521
1522                         // Set the hide app bar preference icon.
1523                         if (sharedPreferences.getBoolean("hide_app_bar", true)) {  //  Hide app bar is enabled.
1524                             // Set the icon according to the theme.
1525                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1526                                 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1527                             } else {
1528                                 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1529                             }
1530                         } else {  // Hide app bar is disabled.
1531                             // Set the icon according to the theme.
1532                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1533                                 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1534                             } else {
1535                                 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1536                             }
1537                         }
1538                     } else {  // Full screen browsing is disabled.
1539                         // Update the icons according to the theme.
1540                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1541                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_night);
1542                             hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_night);
1543                         } else {
1544                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_day);
1545                             hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_day);
1546                         }
1547                     }
1548                     break;
1549
1550                 case "hide_app_bar":
1551                     // Update the icon.
1552                     if (sharedPreferences.getBoolean("hide_app_bar", true)) {  // Hide app bar is enabled.
1553                         // Set the icon according to the theme.
1554                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1555                             hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1556                         } else {
1557                             hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1558                         }
1559                     } else {  // Hide app bar is disabled.
1560                         // Set the icon according to the theme.
1561                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1562                             hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1563                         } else {
1564                             hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1565                         }
1566                     }
1567                     break;
1568
1569                 case "clear_everything":
1570                     // Store the new clear everything status
1571                     boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1572
1573                     // Update the status of the clear and exit preferences.
1574                     clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1575                     clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1576                     clearFormDataPreference.setEnabled(!newClearEverythingBoolean);  // This line can be removed once the minimum API >= 26.
1577                     clearLogcatPreference.setEnabled(!newClearEverythingBoolean);
1578                     clearCachePreference.setEnabled(!newClearEverythingBoolean);
1579
1580                     // Update the clear everything preference icon.
1581                     if (newClearEverythingBoolean) {
1582                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1583                             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_day);
1584                         } else {
1585                             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_night);
1586                         }
1587                     } else {
1588                         clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1589                     }
1590
1591                     // Update the clear cookies preference icon.
1592                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1593                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1594                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_day);
1595                         } else {
1596                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_night);
1597                         }
1598                     } else {
1599                         clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1600                     }
1601
1602                     // Update the clear dom storage preference icon.
1603                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1604                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1605                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_day);
1606                         } else {
1607                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_night);
1608                         }
1609                     } else {
1610                         clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1611                     }
1612
1613                     // Update the clear form data preference icon if the API < 26.
1614                     if (Build.VERSION.SDK_INT < 26) {
1615                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1616                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1617                                 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_day);
1618                             } else {
1619                                 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_night);
1620                             }
1621                         } else {
1622                             clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1623                         }
1624                     }
1625
1626                     // Update the clear logcat preference icon.
1627                     if (newClearEverythingBoolean || sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1628                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1629                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_day);
1630                         } else {
1631                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_night);
1632                         }
1633                     } else {
1634                         clearLogcatPreference.setIcon(R.drawable.cache_warning);
1635                     }
1636
1637                     // Update the clear cache preference icon.
1638                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1639                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1640                             clearCachePreference.setIcon(R.drawable.cache_cleared_day);
1641                         } else {
1642                             clearCachePreference.setIcon(R.drawable.cache_cleared_night);
1643                         }
1644                     } else {
1645                         clearCachePreference.setIcon(R.drawable.cache_warning);
1646                     }
1647                     break;
1648
1649                 case "clear_cookies":
1650                     // Update the icon.
1651                     if (sharedPreferences.getBoolean("clear_cookies", true)) {
1652                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1653                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_day);
1654                         } else {
1655                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_night);
1656                         }
1657                     } else {
1658                         clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1659                     }
1660                     break;
1661
1662                 case "clear_dom_storage":
1663                     // Update the icon.
1664                     if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1665                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1666                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_day);
1667                         } else {
1668                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_night);
1669                         }
1670                     } else {
1671                         clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1672                     }
1673                     break;
1674
1675                 // This section can be removed once the minimum API >= 26.
1676                 case "clear_form_data":
1677                     // Update the icon.
1678                     if (sharedPreferences.getBoolean("clear_form_data", true)) {
1679                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1680                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared_day);
1681                         } else {
1682                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared_night);
1683                         }
1684                     } else {
1685                         clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1686                     }
1687                     break;
1688
1689                 case "clear_logcat":
1690                     // Update the icon.
1691                     if (sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1692                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1693                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_day);
1694                         } else {
1695                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_night);
1696                         }
1697                     } else {
1698                         clearLogcatPreference.setIcon(R.drawable.bug_warning);
1699                     }
1700                     break;
1701
1702                 case "clear_cache":
1703                     // Update the icon.
1704                     if (sharedPreferences.getBoolean("clear_cache", true)) {
1705                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1706                             clearCachePreference.setIcon(R.drawable.cache_cleared_day);
1707                         } else {
1708                             clearCachePreference.setIcon(R.drawable.cache_cleared_night);
1709                         }
1710                     } else {
1711                         clearCachePreference.setIcon(R.drawable.cache_warning);
1712                     }
1713                     break;
1714
1715                 case "homepage":
1716                     // Set the new homepage URL as the summary text for the Homepage preference.
1717                     homepagePreference.setSummary(sharedPreferences.getString("homepage", context.getString(R.string.homepage_default_value)));
1718                     break;
1719
1720                 case "font_size":
1721                     // Update the font size summary text.
1722                     fontSizePreference.setSummary(sharedPreferences.getString("font_size", context.getString(R.string.font_size_default_value)) + "%");
1723                     break;
1724
1725                 case "open_intents_in_new_tab":
1726                     // Update the icon.
1727                     if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1728                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1729                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_day);
1730                         } else {
1731                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_night);
1732                         }
1733                     } else {
1734                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1735                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_day);
1736                         } else {
1737                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_night);
1738                         }
1739                     }
1740                     break;
1741
1742                 case "swipe_to_refresh":
1743                     // Update the icon.
1744                     if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1745                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1746                             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_day);
1747                         } else {
1748                             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_night);
1749                         }
1750                     } else {
1751                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1752                             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_day);
1753                         } else {
1754                             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_night);
1755                         }
1756                     }
1757                     break;
1758
1759                 case "download_with_external_app":
1760                     // Update the icon.
1761                     if (sharedPreferences.getBoolean(context.getString(R.string.download_with_external_app_key), false)) {
1762                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1763                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_day);
1764                         } else {
1765                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_night);
1766                         }
1767                     } else {
1768                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1769                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_day);
1770                         } else {
1771                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_night);
1772                         }
1773                     }
1774                     break;
1775
1776                 case "scroll_app_bar":
1777                     // Update the icon.
1778                     if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1779                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1780                             scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1781                         } else {
1782                             scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1783                         }
1784                     } else {
1785                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1786                             scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1787                         } else {
1788                             scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1789                         }
1790                     }
1791                     break;
1792
1793                 case "bottom_app_bar":
1794                     // Update the icon.
1795                     if (sharedPreferences.getBoolean(context.getString(R.string.bottom_app_bar_key), false)) {
1796                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1797                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_day);
1798                         } else {
1799                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_night);
1800                         }
1801                     } else {
1802                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1803                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_day);
1804                         } else {
1805                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_night);
1806                         }
1807                     }
1808
1809                     // Restart Privacy Browser.
1810                     restartPrivacyBrowser();
1811                     break;
1812
1813                 case "display_additional_app_bar_icons":
1814                     // Update the icon.
1815                     if (sharedPreferences.getBoolean(context.getString(R.string.display_additional_app_bar_icons_key), false)) {
1816                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1817                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_day);
1818                         } else {
1819                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_night);
1820                         }
1821                     } else {
1822                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1823                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_day);
1824                         } else {
1825                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_night);
1826                         }
1827                     }
1828                     break;
1829
1830                 case "app_theme":
1831                     // Get the new theme.
1832                     String newAppTheme = sharedPreferences.getString("app_theme", context.getString(R.string.app_theme_default_value));
1833
1834                     // Update the system according to the new theme.  A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1835                     if (newAppTheme.equals(appThemeEntryValuesStringArray[1])) {  // The light theme is selected.
1836                         // Update the theme preference summary text.
1837                         appThemePreference.setSummary(appThemeEntriesStringArray[1]);
1838
1839                         // Apply the new theme.
1840                         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
1841                     } else if (newAppTheme.equals(appThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
1842                         // Update the theme preference summary text.
1843                         appThemePreference.setSummary(appThemeEntriesStringArray[2]);
1844
1845                         // Apply the new theme.
1846                         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
1847                     } else {  // The system default theme is selected.
1848                         // Update the theme preference summary text.
1849                         appThemePreference.setSummary(appThemeEntriesStringArray[0]);
1850
1851                         // Apply the new theme.
1852                         if (Build.VERSION.SDK_INT >= 28) {  // The system default theme is supported.
1853                             // Follow the system default theme.
1854                             AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
1855                         } else {// The system default theme is not supported.
1856                             // Follow the battery saver mode.
1857                             AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
1858                         }
1859                     }
1860
1861                     // Update the current theme status.
1862                     currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
1863                     break;
1864
1865                 case "webview_theme":
1866                     // Get the new WebView theme.
1867                     String newWebViewTheme = sharedPreferences.getString("webview_theme", context.getString(R.string.webview_theme_default_value));
1868
1869                     // Define a new WebView theme entry number.
1870                     int newWebViewThemeEntryNumber;
1871
1872                     // Get the webView theme entry number that matches the new WebView theme.  A switch statement cannot be used because the theme entry values string array is not a compile time constant.
1873                     if (newWebViewTheme.equals(webViewThemeEntriesStringArray[1])) {  // The light theme is selected.
1874                         // Store the new WebView theme entry number.
1875                         newWebViewThemeEntryNumber = 1;
1876                     } else if (newWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
1877                         // Store the WebView theme entry number.
1878                         newWebViewThemeEntryNumber = 2;
1879                     } else {  // The system default theme is selected.
1880                         // Store the WebView theme entry number.
1881                         newWebViewThemeEntryNumber = 0;
1882                     }
1883
1884                     // Update the icon.
1885                     switch (newWebViewThemeEntryNumber) {
1886                         case 0:  // The system default WebView theme is selected.
1887                             // Set the icon according to the app theme.
1888                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1889                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
1890                             } else {
1891                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
1892                             }
1893                             break;
1894
1895                         case 1:  // The system default WebView theme is selected.
1896                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1897                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
1898                             } else {
1899                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_night);
1900                             }
1901                             break;
1902
1903                         case 2:  // The system default WebView theme is selected.
1904                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1905                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_day);
1906                             } else {
1907                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
1908                             }
1909                             break;
1910                     }
1911
1912                     // Set the current theme as the summary text for the preference.
1913                     webViewThemePreference.setSummary(webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]);
1914                     break;
1915
1916                 case "wide_viewport":
1917                     // Update the icon.
1918                     if (sharedPreferences.getBoolean("wide_viewport", true)) {
1919                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1920                             wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_night);
1921                         } else {
1922                             wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_day);
1923                         }
1924                     } else {
1925                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1926                             wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_night);
1927                         } else {
1928                             wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_day);
1929                         }
1930                     }
1931                     break;
1932
1933                 case "display_webpage_images":
1934                     // Update the icon.
1935                     if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1936                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1937                             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_night);
1938                         } else {
1939                             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_day);
1940                         }
1941                     } else {
1942                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1943                             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_night);
1944                         } else {
1945                             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_day);
1946                         }
1947                     }
1948                     break;
1949             }
1950         };
1951     }
1952
1953     private void restartPrivacyBrowser() {
1954         // Create an intent to restart Privacy Browser.
1955         Intent restartIntent = requireActivity().getParentActivityIntent();
1956
1957         // Assert that the intent is not null to remove the lint error below.
1958         assert restartIntent != null;
1959
1960         // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack.  It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1961         restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1962
1963         // Create a handler to restart the activity.
1964         Handler restartHandler = new Handler(Looper.getMainLooper());
1965
1966         // Create a runnable to restart the activity.
1967         Runnable restartRunnable = () -> {
1968             // Restart the activity.
1969             startActivity(restartIntent);
1970
1971             // Kill this instance of Privacy Browser.  Otherwise, the app exhibits sporadic behavior after the restart.
1972             System.exit(0);
1973         };
1974
1975         // Restart the activity after 300 milliseconds, so that the app has enough time to save the change to the preference.
1976         restartHandler.postDelayed(restartRunnable, 300);
1977     }
1978 }