2 * Copyright © 2018-2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
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.
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.
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/>.
20 package com.stoutner.privacybrowser.dialogs
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
31 import androidx.appcompat.app.AlertDialog
32 import androidx.fragment.app.DialogFragment
33 import androidx.preference.PreferenceManager
35 import com.stoutner.privacybrowser.R
36 import com.stoutner.privacybrowser.helpers.BlocklistHelper
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"
43 class ViewRequestDialog : DialogFragment() {
44 // Define the class variables.
45 private lateinit var viewRequestListener: ViewRequestListener
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)
52 // Show the next request.
53 fun onNext(currentId: Int)
56 override fun onAttach(context: Context) {
57 // Run the default commands.
58 super.onAttach(context)
60 // Get a handle for the listener from the launching context.
61 viewRequestListener = context as ViewRequestListener
65 // `@JvmStatic` will no longer be required once all the code has transitioned to Kotlin.
67 fun request(id: Int, isLastRequest: Boolean, requestDetails: Array<String>): ViewRequestDialog {
71 // Store the request details.
73 bundle.putBoolean(IS_LAST_REQUEST, isLastRequest)
74 bundle.putStringArray(REQUEST_DETAILS, requestDetails)
76 // Create a new instance of the view request dialog.
77 val viewRequestDialog = ViewRequestDialog()
79 // Add the arguments to the new dialog.
80 viewRequestDialog.arguments = bundle
82 // Return the new dialog.
83 return viewRequestDialog
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)!!
93 // Use an alert dialog builder to create the alert dialog.
94 val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
96 // Get the current theme status.
97 val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
99 // Set the icon according to the theme.
100 dialogBuilder.setIconAttribute(R.attr.blockAdsBlueIcon)
103 dialogBuilder.setTitle(resources.getString(R.string.request_details) + " - " + id)
106 dialogBuilder.setView(R.layout.view_request_dialog)
108 // Set the close button. Using `null` as the listener closes the dialog without doing anything else.
109 dialogBuilder.setNeutralButton(R.string.close, null)
111 // Set the previous button.
112 dialogBuilder.setNegativeButton(R.string.previous) { _: DialogInterface?, _: Int ->
113 // Load the previous request.
114 viewRequestListener.onPrevious(id)
117 // Set the next button.
118 dialogBuilder.setPositiveButton(R.string.next) { _: DialogInterface?, _: Int ->
119 // Load the next request.
120 viewRequestListener.onNext(id)
123 // Create an alert dialog from the alert dialog builder.
124 val alertDialog = dialogBuilder.create()
126 // Get a handle for the shared preferences.
127 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
129 // Get the screenshot preference.
130 val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
132 // Disable screenshots if not allowed.
133 if (!allowScreenshots) {
134 // Disable screenshots.
135 alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
138 //The alert dialog must be shown before the contents can be modified.
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)
155 // Disable the previous button if the first resource request is displayed.
156 previousButton.isEnabled = (id != 1)
158 // Disable the next button if the last resource request is displayed.
159 nextButton.isEnabled = !isLastRequest
161 // Set the request action text.
162 when (requestDetails[BlocklistHelper.REQUEST_DISPOSITION]) {
163 BlocklistHelper.REQUEST_DEFAULT -> {
165 requestDisposition.setText(R.string.default_allowed)
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))
172 BlocklistHelper.REQUEST_ALLOWED -> {
174 requestDisposition.setText(R.string.allowed)
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))
181 @Suppress("DEPRECATION")
182 requestDisposition.setBackgroundColor(resources.getColor(R.color.blue_700_50))
186 BlocklistHelper.REQUEST_THIRD_PARTY -> {
188 requestDisposition.setText(R.string.third_party_blocked)
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))
195 @Suppress("DEPRECATION")
196 requestDisposition.setBackgroundColor(resources.getColor(R.color.yellow_700_50))
199 BlocklistHelper.REQUEST_BLOCKED -> {
201 requestDisposition.setText(R.string.blocked)
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))
208 @Suppress("DEPRECATION")
209 requestDisposition.setBackgroundColor(resources.getColor(R.color.red_700_40))
214 // Display the request URL.
215 requestUrl.text = requestDetails[BlocklistHelper.REQUEST_URL]
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)
259 // Return the alert dialog.