/*
- * Copyright 2017-2023 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2017-2024 Soren Stoutner <soren@stoutner.com>.
*
* This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
*
import android.content.Context
import android.database.Cursor
import android.os.Bundle
-import android.os.Handler
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ScrollView
import android.widget.Spinner
import android.widget.TextView
-import androidx.activity.OnBackPressedCallback
+import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat
import androidx.appcompat.widget.Toolbar
import com.google.android.material.snackbar.Snackbar
import com.stoutner.privacybrowser.R
+import com.stoutner.privacybrowser.dialogs.AddDomainDialog
import com.stoutner.privacybrowser.dialogs.AddDomainDialog.AddDomainListener
-import com.stoutner.privacybrowser.dialogs.AddDomainDialog.Companion.addDomain
import com.stoutner.privacybrowser.fragments.DomainSettingsFragment
import com.stoutner.privacybrowser.fragments.DomainsListFragment
import com.stoutner.privacybrowser.fragments.DomainsListFragment.DismissSnackbarInterface
import com.stoutner.privacybrowser.fragments.DomainsListFragment.SaveDomainSettingsInterface
+import com.stoutner.privacybrowser.helpers.DOMAIN_NAME
+import com.stoutner.privacybrowser.helpers.ID
import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper
// Define the public constants.
// Get the status of close-on-back, which is true when the domains activity is called from the options menu.
closeOnBack = intent.getBooleanExtra(CLOSE_ON_BACK, false)
- // Get the current URL.
- val currentUrl = intent.getStringExtra(CURRENT_URL)
-
// Store the current SSL certificate information in class variables.
sslIssuedToCName = intent.getStringExtra(SSL_ISSUED_TO_CNAME)
sslIssuedToOName = intent.getStringExtra(SSL_ISSUED_TO_ONAME)
// Configure the add domain floating action button.
addDomainFAB.setOnClickListener {
// Create an add domain dialog.
- val addDomainDialog: DialogFragment = addDomain(currentUrl)
+ val addDomainDialog: DialogFragment = AddDomainDialog()
// Show the add domain dialog.
addDomainDialog.show(supportFragmentManager, resources.getString(R.string.add_domain))
override fun bindView(view: View, context: Context, cursor: Cursor) {
// Get the domain name string.
- val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME))
+ val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME))
// Get a handle for the domain name text view.
val domainNameTextView = view.findViewById<TextView>(R.id.domain_name_textview)
override fun bindView(view: View, context: Context, cursor: Cursor) {
/// Get the domain name string.
- val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME))
+ val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME))
// Get a handle for the domain name text view.
val domainNameTextView = view.findViewById<TextView>(R.id.domain_name_textview)
}
} else { // The snackbar was dismissed without the undo button being pushed.
// Delete the selected domain.
- domainsDatabaseHelper.deleteDomain(databaseIdToDelete)
-
- // Enable the delete menu item if the system was waiting for a snackbar to be dismissed.
- if (dismissingSnackbar) {
- // Create a runnable to enable the delete menu item.
- val enableDeleteMenuItemRunnable = Runnable {
- // Enable or show the delete menu item according to the display mode.
- if (twoPanedMode)
- deleteMenuItem.isEnabled = true
- else
- deleteMenuItem.isVisible = true
-
- // Reset the dismissing snackbar tracker.
- dismissingSnackbar = false
- }
-
- // Instantiate a handler running the main looper.
- val handler = Handler(mainLooper)
-
- // Enable or show the delete menu icon after 100 milliseconds to make sure that the previous domain has been deleted from the database.
- handler.postDelayed(enableDeleteMenuItemRunnable, 100)
+ val rowsDeleted = domainsDatabaseHelper.deleteDomain(databaseIdToDelete)
+
+ // Enable the delete menu item.
+ // The rows deleted should always be greater than 0, but in all cases they should be greater than -1.
+ // This has the effect of tricking the compiler into waiting until after the delete finishes to reenable the delete menu item,
+ // because the compiler (probably) can't tell that the response will never be less than -1, so it doesn't compile out the delay.
+ if (rowsDeleted > -1) {
+ // Enable or show the delete menu item according to the display mode.
+ if (twoPanedMode)
+ deleteMenuItem.isEnabled = true
+ else
+ deleteMenuItem.isVisible = true
+
+ // Reset the dismissing snackbar tracker.
+ dismissingSnackbar = false
}
// Close the activity if back was pressed.
}
}
- override fun onAddDomain(dialogFragment: DialogFragment) {
+ override fun addDomain(dialogFragment: DialogFragment) {
// Dismiss the undo delete snackbar if it is currently displayed.
if (undoDeleteSnackbar != null && undoDeleteSnackbar!!.isShown)
undoDeleteSnackbar!!.dismiss()
override fun saveDomainSettings(view: View) {
// Get handles for the domain settings.
val domainNameEditText = view.findViewById<EditText>(R.id.domain_settings_name_edittext)
- val javaScriptSwitch = view.findViewById<SwitchCompat>(R.id.javascript_switch)
- val cookiesSwitch = view.findViewById<SwitchCompat>(R.id.cookies_switch)
- val domStorageSwitch = view.findViewById<SwitchCompat>(R.id.dom_storage_switch)
- val formDataSwitch = view.findViewById<SwitchCompat>(R.id.form_data_switch) // Form data can be removed once the minimum API >= 26.
- val easyListSwitch = view.findViewById<SwitchCompat>(R.id.easylist_switch)
- val easyPrivacySwitch = view.findViewById<SwitchCompat>(R.id.easyprivacy_switch)
- val fanboysAnnoyanceSwitch = view.findViewById<SwitchCompat>(R.id.fanboys_annoyance_list_switch)
- val fanboysSocialBlockingSwitch = view.findViewById<SwitchCompat>(R.id.fanboys_social_blocking_list_switch)
- val ultraListSwitch = view.findViewById<SwitchCompat>(R.id.ultralist_switch)
- val ultraPrivacySwitch = view.findViewById<SwitchCompat>(R.id.ultraprivacy_switch)
- val blockAllThirdPartyRequestsSwitch = view.findViewById<SwitchCompat>(R.id.block_all_third_party_requests_switch)
+ val javaScriptSpinner = view.findViewById<Spinner>(R.id.javascript_spinner)
+ val cookiesSpinner = view.findViewById<Spinner>(R.id.cookies_spinner)
+ val domStorageSpinner = view.findViewById<Spinner>(R.id.dom_storage_spinner)
val userAgentSpinner = view.findViewById<Spinner>(R.id.user_agent_spinner)
val customUserAgentEditText = view.findViewById<EditText>(R.id.custom_user_agent_edittext)
+ val easyListSpinner = view.findViewById<Spinner>(R.id.easylist_spinner)
+ val easyPrivacySpinner = view.findViewById<Spinner>(R.id.easyprivacy_spinner)
+ val fanboysAnnoyanceSpinner = view.findViewById<Spinner>(R.id.fanboys_annoyance_list_spinner)
+ val fanboysSocialBlockingSpinner = view.findViewById<Spinner>(R.id.fanboys_social_blocking_list_spinner)
+ val ultraListSpinner = view.findViewById<Spinner>(R.id.ultralist_spinner)
+ val ultraPrivacySpinner = view.findViewById<Spinner>(R.id.ultraprivacy_spinner)
+ val blockAllThirdPartyRequestsSpinner = view.findViewById<Spinner>(R.id.block_all_third_party_requests_spinner)
val fontSizeSpinner = view.findViewById<Spinner>(R.id.font_size_spinner)
val customFontSizeEditText = view.findViewById<EditText>(R.id.custom_font_size_edittext)
val swipeToRefreshSpinner = view.findViewById<Spinner>(R.id.swipe_to_refresh_spinner)
val webViewThemeSpinner = view.findViewById<Spinner>(R.id.webview_theme_spinner)
val wideViewportSpinner = view.findViewById<Spinner>(R.id.wide_viewport_spinner)
- val displayWebpageImagesSpinner = view.findViewById<Spinner>(R.id.display_webpage_images_spinner)
+ val displayWebpageImagesSpinner = view.findViewById<Spinner>(R.id.display_images_spinner)
val pinnedSslCertificateSwitch = view.findViewById<SwitchCompat>(R.id.pinned_ssl_certificate_switch)
val currentWebsiteCertificateRadioButton = view.findViewById<RadioButton>(R.id.current_website_certificate_radiobutton)
val pinnedIpAddressesSwitch = view.findViewById<SwitchCompat>(R.id.pinned_ip_addresses_switch)
// Extract the data for the domain settings.
val domainNameString = domainNameEditText.text.toString()
- val javaScript = javaScriptSwitch.isChecked
- val cookies = cookiesSwitch.isChecked
- val domStorage = domStorageSwitch.isChecked
- val formData = formDataSwitch.isChecked // Form data can be removed once the minimum API >= 26.
- val easyList = easyListSwitch.isChecked
- val easyPrivacy = easyPrivacySwitch.isChecked
- val fanboysAnnoyance = fanboysAnnoyanceSwitch.isChecked
- val fanboysSocialBlocking = fanboysSocialBlockingSwitch.isChecked
- val ultraList = ultraListSwitch.isChecked
- val ultraPrivacy = ultraPrivacySwitch.isChecked
- val blockAllThirdPartyRequests = blockAllThirdPartyRequestsSwitch.isChecked
+ val javaScriptInt = javaScriptSpinner.selectedItemPosition
+ val cookiesInt = cookiesSpinner.selectedItemPosition
+ val domStorageInt = domStorageSpinner.selectedItemPosition
val userAgentSwitchPosition = userAgentSpinner.selectedItemPosition
+ val easyListInt = easyListSpinner.selectedItemPosition
+ val easyPrivacyInt = easyPrivacySpinner.selectedItemPosition
+ val fanboysAnnoyanceInt = fanboysAnnoyanceSpinner.selectedItemPosition
+ val fanboysSocialBlockingInt = fanboysSocialBlockingSpinner.selectedItemPosition
+ val ultraListInt = ultraListSpinner.selectedItemPosition
+ val ultraPrivacyInt = ultraPrivacySpinner.selectedItemPosition
+ val blockAllThirdPartyRequestsInt = blockAllThirdPartyRequestsSpinner.selectedItemPosition
val fontSizeSwitchPosition = fontSizeSpinner.selectedItemPosition
val swipeToRefreshInt = swipeToRefreshSpinner.selectedItemPosition
val webViewThemeInt = webViewThemeSpinner.selectedItemPosition
fontSizeInt = customFontSizeEditText.text.toString().toInt()
// Save the domain settings.
- domainsDatabaseHelper.updateDomain(currentDomainDatabaseId, domainNameString, javaScript, cookies, domStorage, formData, easyList, easyPrivacy, fanboysAnnoyance, fanboysSocialBlocking, ultraList,
- ultraPrivacy, blockAllThirdPartyRequests, userAgentName, fontSizeInt, swipeToRefreshInt, webViewThemeInt, wideViewportInt, displayWebpageImagesInt,
+ domainsDatabaseHelper.updateDomain(currentDomainDatabaseId, domainNameString, javaScriptInt, cookiesInt, domStorageInt, userAgentName, easyListInt, easyPrivacyInt, fanboysAnnoyanceInt,
+ fanboysSocialBlockingInt, ultraListInt, ultraPrivacyInt, blockAllThirdPartyRequestsInt, fontSizeInt, swipeToRefreshInt, webViewThemeInt, wideViewportInt, displayWebpageImagesInt,
pinnedSslCertificate, pinnedIpAddress)
// Update the pinned SSL certificate if a new one is checked.
val domainNameTextView = view.findViewById<TextView>(R.id.domain_name_textview)
// Get the domain name string.
- val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME))
+ val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME))
// Set the domain name.
domainNameTextView.text = domainNameString
domainsCursor.moveToPosition(i)
// Get the database ID for this position.
- val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID))
+ val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID))
// Set the highlighted domain position if the database ID for this matches the highlighted domain database ID.
if (highlightedDomainDatabaseId == currentDatabaseId)
domainsCursor.moveToPosition(highlightedDomainPosition)
// Get the database ID for the highlighted domain.
- currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID))
+ currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID))
// Create an arguments bundle.
val argumentsBundle = Bundle()