package com.stoutner.privacybrowser.dialogs
import android.app.Dialog
-import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.view.WindowManager
+import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
// Define the class constants.
private const val ID = "id"
-private const val IS_LAST_REQUEST = "is_last_request"
-private const val REQUEST_DATA_CLASS = "request_data_class"
-
-// Define the private variables.
-private var blueColor = 0
-private var redColor = 0
+private const val REQUEST_DATA_CLASS_ARRAY_LIST = "request_data_class_array_list"
class ViewRequestDialog : DialogFragment() {
companion object {
- fun request(id: Int, isLastRequest: Boolean, requestDataClass: RequestDataClass): ViewRequestDialog {
+ fun request(id: Int, requestDataClassArrayList: ArrayList<RequestDataClass>): ViewRequestDialog {
// Create a bundle.
val bundle = Bundle()
// Store the request details.
bundle.putInt(ID, id)
- bundle.putBoolean(IS_LAST_REQUEST, isLastRequest)
- bundle.putParcelable(REQUEST_DATA_CLASS, requestDataClass)
+ bundle.putParcelableArrayList(REQUEST_DATA_CLASS_ARRAY_LIST, requestDataClassArrayList)
// Create a new instance of the view request dialog.
val viewRequestDialog = ViewRequestDialog()
}
}
- // Define the class variables.
- private lateinit var viewRequestListener: ViewRequestListener
-
- // The public interface is used to send information back to the parent activity.
- interface ViewRequestListener {
- // Show the previous request.
- fun onPrevious(currentId: Int)
-
- // Show the next request.
- fun onNext(currentId: Int)
- }
-
- override fun onAttach(context: Context) {
- // Run the default commands.
- super.onAttach(context)
-
- // Get a handle for the listener from the launching context.
- viewRequestListener = context as ViewRequestListener
- }
+ // Define the private variables.
+ private var blueColor = 0
+ private var currentId = 0
+ private var redColor = 0
+ private var transparentColor = 0
+ private var yellowColor = 0
+
+ // Declare the class variables.
+ private lateinit var requestDataClassArrayList: ArrayList<RequestDataClass>
+
+ // Declare the class views.
+ private lateinit var alertDialog: AlertDialog
+ private lateinit var requestDispositionTextView: TextView
+ private lateinit var webpageUrlTextView: TextView
+ private lateinit var requestUrlTextView: TextView
+ private lateinit var requestUrlWithSeparatorsTextView: TextView
+ private lateinit var truncatedRequestUrlTextView: TextView
+ private lateinit var truncatedRequestUrlWithSeparatorsTextView: TextView
+ private lateinit var thirdPartyRequestTextView: TextView
+ private lateinit var filterListEntryTextView: TextView
+ private lateinit var filterListLabelTextView: TextView
+ private lateinit var filterListTextView: TextView
+ private lateinit var sublistLabelTextView: TextView
+ private lateinit var sublistTextView: TextView
+ private lateinit var appliedEntryListLabelTextView: TextView
+ private lateinit var appliedEntryListTextView: TextView
+ private lateinit var domainLabelTextView: TextView
+ private lateinit var domainTextView: TextView
+ private lateinit var domainListLabelTextView: TextView
+ private lateinit var domainListTextView: TextView
+ private lateinit var thirdPartyFilterListEntryLabelTextView: TextView
+ private lateinit var thirdPartyFilterListEntryTextView: TextView
+ private lateinit var initialMatchLabelTextView: TextView
+ private lateinit var initialMatchTextView: TextView
+ private lateinit var finalMatchLabelTextView: TextView
+ private lateinit var finalMatchTextView: TextView
+ private lateinit var appliedFilterOptionsLabelTextView: TextView
+ private lateinit var appliedFilterOptionsTextView: TextView
+ private lateinit var originalFilterOptionsLabelTextView: TextView
+ private lateinit var originalFilterOptionsTextView: TextView
+ private lateinit var originalEntryLabelTextView: TextView
+ private lateinit var originalEntryTextView: TextView
+ private lateinit var previousButton: Button
+ private lateinit var nextButton: Button
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// Get the arguments from the bundle.
- // The deprecated `getParcelable()` method can be updated once the minimum API >= 33.
- val id = requireArguments().getInt(ID)
- val isLastRequest = requireArguments().getBoolean(IS_LAST_REQUEST)
- @Suppress("DEPRECATION") val requestDataClass = requireArguments().getParcelable<RequestDataClass>(REQUEST_DATA_CLASS)!!
+ currentId = requireArguments().getInt(ID)
+ @Suppress("DEPRECATION") // The deprecated `getParcelable()` method can be updated once the minimum API >= 33.
+ requestDataClassArrayList = requireArguments().getParcelableArrayList(REQUEST_DATA_CLASS_ARRAY_LIST)!!
// Use an alert dialog builder to create the alert dialog.
val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
// Set the icon.
dialogBuilder.setIcon(R.drawable.block_ads_enabled)
- // Set the title.
+ // Set the title. This must be set here or it can't be updated later.
dialogBuilder.setTitle(resources.getString(R.string.request_details) + " - " + id)
// Set the view.
// Set the close button. Using `null` as the listener closes the dialog without doing anything else.
dialogBuilder.setNeutralButton(R.string.close, null)
- // Set the previous button.
- dialogBuilder.setNegativeButton(R.string.previous) { _: DialogInterface?, _: Int ->
- // Load the previous request.
- viewRequestListener.onPrevious(id)
- }
+ // Set the previous button. The button actions are set later so they can run without closing the dialog.
+ dialogBuilder.setNegativeButton(R.string.previous, null)
- // Set the next button.
- dialogBuilder.setPositiveButton(R.string.next) { _: DialogInterface?, _: Int ->
- // Load the next request.
- viewRequestListener.onNext(id)
- }
+ // Set the next button. The button actions are set later so they can run without closing the dialog.
+ dialogBuilder.setPositiveButton(R.string.next, null)
// Create an alert dialog from the alert dialog builder.
- val alertDialog = dialogBuilder.create()
+ alertDialog = dialogBuilder.create()
// Get a handle for the shared preferences.
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
alertDialog.show()
// Get handles for the dialog views.
- val requestDispositionTextView = alertDialog.findViewById<TextView>(R.id.request_disposition_textview)!!
- val webpageUrlTextView = alertDialog.findViewById<TextView>(R.id.webpage_url_textview)!!
- val requestUrlTextView = alertDialog.findViewById<TextView>(R.id.request_url_textview)!!
- val requestUrlWithSeparatorsTextView = alertDialog.findViewById<TextView>(R.id.request_url_with_separators_textview)!!
- val truncatedRequestUrlTextView = alertDialog.findViewById<TextView>(R.id.truncated_request_url_textview)!!
- val truncatedRequestUrlWithSeparatorsTextView = alertDialog.findViewById<TextView>(R.id.truncated_request_url_with_separators_textview)!!
- val thirdPartyRequestTextView = alertDialog.findViewById<TextView>(R.id.third_party_request_textview)!!
- val filterListEntryTextView = alertDialog.findViewById<TextView>(R.id.filterlist_entry_textview)!!
- val filterListLabelTextView = alertDialog.findViewById<TextView>(R.id.filterlist_label_textview)!!
- val filterListTextView = alertDialog.findViewById<TextView>(R.id.filterlist_textview)!!
- val sublistLabelTextView = alertDialog.findViewById<TextView>(R.id.sublist_label_textview)!!
- val sublistTextView = alertDialog.findViewById<TextView>(R.id.sublist_textview)!!
- val appliedEntryListLabelTextView = alertDialog.findViewById<TextView>(R.id.applied_entry_list_label_textview)!!
- val appliedEntryListTextView = alertDialog.findViewById<TextView>(R.id.applied_entry_list_textview)!!
- val domainLabelTextView = alertDialog.findViewById<TextView>(R.id.domain_label_textview)!!
- val domainTextView = alertDialog.findViewById<TextView>(R.id.domain_textview)!!
- val domainListLabelTextView = alertDialog.findViewById<TextView>(R.id.domain_list_label_textview)!!
- val domainListTextView = alertDialog.findViewById<TextView>(R.id.domain_list_textview)!!
- val thirdPartyFilterListEntryLabelTextView = alertDialog.findViewById<TextView>(R.id.third_party_filter_list_entry_label_textview)!!
- val thirdPartyFilterListEntryTextView = alertDialog.findViewById<TextView>(R.id.third_party_filter_list_entry_textview)!!
- val initialMatchLabelTextView = alertDialog.findViewById<TextView>(R.id.initial_match_label_textview)!!
- val initialMatchTextView = alertDialog.findViewById<TextView>(R.id.initial_match_textview)!!
- val finalMatchLabelTextView = alertDialog.findViewById<TextView>(R.id.final_match_label_textview)!!
- val finalMatchTextView = alertDialog.findViewById<TextView>(R.id.final_match_textview)!!
- val appliedFilterOptionsLabelTextView = alertDialog.findViewById<TextView>(R.id.applied_filter_options_label_textview)!!
- val appliedFilterOptionsTextView = alertDialog.findViewById<TextView>(R.id.applied_filter_options_textview)!!
- val originalFilterOptionsLabelTextView = alertDialog.findViewById<TextView>(R.id.original_filter_options_label_textview)!!
- val originalFilterOptionsTextView = alertDialog.findViewById<TextView>(R.id.original_filter_options_textview)!!
- val originalEntryLabelTextView = alertDialog.findViewById<TextView>(R.id.original_entry_label_textview)!!
- val originalEntryTextView = alertDialog.findViewById<TextView>(R.id.original_entry_textview)!!
- val previousButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
- val nextButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
+ requestDispositionTextView = alertDialog.findViewById(R.id.request_disposition_textview)!!
+ webpageUrlTextView = alertDialog.findViewById(R.id.webpage_url_textview)!!
+ requestUrlTextView = alertDialog.findViewById(R.id.request_url_textview)!!
+ requestUrlWithSeparatorsTextView = alertDialog.findViewById(R.id.request_url_with_separators_textview)!!
+ truncatedRequestUrlTextView = alertDialog.findViewById(R.id.truncated_request_url_textview)!!
+ truncatedRequestUrlWithSeparatorsTextView = alertDialog.findViewById(R.id.truncated_request_url_with_separators_textview)!!
+ thirdPartyRequestTextView = alertDialog.findViewById(R.id.third_party_request_textview)!!
+ filterListEntryTextView = alertDialog.findViewById(R.id.filterlist_entry_textview)!!
+ filterListLabelTextView = alertDialog.findViewById(R.id.filterlist_label_textview)!!
+ filterListTextView = alertDialog.findViewById(R.id.filterlist_textview)!!
+ sublistLabelTextView = alertDialog.findViewById(R.id.sublist_label_textview)!!
+ sublistTextView = alertDialog.findViewById(R.id.sublist_textview)!!
+ appliedEntryListLabelTextView = alertDialog.findViewById(R.id.applied_entry_list_label_textview)!!
+ appliedEntryListTextView = alertDialog.findViewById(R.id.applied_entry_list_textview)!!
+ domainLabelTextView = alertDialog.findViewById(R.id.domain_label_textview)!!
+ domainTextView = alertDialog.findViewById(R.id.domain_textview)!!
+ domainListLabelTextView = alertDialog.findViewById(R.id.domain_list_label_textview)!!
+ domainListTextView = alertDialog.findViewById(R.id.domain_list_textview)!!
+ thirdPartyFilterListEntryLabelTextView = alertDialog.findViewById(R.id.third_party_filter_list_entry_label_textview)!!
+ thirdPartyFilterListEntryTextView = alertDialog.findViewById(R.id.third_party_filter_list_entry_textview)!!
+ initialMatchLabelTextView = alertDialog.findViewById(R.id.initial_match_label_textview)!!
+ initialMatchTextView = alertDialog.findViewById(R.id.initial_match_textview)!!
+ finalMatchLabelTextView = alertDialog.findViewById(R.id.final_match_label_textview)!!
+ finalMatchTextView = alertDialog.findViewById(R.id.final_match_textview)!!
+ appliedFilterOptionsLabelTextView = alertDialog.findViewById(R.id.applied_filter_options_label_textview)!!
+ appliedFilterOptionsTextView = alertDialog.findViewById(R.id.applied_filter_options_textview)!!
+ originalFilterOptionsLabelTextView = alertDialog.findViewById(R.id.original_filter_options_label_textview)!!
+ originalFilterOptionsTextView = alertDialog.findViewById(R.id.original_filter_options_textview)!!
+ originalEntryLabelTextView = alertDialog.findViewById(R.id.original_entry_label_textview)!!
+ originalEntryTextView = alertDialog.findViewById(R.id.original_entry_textview)!!
+ previousButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
+ nextButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
+
+ // Set the previous button on click listener. This must be done here instead of in the builder to prevent the dialog from closing when the button is pressed.
+ previousButton.setOnClickListener {
+ // Decrement the current ID.
+ --currentId
+
+ // Repopulate the dialog.
+ populateDialog()
+ }
+
+ // Set the next button on click listener. This must be done here instead of in the builder to prevent the dialog from closing when the button is pressed.
+ nextButton.setOnClickListener {
+ // Increment the current ID.
+ ++currentId
+
+ // Repopulate the dialog.
+ populateDialog()
+ }
+
+ // Get a handle for the context.
+ val context = requireContext()
+
+ // Get handles for the colors.
+ blueColor = getColor(context, R.color.requests_blue_background)
+ redColor = getColor(context, R.color.red_background)
+ transparentColor = getColor(context, R.color.transparent)
+ yellowColor = getColor(context, R.color.yellow_background)
+
+ // Populate the dialog.
+ populateDialog()
+
+ // Return the alert dialog.
+ return alertDialog
+ }
+
+ private fun convertListToString(stringList: List<String>, separatorString: String): String {
+ // Create a string builder.
+ val stringBuilder = StringBuilder()
+
+ // Add each of the strings from the list.
+ for (string in stringList) {
+ // Append four space if the string builder is already populated.
+ if (stringBuilder.isNotEmpty())
+ stringBuilder.append(separatorString)
+
+ // Append the string.
+ stringBuilder.append(string)
+ }
+
+ // Return the string.
+ return stringBuilder.toString()
+ }
+
+ private fun populateDialog() {
+ // Get the request data class. The array list is 0 based.
+ val requestDataClass = requestDataClassArrayList[currentId - 1]
+
+ // Update the dialog title.
+ alertDialog.setTitle(resources.getString(R.string.request_details) + " - " + currentId)
// Disable the previous button if the first resource request is displayed.
- previousButton.isEnabled = (id != 1)
+ previousButton.isEnabled = (currentId != 1)
// Disable the next button if the last resource request is displayed.
- nextButton.isEnabled = !isLastRequest
+ nextButton.isEnabled = (currentId != requestDataClassArrayList.size)
- // Get handles for the colors.
- blueColor = getColor(requireContext(), R.color.requests_blue_background)
- redColor = getColor(requireContext(), R.color.red_background)
- val yellowColor = getColor(requireContext(), R.color.yellow_background)
+ // Reset the matched URL background colors.
+ requestUrlTextView.setBackgroundColor(transparentColor)
+ truncatedRequestUrlTextView.setBackgroundColor(transparentColor)
+ requestUrlWithSeparatorsTextView.setBackgroundColor(transparentColor)
+ truncatedRequestUrlWithSeparatorsTextView.setBackgroundColor(transparentColor)
// Set the request disposition text and associated backgrounds.
when (requestDataClass.disposition) {
// Set the request disposition background color to be transparent.
requestDispositionTextView.setBackgroundColor(getColor(requireContext(), R.color.transparent))
+
+ // Reset the third-party request background color.
+ thirdPartyRequestTextView.setBackgroundColor(transparentColor)
}
RequestDisposition.Allowed -> {
// Set the domain list text view background color to be the same as the domain text view background color.
setFilterListBackgroundColor(requestDataClass.filterListDomain, domainListTextView, true)
- // Set the matching text view background color to blue if they are populated.
+ // Set the initial match text view background color to blue if it is populated.
if (requestDataClass.filterListInitialMatch)
initialMatchTextView.setBackgroundColor(blueColor)
+ else
+ initialMatchTextView.setBackgroundColor(transparentColor)
+
+ // Set the final match text view background color to blue if it is populated.
if (requestDataClass.filterListFinalMatch)
finalMatchTextView.setBackgroundColor(blueColor)
+ else
+ finalMatchTextView.setBackgroundColor(transparentColor)
}
RequestDisposition.Blocked -> {
// Set the domain list text view background color to be the same as the domain text view background color.
setFilterListBackgroundColor(requestDataClass.filterListDomain, domainListTextView, false)
- // Set the matching text view background color to red if they are populated.
+ // Set the initial match text view background color to red if it is populated.
if (requestDataClass.filterListInitialMatch)
initialMatchTextView.setBackgroundColor(redColor)
+ else
+ initialMatchTextView.setBackgroundColor(transparentColor)
+
+ // Set the final match text view background color to red if it is populated.
if (requestDataClass.filterListFinalMatch)
finalMatchTextView.setBackgroundColor(redColor)
+ else
+ finalMatchTextView.setBackgroundColor(transparentColor)
}
RequestDisposition.ThirdParty -> {
originalEntryLabelTextView.visibility = View.GONE
originalEntryTextView.visibility = View.GONE
} else { // A blocked or allowed request.
+ // Show the extra views.
+ filterListEntryTextView.visibility = View.VISIBLE
+ filterListLabelTextView.visibility = View.VISIBLE
+ filterListTextView.visibility = View.VISIBLE
+ sublistLabelTextView.visibility = View.VISIBLE
+ sublistTextView.visibility = View.VISIBLE
+ appliedEntryListLabelTextView.visibility = View.VISIBLE
+ appliedEntryListTextView.visibility = View.VISIBLE
+ domainLabelTextView.visibility = View.VISIBLE
+ domainTextView.visibility = View.VISIBLE
+ domainListLabelTextView.visibility = View.VISIBLE
+ domainListTextView.visibility = View.VISIBLE
+ thirdPartyFilterListEntryLabelTextView.visibility = View.VISIBLE
+ thirdPartyFilterListEntryTextView.visibility = View.VISIBLE
+ initialMatchLabelTextView.visibility = View.VISIBLE
+ initialMatchTextView.visibility = View.VISIBLE
+ finalMatchLabelTextView.visibility = View.VISIBLE
+ finalMatchTextView.visibility = View.VISIBLE
+ appliedFilterOptionsLabelTextView.visibility = View.VISIBLE
+ appliedFilterOptionsTextView.visibility = View.VISIBLE
+ originalFilterOptionsLabelTextView.visibility = View.VISIBLE
+ originalFilterOptionsTextView.visibility = View.VISIBLE
+ originalEntryLabelTextView.visibility = View.VISIBLE
+ originalEntryTextView.visibility = View.VISIBLE
+
// Populate the filter list.
when (requestDataClass.filterList) {
FilterList.UltraPrivacy -> filterListTextView.text = getString(R.string.ultraprivacy)
originalFilterOptionsTextView.text = requestDataClass.filterListOriginalFilterOptionsString
originalEntryTextView.text = requestDataClass.filterListOriginalEntryString
}
-
- // Return the alert dialog.
- return alertDialog
- }
-
- private fun convertListToString(stringList: List<String>, separatorString: String): String {
- // Create a string builder.
- val stringBuilder = StringBuilder()
-
- // Add each of the strings from the list.
- for (string in stringList) {
- // Append four space if the string builder is already populated.
- if (stringBuilder.isNotEmpty())
- stringBuilder.append(separatorString)
-
- // Append the string.
- stringBuilder.append(string)
- }
-
- // Return the string.
- return stringBuilder.toString()
}
private fun populateFilterOption(filterOptionDisposition: FilterOptionDisposition) : String {
private fun setFilterListBackgroundColor(filterOptionDisposition: FilterOptionDisposition, textView: TextView, isAllowList: Boolean) {
// Set the text view background.
if (isAllowList) { // This is an allow list.
- if (filterOptionDisposition == FilterOptionDisposition.Apply) // The filter option is applied on an allow list, set the background to blue.
- textView.setBackgroundColor(blueColor)
- else if (filterOptionDisposition == FilterOptionDisposition.Override) // The filter option is overridden on an allow list, set the background to red.
- textView.setBackgroundColor(redColor)
+ when (filterOptionDisposition) { // For allow lists, set applied entries to blue and overridden entries to red.
+ FilterOptionDisposition.Null -> textView.setBackgroundColor(transparentColor)
+ FilterOptionDisposition.Apply -> textView.setBackgroundColor(blueColor)
+ FilterOptionDisposition.Override -> textView.setBackgroundColor(redColor)
+ }
} else { // This is a block list.
- if (filterOptionDisposition == FilterOptionDisposition.Apply) // The filter option is applied on a block list, set the background to be red.
- textView.setBackgroundColor(redColor)
- else if (filterOptionDisposition == FilterOptionDisposition.Override) // The filter option is overridden on a block list, set the background to be blue.
- textView.setBackgroundColor(blueColor)
+ when (filterOptionDisposition) { // For block lists, set applied entries to red and overridden entries to blue.
+ FilterOptionDisposition.Null -> textView.setBackgroundColor(transparentColor)
+ FilterOptionDisposition.Apply -> textView.setBackgroundColor(redColor)
+ FilterOptionDisposition.Override -> textView.setBackgroundColor(blueColor)
+ }
}
}
}