]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java
Fix a crash when opening a drawer while restarting. https://redmine.stoutner.com...
[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
984     // The listener should be unregistered when the app is paused.
985     @Override
986     public void onPause() {
987         // Run the default commands.
988         super.onPause();
989
990         // Get a handle for the shared preferences.
991         SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
992
993         // Unregister the shared preference listener.
994         sharedPreferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
995     }
996
997     // The listener should be re-registered when the app is resumed.
998     @Override
999     public void onResume() {
1000         // Run the default commands.
1001         super.onResume();
1002
1003         // Get a new shared preference change listener.
1004         sharedPreferenceChangeListener = getSharedPreferenceChangeListener(requireContext());
1005
1006         // Get a handle for the shared preferences.
1007         SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
1008
1009         // Re-register the shared preference listener.
1010         sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
1011     }
1012
1013     // 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.
1014     // This can be removed at some future point, perhaps after the switch to PreferenceScreenCompat.  It isn't an issue in Privacy Cell.
1015     private SharedPreferences.OnSharedPreferenceChangeListener getSharedPreferenceChangeListener(Context context) {
1016         // Return the shared preference change listener.
1017         return (SharedPreferences sharedPreferences, String key) -> {
1018             switch (key) {
1019                 case "javascript":
1020                     // Update the icons and the DOM storage preference status.
1021                     if (sharedPreferences.getBoolean("javascript", false)) {  // The JavaScript preference is enabled.
1022                         // Update the icon for the JavaScript preference.
1023                         javaScriptPreference.setIcon(R.drawable.javascript_enabled);
1024
1025                         // Update the status of the DOM storage preference.
1026                         domStoragePreference.setEnabled(true);
1027
1028                         // Update the icon for the DOM storage preference.
1029                         if (sharedPreferences.getBoolean("dom_storage", false)) {
1030                             domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1031                         } else {
1032                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1033                                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_day);
1034                             } else {
1035                                 domStoragePreference.setIcon(R.drawable.dom_storage_disabled_night);
1036                             }
1037                         }
1038                     } else {  // The JavaScript preference is disabled.
1039                         // Update the icon for the JavaScript preference.
1040                         javaScriptPreference.setIcon(R.drawable.privacy_mode);
1041
1042                         // Update the status of the DOM storage preference.
1043                         domStoragePreference.setEnabled(false);
1044
1045                         // Set the icon for DOM storage preference to be ghosted.
1046                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1047                             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_day);
1048                         } else {
1049                             domStoragePreference.setIcon(R.drawable.dom_storage_ghosted_night);
1050                         }
1051                     }
1052                     break;
1053
1054                 case "cookies":
1055                     // Update the icon.
1056                     if (sharedPreferences.getBoolean(context.getString(R.string.cookies_key), false)) {
1057                         cookiesPreference.setIcon(R.drawable.cookies_enabled);
1058                     } else {
1059                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1060                             cookiesPreference.setIcon(R.drawable.cookies_disabled_day);
1061                         } else {
1062                             cookiesPreference.setIcon(R.drawable.cookies_disabled_night);
1063                         }
1064                     }
1065                     break;
1066
1067                 case "dom_storage":
1068                     // Update the icon.
1069                     if (sharedPreferences.getBoolean("dom_storage", false)) {
1070                         domStoragePreference.setIcon(R.drawable.dom_storage_enabled);
1071                     } else {
1072                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1073                             domStoragePreference.setIcon(R.drawable.dom_storage_disabled_day);
1074                         } else {
1075                             domStoragePreference.setIcon(R.drawable.dom_storage_disabled_night);
1076                         }
1077                     }
1078                     break;
1079
1080                 // Save form data can be removed once the minimum API >= 26.
1081                 case "save_form_data":
1082                     // Update the icon.
1083                     if (sharedPreferences.getBoolean("save_form_data", false)) {
1084                         formDataPreference.setIcon(R.drawable.form_data_enabled);
1085                     } else {
1086                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1087                             formDataPreference.setIcon(R.drawable.form_data_disabled_day);
1088                         } else {
1089                             formDataPreference.setIcon(R.drawable.form_data_disabled_night);
1090                         }
1091                     }
1092                     break;
1093
1094                 case "user_agent":
1095                     // Get the new user agent name.
1096                     String newUserAgentName = sharedPreferences.getString("user_agent", context.getString(R.string.user_agent_default_value));
1097
1098                     // Get the array position for the new user agent name.
1099                     int newUserAgentArrayPosition = userAgentNamesArray.getPosition(newUserAgentName);
1100
1101                     // Get the translated new user agent name.
1102                     String translatedNewUserAgentName = translatedUserAgentNamesArray[newUserAgentArrayPosition];
1103
1104                     // Populate the user agent summary.
1105                     switch (newUserAgentArrayPosition) {
1106                         case MainWebViewActivity.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT:
1107                             // Get the user agent text from the webview (which changes based on the version of Android and WebView installed).
1108                             userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + defaultUserAgent);
1109
1110                             // Disable the custom user agent preference.
1111                             customUserAgentPreference.setEnabled(false);
1112
1113                             // Set the custom user agent preference icon according to the theme.
1114                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1115                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_night);
1116                             } else {
1117                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_day);
1118                             }
1119                             break;
1120
1121                         case MainWebViewActivity.SETTINGS_CUSTOM_USER_AGENT:
1122                             // Set the summary text.
1123                             userAgentPreference.setSummary(R.string.custom_user_agent);
1124
1125                             // Enable the custom user agent preference.
1126                             customUserAgentPreference.setEnabled(true);
1127
1128                             // Set the custom user agent preference icon according to the theme.
1129                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1130                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_night);
1131                             } else {
1132                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_enabled_day);
1133                             }
1134                             break;
1135
1136                         default:
1137                             // Get the user agent summary from the user agent data array.
1138                             userAgentPreference.setSummary(translatedNewUserAgentName + ":\n" + userAgentDataArray[newUserAgentArrayPosition]);
1139
1140                             // Disable the custom user agent preference.
1141                             customUserAgentPreference.setEnabled(false);
1142
1143                             // Set the custom user agent preference icon according to the theme.
1144                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1145                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_night);
1146                             } else {
1147                                 customUserAgentPreference.setIcon(R.drawable.custom_user_agent_ghosted_day);
1148                             }
1149                     }
1150                     break;
1151
1152                 case "custom_user_agent":
1153                     // Set the new custom user agent as the summary text for the preference.
1154                     customUserAgentPreference.setSummary(sharedPreferences.getString("custom_user_agent", context.getString(R.string.custom_user_agent_default_value)));
1155                     break;
1156
1157                 case "incognito_mode":
1158                     // Update the icon.
1159                     if (sharedPreferences.getBoolean("incognito_mode", false)) {
1160                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1161                             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_night);
1162                         } else {
1163                             incognitoModePreference.setIcon(R.drawable.incognito_mode_enabled_day);
1164                         }
1165                     } else {
1166                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1167                             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_night);
1168                         } else {
1169                             incognitoModePreference.setIcon(R.drawable.incognito_mode_disabled_day);
1170                         }
1171                     }
1172                     break;
1173
1174                 case "allow_screenshots":
1175                     // Update the icon.
1176                     if (sharedPreferences.getBoolean(context.getString(R.string.allow_screenshots_key), false)) {
1177                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1178                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_day);
1179                         } else {
1180                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_enabled_night);
1181                         }
1182                     } else {
1183                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1184                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_day);
1185                         } else {
1186                             allowScreenshotsPreference.setIcon(R.drawable.allow_screenshots_disabled_night);
1187                         }
1188                     }
1189
1190                     // Restart Privacy Browser.
1191                     restartPrivacyBrowser();
1192                     break;
1193
1194                 case "easylist":
1195                     // Update the icon.
1196                     if (sharedPreferences.getBoolean("easylist", true)) {
1197                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1198                             easyListPreference.setIcon(R.drawable.block_ads_enabled_night);
1199                         } else {
1200                             easyListPreference.setIcon(R.drawable.block_ads_enabled_day);
1201                         }
1202                     } else {
1203                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1204                             easyListPreference.setIcon(R.drawable.block_ads_disabled_night);
1205                         } else {
1206                             easyListPreference.setIcon(R.drawable.block_ads_disabled_day);
1207                         }
1208                     }
1209                     break;
1210
1211                 case "easyprivacy":
1212                     // Update the icon.
1213                     if (sharedPreferences.getBoolean("easyprivacy", true)) {
1214                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1215                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
1216                         } else {
1217                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
1218                         }
1219                     } else {
1220                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1221                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
1222                         } else {
1223                             easyPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
1224                         }
1225                     }
1226                     break;
1227
1228                 case "fanboys_annoyance_list":
1229                     boolean currentFanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
1230                     boolean currentFanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
1231
1232                     // Update the Fanboy icons.
1233                     if (currentFanboyAnnoyanceList) {  // Fanboy's annoyance list is enabled.
1234                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1235                             // Update the Fanboy's annoyance list icon.
1236                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_night);
1237
1238                             // Update the Fanboy's social blocking list icon.
1239                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_night);
1240                         } else {
1241                             // Update the Fanboy's annoyance list icon.
1242                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_enabled_day);
1243
1244                             // Update the Fanboy's social blocking list icon.
1245                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_ghosted_day);
1246                         }
1247                     } else {  // Fanboy's annoyance list is disabled.
1248                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1249                             // Update the Fanboy's annoyance list icon.
1250                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_night);
1251
1252                             // Update the Fanboy's social blocking list icon.
1253                             if (currentFanboySocialBlockingList) {
1254                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_night);
1255                             } else {
1256                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_night);
1257                             }
1258                         } else {
1259                             // Update the Fanboy's annoyance list icon.
1260                             fanboyAnnoyanceListPreference.setIcon(R.drawable.social_media_disabled_day);
1261
1262                             // Update the Fanboy's social blocking list icon.
1263                             if (currentFanboySocialBlockingList) {
1264                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_day);
1265                             } else {
1266                                 fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_day);
1267                             }
1268                         }
1269                     }
1270
1271                     // Only enable Fanboy's social blocking list preference if Fanboy's annoyance list preference is disabled.
1272                     fanboySocialBlockingListPreference.setEnabled(!currentFanboyAnnoyanceList);
1273                     break;
1274
1275                 case "fanboys_social_blocking_list":
1276                     // Update the icon.
1277                     if (sharedPreferences.getBoolean("fanboys_social_blocking_list", true)) {
1278                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1279                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_night);
1280                         } else {
1281                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_enabled_day);
1282                         }
1283                     } else {
1284                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1285                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_night);
1286                         } else {
1287                             fanboySocialBlockingListPreference.setIcon(R.drawable.social_media_disabled_day);
1288                         }
1289                     }
1290                     break;
1291
1292                 case "ultralist":
1293                     // Update the icon.
1294                     if (sharedPreferences.getBoolean("ultralist", true)) {
1295                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1296                             ultraListPreference.setIcon(R.drawable.block_ads_enabled_night);
1297                         } else {
1298                             ultraListPreference.setIcon(R.drawable.block_ads_enabled_day);
1299                         }
1300                     } else {
1301                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1302                             ultraListPreference.setIcon(R.drawable.block_ads_disabled_night);
1303                         } else {
1304                             ultraListPreference.setIcon(R.drawable.block_ads_disabled_day);
1305                         }
1306                     }
1307                     break;
1308
1309                 case "ultraprivacy":
1310                     // Update the icon.
1311                     if (sharedPreferences.getBoolean("ultraprivacy", true)) {
1312                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1313                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_night);
1314                         } else {
1315                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_enabled_day);
1316                         }
1317                     } else {
1318                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1319                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_night);
1320                         } else {
1321                             ultraPrivacyPreference.setIcon(R.drawable.block_tracking_disabled_day);
1322                         }
1323                     }
1324                     break;
1325
1326                 case "block_all_third_party_requests":
1327                     // Update the icon.
1328                     if (sharedPreferences.getBoolean("block_all_third_party_requests", false)) {
1329                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1330                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_night);
1331                         } else {
1332                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_enabled_day);
1333                         }
1334                     } else {
1335                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1336                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_night);
1337                         } else {
1338                             blockAllThirdPartyRequestsPreference.setIcon(R.drawable.block_all_third_party_requests_disabled_day);
1339                         }
1340                     }
1341                     break;
1342
1343                 case "google_analytics":
1344                     // Update the icon.
1345                     if (sharedPreferences.getBoolean("google_analytics", true)) {
1346                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1347                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_night);
1348                         } else {
1349                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_enabled_day);
1350                         }
1351                     } else {
1352                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1353                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_night);
1354                         } else {
1355                             googleAnalyticsPreference.setIcon(R.drawable.modify_url_disabled_day);
1356                         }
1357                     }
1358                     break;
1359
1360                 case "facebook_click_ids":
1361                     // Update the icon.
1362                     if (sharedPreferences.getBoolean("facebook_click_ids", true)) {
1363                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1364                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_night);
1365                         } else {
1366                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_enabled_day);
1367                         }
1368                     } else {
1369                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1370                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_night);
1371                         } else {
1372                             facebookClickIdsPreference.setIcon(R.drawable.modify_url_disabled_day);
1373                         }
1374                     }
1375                     break;
1376
1377                 case "twitter_amp_redirects":
1378                     // Update the icon.
1379                     if (sharedPreferences.getBoolean("twitter_amp_redirects", true)) {
1380                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1381                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_night);
1382                         } else {
1383                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_enabled_day);
1384                         }
1385                     } else {
1386                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1387                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_night);
1388                         } else {
1389                             twitterAmpRedirectsPreference.setIcon(R.drawable.modify_url_disabled_day);
1390                         }
1391                     }
1392                     break;
1393
1394                 case "search":
1395                     // Store the new search string.
1396                     String newSearchString = sharedPreferences.getString("search", context.getString(R.string.search_default_value));
1397
1398                     // Update the search and search custom URL preferences.
1399                     if (newSearchString.equals("Custom URL")) {  // `Custom URL` is selected.
1400                         // Set the summary text to `R.string.custom_url`, which is translated.
1401                         searchPreference.setSummary(R.string.custom_url);
1402
1403                         // Enable `searchCustomURLPreference`.
1404                         searchCustomURLPreference.setEnabled(true);
1405
1406                         // Set the `searchCustomURLPreference` according to the theme.
1407                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1408                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_night);
1409                         } else {
1410                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_enabled_day);
1411                         }
1412                     } else {  // `Custom URL` is not selected.
1413                         // Set the summary text to `newSearchString`.
1414                         searchPreference.setSummary(newSearchString);
1415
1416                         // Disable `searchCustomURLPreference`.
1417                         searchCustomURLPreference.setEnabled(false);
1418
1419                         // Set the `searchCustomURLPreference` according to the theme.
1420                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1421                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_night);
1422                         } else {
1423                             searchCustomURLPreference.setIcon(R.drawable.search_custom_url_ghosted_day);
1424                         }
1425                     }
1426                     break;
1427
1428                 case "search_custom_url":
1429                     // Set the new search custom URL as the summary text for the preference.
1430                     searchCustomURLPreference.setSummary(sharedPreferences.getString("search_custom_url", context.getString(R.string.search_custom_url_default_value)));
1431                     break;
1432
1433                 case "proxy":
1434                     // Get current proxy string.
1435                     String currentProxyString = sharedPreferences.getString("proxy", context.getString(R.string.proxy_default_value));
1436
1437                     // Update the summary text for the proxy preference.
1438                     switch (currentProxyString) {
1439                         case ProxyHelper.NONE:
1440                             proxyPreference.setSummary(context.getString(R.string.no_proxy_enabled));
1441                             break;
1442
1443                         case ProxyHelper.TOR:
1444                             if (Build.VERSION.SDK_INT == 19) {  // Proxying through SOCKS doesn't work on Android KitKat.
1445                                 proxyPreference.setSummary(context.getString(R.string.tor_enabled_kitkat));
1446                             } else {
1447                                 proxyPreference.setSummary(context.getString(R.string.tor_enabled));
1448                             }
1449                             break;
1450
1451                         case ProxyHelper.I2P:
1452                             proxyPreference.setSummary(context.getString(R.string.i2p_enabled));
1453                             break;
1454
1455                         case ProxyHelper.CUSTOM:
1456                             proxyPreference.setSummary(context.getString(R.string.custom_proxy));
1457                             break;
1458                     }
1459
1460                     // Update the status of the custom URL preference.
1461                     proxyCustomUrlPreference.setEnabled(currentProxyString.equals("Custom"));
1462
1463                     // Update the icons.
1464                     if (currentProxyString.equals("None")) {  // Proxying is disabled.
1465                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
1466                             // Set the main proxy icon to be disabled
1467                             proxyPreference.setIcon(R.drawable.proxy_disabled_night);
1468
1469                             // Set the custom proxy URL icon to be ghosted.
1470                             proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
1471                         } else {  // Light theme.
1472                             // Set the main proxy icon to be disabled.
1473                             proxyPreference.setIcon(R.drawable.proxy_disabled_day);
1474
1475                             // Set the custom proxy URL icon to be ghosted.
1476                             proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
1477                         }
1478                     } else {  // Proxying is enabled.
1479                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
1480                             // Set the main proxy icon to be enabled.
1481                             proxyPreference.setIcon(R.drawable.proxy_enabled_night);
1482
1483                             /// Set the custom proxy URL icon according to its status.
1484                             if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
1485                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_night);
1486                             } else {  // Custom proxy is disabled.
1487                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_night);
1488                             }
1489                         } else {  // Light theme.
1490                             // Set the main proxy icon to be enabled.
1491                             proxyPreference.setIcon(R.drawable.proxy_enabled_day);
1492
1493                             // Set the custom proxy URL icon according to its status.
1494                             if (proxyCustomUrlPreference.isEnabled()) {  // Custom proxy is enabled.
1495                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_enabled_day);
1496                             } else {  // Custom proxy is disabled.
1497                                 proxyCustomUrlPreference.setIcon(R.drawable.proxy_ghosted_day);
1498                             }
1499                         }
1500                     }
1501                     break;
1502
1503                 case "proxy_custom_url":
1504                     // Set the summary text for the proxy custom URL.
1505                     proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value)));
1506                     break;
1507
1508                 case "full_screen_browsing_mode":
1509                     if (sharedPreferences.getBoolean("full_screen_browsing_mode", false)) {  // Full screen browsing is enabled.
1510                         // Set the full screen browsing mode preference icon according to the theme.
1511                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1512                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_night);
1513                         } else {
1514                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_enabled_day);
1515                         }
1516
1517                         // Set the hide app bar preference icon.
1518                         if (sharedPreferences.getBoolean("hide_app_bar", true)) {  //  Hide app bar is enabled.
1519                             // Set the icon according to the theme.
1520                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1521                                 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1522                             } else {
1523                                 hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1524                             }
1525                         } else {  // Hide app bar is disabled.
1526                             // Set the icon according to the theme.
1527                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1528                                 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1529                             } else {
1530                                 hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1531                             }
1532                         }
1533                     } else {  // Full screen browsing is disabled.
1534                         // Update the icons according to the theme.
1535                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1536                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_night);
1537                             hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_night);
1538                         } else {
1539                             fullScreenBrowsingModePreference.setIcon(R.drawable.full_screen_disabled_day);
1540                             hideAppBarPreference.setIcon(R.drawable.app_bar_ghosted_day);
1541                         }
1542                     }
1543                     break;
1544
1545                 case "hide_app_bar":
1546                     // Update the icon.
1547                     if (sharedPreferences.getBoolean("hide_app_bar", true)) {  // Hide app bar is enabled.
1548                         // Set the icon according to the theme.
1549                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1550                             hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1551                         } else {
1552                             hideAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1553                         }
1554                     } else {  // Hide app bar is disabled.
1555                         // Set the icon according to the theme.
1556                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1557                             hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1558                         } else {
1559                             hideAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1560                         }
1561                     }
1562                     break;
1563
1564                 case "clear_everything":
1565                     // Store the new clear everything status
1566                     boolean newClearEverythingBoolean = sharedPreferences.getBoolean("clear_everything", true);
1567
1568                     // Update the status of the clear and exit preferences.
1569                     clearCookiesPreference.setEnabled(!newClearEverythingBoolean);
1570                     clearDomStoragePreference.setEnabled(!newClearEverythingBoolean);
1571                     clearFormDataPreference.setEnabled(!newClearEverythingBoolean);  // This line can be removed once the minimum API >= 26.
1572                     clearLogcatPreference.setEnabled(!newClearEverythingBoolean);
1573                     clearCachePreference.setEnabled(!newClearEverythingBoolean);
1574
1575                     // Update the clear everything preference icon.
1576                     if (newClearEverythingBoolean) {
1577                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1578                             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_day);
1579                         } else {
1580                             clearEverythingPreference.setIcon(R.drawable.clear_everything_enabled_night);
1581                         }
1582                     } else {
1583                         clearEverythingPreference.setIcon(R.drawable.clear_everything_disabled);
1584                     }
1585
1586                     // Update the clear cookies preference icon.
1587                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cookies", true)) {
1588                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1589                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_day);
1590                         } else {
1591                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_night);
1592                         }
1593                     } else {
1594                         clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1595                     }
1596
1597                     // Update the clear dom storage preference icon.
1598                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_dom_storage", true)) {
1599                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1600                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_day);
1601                         } else {
1602                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_night);
1603                         }
1604                     } else {
1605                         clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1606                     }
1607
1608                     // Update the clear form data preference icon if the API < 26.
1609                     if (Build.VERSION.SDK_INT < 26) {
1610                         if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_form_data", true)) {
1611                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1612                                 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_day);
1613                             } else {
1614                                 clearFormDataPreference.setIcon(R.drawable.form_data_cleared_night);
1615                             }
1616                         } else {
1617                             clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1618                         }
1619                     }
1620
1621                     // Update the clear logcat preference icon.
1622                     if (newClearEverythingBoolean || sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1623                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1624                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_day);
1625                         } else {
1626                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_night);
1627                         }
1628                     } else {
1629                         clearLogcatPreference.setIcon(R.drawable.cache_warning);
1630                     }
1631
1632                     // Update the clear cache preference icon.
1633                     if (newClearEverythingBoolean || sharedPreferences.getBoolean("clear_cache", true)) {
1634                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1635                             clearCachePreference.setIcon(R.drawable.cache_cleared_day);
1636                         } else {
1637                             clearCachePreference.setIcon(R.drawable.cache_cleared_night);
1638                         }
1639                     } else {
1640                         clearCachePreference.setIcon(R.drawable.cache_warning);
1641                     }
1642                     break;
1643
1644                 case "clear_cookies":
1645                     // Update the icon.
1646                     if (sharedPreferences.getBoolean("clear_cookies", true)) {
1647                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1648                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_day);
1649                         } else {
1650                             clearCookiesPreference.setIcon(R.drawable.cookies_cleared_night);
1651                         }
1652                     } else {
1653                         clearCookiesPreference.setIcon(R.drawable.cookies_warning);
1654                     }
1655                     break;
1656
1657                 case "clear_dom_storage":
1658                     // Update the icon.
1659                     if (sharedPreferences.getBoolean("clear_dom_storage", true)) {
1660                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1661                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_day);
1662                         } else {
1663                             clearDomStoragePreference.setIcon(R.drawable.dom_storage_cleared_night);
1664                         }
1665                     } else {
1666                         clearDomStoragePreference.setIcon(R.drawable.dom_storage_warning);
1667                     }
1668                     break;
1669
1670                 // This section can be removed once the minimum API >= 26.
1671                 case "clear_form_data":
1672                     // Update the icon.
1673                     if (sharedPreferences.getBoolean("clear_form_data", true)) {
1674                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1675                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared_day);
1676                         } else {
1677                             clearFormDataPreference.setIcon(R.drawable.form_data_cleared_night);
1678                         }
1679                     } else {
1680                         clearFormDataPreference.setIcon(R.drawable.form_data_warning);
1681                     }
1682                     break;
1683
1684                 case "clear_logcat":
1685                     // Update the icon.
1686                     if (sharedPreferences.getBoolean(context.getString(R.string.clear_logcat_key), true)) {
1687                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1688                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_day);
1689                         } else {
1690                             clearLogcatPreference.setIcon(R.drawable.bug_cleared_night);
1691                         }
1692                     } else {
1693                         clearLogcatPreference.setIcon(R.drawable.bug_warning);
1694                     }
1695                     break;
1696
1697                 case "clear_cache":
1698                     // Update the icon.
1699                     if (sharedPreferences.getBoolean("clear_cache", true)) {
1700                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1701                             clearCachePreference.setIcon(R.drawable.cache_cleared_day);
1702                         } else {
1703                             clearCachePreference.setIcon(R.drawable.cache_cleared_night);
1704                         }
1705                     } else {
1706                         clearCachePreference.setIcon(R.drawable.cache_warning);
1707                     }
1708                     break;
1709
1710                 case "homepage":
1711                     // Set the new homepage URL as the summary text for the Homepage preference.
1712                     homepagePreference.setSummary(sharedPreferences.getString("homepage", context.getString(R.string.homepage_default_value)));
1713                     break;
1714
1715                 case "font_size":
1716                     // Update the font size summary text.
1717                     fontSizePreference.setSummary(sharedPreferences.getString("font_size", context.getString(R.string.font_size_default_value)) + "%");
1718                     break;
1719
1720                 case "open_intents_in_new_tab":
1721                     // Update the icon.
1722                     if (sharedPreferences.getBoolean("open_intents_in_new_tab", true)) {
1723                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1724                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_day);
1725                         } else {
1726                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_enabled_night);
1727                         }
1728                     } else {
1729                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1730                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_day);
1731                         } else {
1732                             openIntentsInNewTabPreference.setIcon(R.drawable.tab_disabled_night);
1733                         }
1734                     }
1735                     break;
1736
1737                 case "swipe_to_refresh":
1738                     // Update the icon.
1739                     if (sharedPreferences.getBoolean("swipe_to_refresh", true)) {
1740                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1741                             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_day);
1742                         } else {
1743                             swipeToRefreshPreference.setIcon(R.drawable.refresh_enabled_night);
1744                         }
1745                     } else {
1746                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1747                             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_day);
1748                         } else {
1749                             swipeToRefreshPreference.setIcon(R.drawable.refresh_disabled_night);
1750                         }
1751                     }
1752                     break;
1753
1754                 case "download_with_external_app":
1755                     // Update the icon.
1756                     if (sharedPreferences.getBoolean(context.getString(R.string.download_with_external_app_key), false)) {
1757                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1758                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_day);
1759                         } else {
1760                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_enabled_night);
1761                         }
1762                     } else {
1763                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1764                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_day);
1765                         } else {
1766                             downloadWithExternalAppPreference.setIcon(R.drawable.download_with_external_app_disabled_night);
1767                         }
1768                     }
1769                     break;
1770
1771                 case "scroll_app_bar":
1772                     // Update the icon.
1773                     if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
1774                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1775                             scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
1776                         } else {
1777                             scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_night);
1778                         }
1779                     } else {
1780                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1781                             scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_day);
1782                         } else {
1783                             scrollAppBarPreference.setIcon(R.drawable.app_bar_disabled_night);
1784                         }
1785                     }
1786                     break;
1787
1788                 case "bottom_app_bar":
1789                     // Update the icon.
1790                     if (sharedPreferences.getBoolean(context.getString(R.string.bottom_app_bar_key), false)) {
1791                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1792                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_day);
1793                         } else {
1794                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_enabled_night);
1795                         }
1796                     } else {
1797                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1798                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_day);
1799                         } else {
1800                             bottomAppBarPreference.setIcon(R.drawable.bottom_app_bar_disabled_night);
1801                         }
1802                     }
1803
1804                     // Restart Privacy Browser.
1805                     restartPrivacyBrowser();
1806                     break;
1807
1808                 case "display_additional_app_bar_icons":
1809                     // Update the icon.
1810                     if (sharedPreferences.getBoolean(context.getString(R.string.display_additional_app_bar_icons_key), false)) {
1811                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1812                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_day);
1813                         } else {
1814                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_enabled_night);
1815                         }
1816                     } else {
1817                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1818                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_day);
1819                         } else {
1820                             displayAdditionalAppBarIconsPreference.setIcon(R.drawable.more_disabled_night);
1821                         }
1822                     }
1823                     break;
1824
1825                 case "app_theme":
1826                     // Get the new theme.
1827                     String newAppTheme = sharedPreferences.getString("app_theme", context.getString(R.string.app_theme_default_value));
1828
1829                     // 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.
1830                     if (newAppTheme.equals(appThemeEntryValuesStringArray[1])) {  // The light theme is selected.
1831                         // Update the theme preference summary text.
1832                         appThemePreference.setSummary(appThemeEntriesStringArray[1]);
1833
1834                         // Apply the new theme.
1835                         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
1836                     } else if (newAppTheme.equals(appThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
1837                         // Update the theme preference summary text.
1838                         appThemePreference.setSummary(appThemeEntriesStringArray[2]);
1839
1840                         // Apply the new theme.
1841                         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
1842                     } else {  // The system default theme is selected.
1843                         // Update the theme preference summary text.
1844                         appThemePreference.setSummary(appThemeEntriesStringArray[0]);
1845
1846                         // Apply the new theme.
1847                         if (Build.VERSION.SDK_INT >= 28) {  // The system default theme is supported.
1848                             // Follow the system default theme.
1849                             AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
1850                         } else {// The system default theme is not supported.
1851                             // Follow the battery saver mode.
1852                             AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY);
1853                         }
1854                     }
1855
1856                     // Update the current theme status.
1857                     currentThemeStatus = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
1858                     break;
1859
1860                 case "webview_theme":
1861                     // Get the new WebView theme.
1862                     String newWebViewTheme = sharedPreferences.getString("webview_theme", context.getString(R.string.webview_theme_default_value));
1863
1864                     // Define a new WebView theme entry number.
1865                     int newWebViewThemeEntryNumber;
1866
1867                     // 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.
1868                     if (newWebViewTheme.equals(webViewThemeEntriesStringArray[1])) {  // The light theme is selected.
1869                         // Store the new WebView theme entry number.
1870                         newWebViewThemeEntryNumber = 1;
1871                     } else if (newWebViewTheme.equals(webViewThemeEntryValuesStringArray[2])) {  // The dark theme is selected.
1872                         // Store the WebView theme entry number.
1873                         newWebViewThemeEntryNumber = 2;
1874                     } else {  // The system default theme is selected.
1875                         // Store the WebView theme entry number.
1876                         newWebViewThemeEntryNumber = 0;
1877                     }
1878
1879                     // Update the icon.
1880                     switch (newWebViewThemeEntryNumber) {
1881                         case 0:  // The system default WebView theme is selected.
1882                             // Set the icon according to the app theme.
1883                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1884                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
1885                             } else {
1886                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
1887                             }
1888                             break;
1889
1890                         case 1:  // The system default WebView theme is selected.
1891                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1892                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_day);
1893                             } else {
1894                                 webViewThemePreference.setIcon(R.drawable.webview_light_theme_night);
1895                             }
1896                             break;
1897
1898                         case 2:  // The system default WebView theme is selected.
1899                             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
1900                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_day);
1901                             } else {
1902                                 webViewThemePreference.setIcon(R.drawable.webview_dark_theme_night);
1903                             }
1904                             break;
1905                     }
1906
1907                     // Set the current theme as the summary text for the preference.
1908                     webViewThemePreference.setSummary(webViewThemeEntriesStringArray[newWebViewThemeEntryNumber]);
1909                     break;
1910
1911                 case "wide_viewport":
1912                     // Update the icon.
1913                     if (sharedPreferences.getBoolean("wide_viewport", true)) {
1914                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1915                             wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_night);
1916                         } else {
1917                             wideViewportPreference.setIcon(R.drawable.wide_viewport_enabled_day);
1918                         }
1919                     } else {
1920                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1921                             wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_night);
1922                         } else {
1923                             wideViewportPreference.setIcon(R.drawable.wide_viewport_disabled_day);
1924                         }
1925                     }
1926                     break;
1927
1928                 case "display_webpage_images":
1929                     // Update the icon.
1930                     if (sharedPreferences.getBoolean("display_webpage_images", true)) {
1931                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1932                             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_night);
1933                         } else {
1934                             displayWebpageImagesPreference.setIcon(R.drawable.images_enabled_day);
1935                         }
1936                     } else {
1937                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {
1938                             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_night);
1939                         } else {
1940                             displayWebpageImagesPreference.setIcon(R.drawable.images_disabled_day);
1941                         }
1942                     }
1943                     break;
1944             }
1945         };
1946     }
1947
1948     private void restartPrivacyBrowser() {
1949         // Create an intent to restart Privacy Browser.
1950         Intent restartIntent = requireActivity().getParentActivityIntent();
1951
1952         // Assert that the intent is not null to remove the lint error below.
1953         assert restartIntent != null;
1954
1955         // `Intent.FLAG_ACTIVITY_CLEAR_TASK` removes all activities from the stack.  It requires `Intent.FLAG_ACTIVITY_NEW_TASK`.
1956         restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1957
1958         // Create a handler to restart the activity.
1959         Handler restartHandler = new Handler(Looper.getMainLooper());
1960
1961         // Create a runnable to restart the activity.
1962         Runnable restartRunnable = () -> {
1963             // Restart the activity.
1964             startActivity(restartIntent);
1965
1966             // Kill this instance of Privacy Browser.  Otherwise, the app exhibits sporadic behavior after the restart.
1967             System.exit(0);
1968         };
1969
1970         // Restart the activity after 400 milliseconds, so that the app has enough time to save the change to the preference.
1971         restartHandler.postDelayed(restartRunnable, 400);
1972     }
1973 }