2c80301ba416df58bc863398186043b5ac17a10f
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / dialogs / ViewRequestDialog.kt
1 /*
2  * Copyright © 2018-2022 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
5  *
6  * Privacy Browser Android is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Privacy Browser Android is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Privacy Browser Android.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacybrowser.dialogs
21
22 import android.app.Dialog
23 import android.content.Context
24 import android.content.DialogInterface
25 import android.content.res.Configuration
26 import android.os.Bundle
27 import android.view.View
28 import android.view.WindowManager
29 import android.widget.TextView
30
31 import androidx.appcompat.app.AlertDialog
32 import androidx.fragment.app.DialogFragment
33 import androidx.preference.PreferenceManager
34
35 import com.stoutner.privacybrowser.R
36 import com.stoutner.privacybrowser.helpers.BlocklistHelper
37
38 // Define the class constants.
39 private const val ID = "id"
40 private const val IS_LAST_REQUEST = "is_last_request"
41 private const val REQUEST_DETAILS = "request_details"
42
43 class ViewRequestDialog : DialogFragment() {
44     // Define the class variables.
45     private lateinit var viewRequestListener: ViewRequestListener
46
47     // The public interface is used to send information back to the parent activity.
48     interface ViewRequestListener {
49         // Show the previous request.
50         fun onPrevious(currentId: Int)
51
52         // Show the next request.
53         fun onNext(currentId: Int)
54     }
55
56     override fun onAttach(context: Context) {
57         // Run the default commands.
58         super.onAttach(context)
59
60         // Get a handle for the listener from the launching context.
61         viewRequestListener = context as ViewRequestListener
62     }
63
64     companion object {
65         // `@JvmStatic` will no longer be required once all the code has transitioned to Kotlin.
66         @JvmStatic
67         fun request(id: Int, isLastRequest: Boolean, requestDetails: Array<String>): ViewRequestDialog {
68             // Create a bundle.
69             val bundle = Bundle()
70
71             // Store the request details.
72             bundle.putInt(ID, id)
73             bundle.putBoolean(IS_LAST_REQUEST, isLastRequest)
74             bundle.putStringArray(REQUEST_DETAILS, requestDetails)
75
76             // Create a new instance of the view request dialog.
77             val viewRequestDialog = ViewRequestDialog()
78
79             // Add the arguments to the new dialog.
80             viewRequestDialog.arguments = bundle
81
82             // Return the new dialog.
83             return viewRequestDialog
84         }
85     }
86
87     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
88         // Get the arguments from the bundle.
89         val id = requireArguments().getInt(ID)
90         val isLastRequest = requireArguments().getBoolean(IS_LAST_REQUEST)
91         val requestDetails = requireArguments().getStringArray(REQUEST_DETAILS)!!
92
93         // Use an alert dialog builder to create the alert dialog.
94         val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
95
96         // Get the current theme status.
97         val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
98
99         // Set the icon according to the theme.
100         dialogBuilder.setIconAttribute(R.attr.blockAdsBlueIcon)
101
102         // Set the title.
103         dialogBuilder.setTitle(resources.getString(R.string.request_details) + " - " + id)
104
105         // Set the view.
106         dialogBuilder.setView(R.layout.view_request_dialog)
107
108         // Set the close button.  Using `null` as the listener closes the dialog without doing anything else.
109         dialogBuilder.setNeutralButton(R.string.close, null)
110
111         // Set the previous button.
112         dialogBuilder.setNegativeButton(R.string.previous) { _: DialogInterface?, _: Int ->
113             // Load the previous request.
114             viewRequestListener.onPrevious(id)
115         }
116
117         // Set the next button.
118         dialogBuilder.setPositiveButton(R.string.next) { _: DialogInterface?, _: Int ->
119             // Load the next request.
120             viewRequestListener.onNext(id)
121         }
122
123         // Create an alert dialog from the alert dialog builder.
124         val alertDialog = dialogBuilder.create()
125
126         // Get a handle for the shared preferences.
127         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
128
129         // Get the screenshot preference.
130         val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
131
132         // Disable screenshots if not allowed.
133         if (!allowScreenshots) {
134             // Disable screenshots.
135             alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
136         }
137
138         //The alert dialog must be shown before the contents can be modified.
139         alertDialog.show()
140
141         // Get handles for the dialog views.
142         val requestDisposition = alertDialog.findViewById<TextView>(R.id.request_disposition)!!
143         val requestUrl = alertDialog.findViewById<TextView>(R.id.request_url)!!
144         val requestBlockListLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_label)!!
145         val requestBlockList = alertDialog.findViewById<TextView>(R.id.request_blocklist)!!
146         val requestSubListLabel = alertDialog.findViewById<TextView>(R.id.request_sublist_label)!!
147         val requestSubList = alertDialog.findViewById<TextView>(R.id.request_sublist)!!
148         val requestBlockListEntriesLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_entries_label)!!
149         val requestBlockListEntries = alertDialog.findViewById<TextView>(R.id.request_blocklist_entries)!!
150         val requestBlockListOriginalEntryLabel = alertDialog.findViewById<TextView>(R.id.request_blocklist_original_entry_label)!!
151         val requestBlockListOriginalEntry = alertDialog.findViewById<TextView>(R.id.request_blocklist_original_entry)!!
152         val previousButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
153         val nextButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
154
155         // Disable the previous button if the first resource request is displayed.
156         previousButton.isEnabled = (id != 1)
157
158         // Disable the next button if the last resource request is displayed.
159         nextButton.isEnabled = !isLastRequest
160
161         // Set the request action text.
162         when (requestDetails[BlocklistHelper.REQUEST_DISPOSITION]) {
163             BlocklistHelper.REQUEST_DEFAULT -> {
164                 // Set the text.
165                 requestDisposition.setText(R.string.default_allowed)
166
167                 // Set the background color.  The deprecated `getColor()` must be used until the minimum API >= 23.
168                 @Suppress("DEPRECATION")
169                 requestDisposition.setBackgroundColor(resources.getColor(R.color.transparent))
170             }
171
172             BlocklistHelper.REQUEST_ALLOWED -> {
173                 // Set the text.
174                 requestDisposition.setText(R.string.allowed)
175
176                 // Set the background color according to the theme.  The deprecated `getColor()` must be used until the minimum API >= 23.
177                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
178                     @Suppress("DEPRECATION")
179                     requestDisposition.setBackgroundColor(resources.getColor(R.color.blue_100))
180                 } else {
181                     @Suppress("DEPRECATION")
182                     requestDisposition.setBackgroundColor(resources.getColor(R.color.blue_700_50))
183                 }
184             }
185
186             BlocklistHelper.REQUEST_THIRD_PARTY -> {
187                 // Set the text.
188                 requestDisposition.setText(R.string.third_party_blocked)
189
190                 // Set the background color according to the theme.  The deprecated `getColor()` must be used until the minimum API >= 23.
191                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
192                     @Suppress("DEPRECATION")
193                     requestDisposition.setBackgroundColor(resources.getColor(R.color.yellow_100))
194                 } else {
195                     @Suppress("DEPRECATION")
196                     requestDisposition.setBackgroundColor(resources.getColor(R.color.yellow_700_50))
197                 }
198             }
199             BlocklistHelper.REQUEST_BLOCKED -> {
200                 // Set the text.
201                 requestDisposition.setText(R.string.blocked)
202
203                 // Set the background color according to the theme.  The deprecated `getColor()` must be used until the minimum API >= 23.
204                 if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
205                     @Suppress("DEPRECATION")
206                     requestDisposition.setBackgroundColor(resources.getColor(R.color.red_100))
207                 } else {
208                     @Suppress("DEPRECATION")
209                     requestDisposition.setBackgroundColor(resources.getColor(R.color.red_700_40))
210                 }
211             }
212         }
213
214         // Display the request URL.
215         requestUrl.text = requestDetails[BlocklistHelper.REQUEST_URL]
216
217         // Modify the dialog based on the request action.
218         if (requestDetails.size == 2) {  // A default request.
219             // Hide the unused views.
220             requestBlockListLabel.visibility = View.GONE
221             requestBlockList.visibility = View.GONE
222             requestSubListLabel.visibility = View.GONE
223             requestSubList.visibility = View.GONE
224             requestBlockListEntriesLabel.visibility = View.GONE
225             requestBlockListEntries.visibility = View.GONE
226             requestBlockListOriginalEntryLabel.visibility = View.GONE
227             requestBlockListOriginalEntry.visibility = View.GONE
228         } else {  // A blocked or allowed request.
229             // Set the text on the text views.
230             requestBlockList.text = requestDetails[BlocklistHelper.REQUEST_BLOCKLIST]
231             requestBlockListEntries.text = requestDetails[BlocklistHelper.REQUEST_BLOCKLIST_ENTRIES]
232             requestBlockListOriginalEntry.text = requestDetails[BlocklistHelper.REQUEST_BLOCKLIST_ORIGINAL_ENTRY]
233             when (requestDetails[BlocklistHelper.REQUEST_SUBLIST]) {
234                 BlocklistHelper.MAIN_WHITELIST -> requestSubList.setText(R.string.main_whitelist)
235                 BlocklistHelper.FINAL_WHITELIST -> requestSubList.setText(R.string.final_whitelist)
236                 BlocklistHelper.DOMAIN_WHITELIST -> requestSubList.setText(R.string.domain_whitelist)
237                 BlocklistHelper.DOMAIN_INITIAL_WHITELIST -> requestSubList.setText(R.string.domain_initial_whitelist)
238                 BlocklistHelper.DOMAIN_FINAL_WHITELIST -> requestSubList.setText(R.string.domain_final_whitelist)
239                 BlocklistHelper.THIRD_PARTY_WHITELIST -> requestSubList.setText(R.string.third_party_whitelist)
240                 BlocklistHelper.THIRD_PARTY_DOMAIN_WHITELIST -> requestSubList.setText(R.string.third_party_domain_whitelist)
241                 BlocklistHelper.THIRD_PARTY_DOMAIN_INITIAL_WHITELIST -> requestSubList.setText(R.string.third_party_domain_initial_whitelist)
242                 BlocklistHelper.MAIN_BLACKLIST -> requestSubList.setText(R.string.main_blacklist)
243                 BlocklistHelper.INITIAL_BLACKLIST -> requestSubList.setText(R.string.initial_blacklist)
244                 BlocklistHelper.FINAL_BLACKLIST -> requestSubList.setText(R.string.final_blacklist)
245                 BlocklistHelper.DOMAIN_BLACKLIST -> requestSubList.setText(R.string.domain_blacklist)
246                 BlocklistHelper.DOMAIN_INITIAL_BLACKLIST -> requestSubList.setText(R.string.domain_initial_blacklist)
247                 BlocklistHelper.DOMAIN_FINAL_BLACKLIST -> requestSubList.setText(R.string.domain_final_blacklist)
248                 BlocklistHelper.DOMAIN_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.domain_regular_expression_blacklist)
249                 BlocklistHelper.THIRD_PARTY_BLACKLIST -> requestSubList.setText(R.string.third_party_blacklist)
250                 BlocklistHelper.THIRD_PARTY_INITIAL_BLACKLIST -> requestSubList.setText(R.string.third_party_initial_blacklist)
251                 BlocklistHelper.THIRD_PARTY_DOMAIN_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_blacklist)
252                 BlocklistHelper.THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_initial_blacklist)
253                 BlocklistHelper.THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.third_party_regular_expression_blacklist)
254                 BlocklistHelper.THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.third_party_domain_regular_expression_blacklist)
255                 BlocklistHelper.REGULAR_EXPRESSION_BLACKLIST -> requestSubList.setText(R.string.regular_expression_blacklist)
256             }
257         }
258
259         // Return the alert dialog.
260         return alertDialog
261     }
262 }