From 0bf651c14efcc5cd97b717af683d282755c833fc Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Thu, 20 Aug 2026 17:05:05 -0700 Subject: [PATCH] Create search functionality for resource requests. https://redmine.stoutner.com/issues/532 --- .../BookmarksDatabaseViewActivity.kt | 9 +- .../activities/FilterListsActivity.kt | 4 +- .../activities/MainWebViewActivity.kt | 16 +- .../activities/RequestsActivity.kt | 151 +++++++++--------- .../adapters/FilterListArrayAdapter.kt | 3 +- .../adapters/RequestsArrayAdapter.kt | 62 ++++++- .../views/NestedScrollWebView.kt | 11 +- .../bookmarks_databaseview_top_appbar.xml | 29 ++-- .../res/layout/filter_lists_bottom_appbar.xml | 15 +- .../res/layout/filter_lists_top_appbar.xml | 15 +- .../res/layout/requests_bottom_appbar.xml | 15 +- .../main/res/layout/requests_top_appbar.xml | 15 +- app/src/main/res/layout/spinner.xml | 25 --- app/src/main/res/layout/spinner_app_bar.xml | 31 ++++ gradle/wrapper/gradle-wrapper.properties | 2 +- 15 files changed, 251 insertions(+), 152 deletions(-) delete mode 100644 app/src/main/res/layout/spinner.xml create mode 100644 app/src/main/res/layout/spinner_app_bar.xml diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.kt index 5d7ca2d7..58304b65 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 Soren Stoutner . + * Copyright 2016-2024, 2026 Soren Stoutner . * * This file is part of Privacy Browser Android . * @@ -49,6 +49,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.Toolbar import androidx.core.graphics.drawable.toBitmap +import androidx.core.util.size import androidx.cursoradapter.widget.CursorAdapter import androidx.cursoradapter.widget.ResourceCursorAdapter import androidx.fragment.app.DialogFragment @@ -139,7 +140,7 @@ class BookmarksDatabaseViewActivity : AppCompatActivity(), EditBookmarkDatabaseV val appBar = supportActionBar!! // Set the app bar custom view. - appBar.setCustomView(R.layout.spinner) + appBar.setCustomView(R.layout.spinner_app_bar) // Display the back arrow in the app bar. appBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM or ActionBar.DISPLAY_HOME_AS_UP @@ -528,7 +529,7 @@ class BookmarksDatabaseViewActivity : AppCompatActivity(), EditBookmarkDatabaseV updateBookmarksListView() // Re-select the previously selected bookmarks. - for (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size()) + for (i in 0 until selectedBookmarksPositionsSparseBooleanArray.size) bookmarksListView.setItemChecked(selectedBookmarksPositionsSparseBooleanArray.keyAt(i), true) } else { // The snackbar was dismissed without the undo button being pushed. // Delete each selected bookmark. @@ -802,7 +803,7 @@ class BookmarksDatabaseViewActivity : AppCompatActivity(), EditBookmarkDatabaseV bookmarksDeletedSnackbar!!.dismiss() } else { // Go home immediately. // Update the current folder in the bookmarks activity. - if ((currentFolderDatabaseId == ALL_FOLDERS_DATABASE_ID) || (currentFolderDatabaseId == HOME_FOLDER_DATABASE_ID)) { // All folders or the the home folder are currently displayed. + if ((currentFolderDatabaseId == ALL_FOLDERS_DATABASE_ID) || (currentFolderDatabaseId == HOME_FOLDER_DATABASE_ID)) { // All folders or the home folder are currently displayed. // Load the home folder. BookmarksActivity.currentFolderId = HOME_FOLDER_ID } else { // A subfolder is currently displayed. diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/FilterListsActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/FilterListsActivity.kt index 92ef6591..13f6a970 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/FilterListsActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/FilterListsActivity.kt @@ -115,7 +115,7 @@ class FilterListsActivity : AppCompatActivity(), ViewFilterListEntryDialog.ViewF val appBar = supportActionBar!! // Set the app bar custom view. - appBar.setCustomView(R.layout.spinner) + appBar.setCustomView(R.layout.spinner_app_bar) // Display the back arrow in the app bar. appBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM or ActionBar.DISPLAY_HOME_AS_UP @@ -195,7 +195,7 @@ class FilterListsActivity : AppCompatActivity(), ViewFilterListEntryDialog.ViewF // Populate the list view with the current filter list data class adapter. filterListListView.adapter = currentFilterListDataClassArrayAdapter - // Reapply the search if the search edit is not empty. + // Reapply the search if the search edit text is not empty. if (searchEditText.text.isNotEmpty()) currentFilterListDataClassArrayAdapter.filter.filter(searchEditText.text) } diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt index 749946b8..f37a48d2 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt @@ -67,6 +67,7 @@ import android.view.WindowManager import android.view.inputmethod.InputMethodManager import android.webkit.CookieManager import android.webkit.HttpAuthHandler +import android.webkit.RenderProcessGoneDetail import android.webkit.SslErrorHandler import android.webkit.ValueCallback import android.webkit.WebChromeClient @@ -2261,12 +2262,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } R.id.requests -> { // Requests. - // Populate the resource requests. - RequestsActivity.resourceRequestsDataClassList = currentWebView!!.getResourceRequestsDataClassList() - // Create an intent to launch the Requests activity. val requestsIntent = Intent(this, RequestsActivity::class.java) + // Add the resource requests to the intent. + requestsIntent.putExtra(REQUEST_DATA_CLASS_ARRAY_LIST, currentWebView!!.getResourceRequestsDataClassList()) + // Add the block third-party requests status to the intent. requestsIntent.putExtra(BLOCK_ALL_THIRD_PARTY_REQUESTS, currentWebView!!.blockAllThirdPartyRequests) @@ -5156,6 +5157,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook return true } } + nestedScrollWebView.webViewClient = object : WebViewClient() { // `shouldOverrideUrlLoading` makes this WebView the default handler for URLs inside the app, so that links are not kicked out to other apps. override fun shouldOverrideUrlLoading(view: WebView, webResourceRequest: WebResourceRequest): Boolean { @@ -5668,6 +5670,14 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } } + + // Handle crashes of the rendering process. + override fun onRenderProcessGone(view: WebView?, detail: RenderProcessGoneDetail?): Boolean { + // Do nothing. + + // Return true. + return true + } } // Check to see if the state is being restored. diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.kt index 9ad0d84b..8ce18d2f 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/RequestsActivity.kt @@ -23,12 +23,16 @@ import android.content.Context import android.content.Intent import android.database.Cursor import android.database.MatrixCursor +import android.os.Build import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.view.Menu import android.view.MenuItem import android.view.View import android.view.WindowManager import android.widget.AdapterView +import android.widget.EditText import android.widget.ListView import android.widget.Spinner import android.widget.TextView @@ -48,26 +52,25 @@ import com.stoutner.privacybrowser.dialogs.ViewRequestDialog // Define the public constants. const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests" +const val REQUEST_DATA_CLASS_ARRAY_LIST = "request_data_class_array_list" // Define the private class constants. private const val LISTVIEW_POSITION = "listview_position" // Define the spinner entry class constants. -private const val ALL_RESOURCE_REQUESTS = 0 -private const val DEFAULT_RESOURCE_REQUESTS = 1 -private const val ALLOWED_RESOURCE_REQUESTS = 2 -private const val BLOCKED_RESOURCE_REQUESTS = 3 -private const val THIRD_PARTY_RESOURCE_REQUESTS = 4 +private const val ALL_REQUESTS = 0 +private const val DEFAULT_REQUESTS = 1 +private const val ALLOWED_REQUESTS = 2 +private const val BLOCKED_REQUESTS = 3 +private const val THIRD_PARTY_REQUESTS = 4 class RequestsActivity : AppCompatActivity() { - companion object { - // The resource requests are populated by `MainWebViewActivity` before `RequestsActivity` is launched. - lateinit var resourceRequestsDataClassList: List - } - // Define the class views. private lateinit var requestsListView: ListView + // Declare the class variables. + private lateinit var currentRequestsDataClassArrayAdapter: RequestsArrayAdapter + public override fun onCreate(savedInstanceState: Bundle?) { // Get a handle for the shared preferences. val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) @@ -89,6 +92,12 @@ class RequestsActivity : AppCompatActivity() { // Get the status of the third-party filter list. val blockAllThirdPartyRequests = intent.getBooleanExtra(BLOCK_ALL_THIRD_PARTY_REQUESTS, false) + // Get the requests data class list. This can be simplified once the minimum API >= 33. + @Suppress("DEPRECATION") val requestsDataClassList = if (Build.VERSION.SDK_INT >= 33) + intent.getParcelableArrayListExtra(REQUEST_DATA_CLASS_ARRAY_LIST, RequestDataClass::class.java)!! + else + intent.getParcelableArrayListExtra(REQUEST_DATA_CLASS_ARRAY_LIST)!! + // Set the content view. if (bottomAppBar) setContentView(R.layout.requests_bottom_appbar) @@ -105,57 +114,58 @@ class RequestsActivity : AppCompatActivity() { val appBar = supportActionBar!! // Set the app bar custom view. - appBar.setCustomView(R.layout.spinner) + appBar.setCustomView(R.layout.spinner_app_bar) // Display the back arrow in the app bar. appBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM or ActionBar.DISPLAY_HOME_AS_UP // Get handles for the views. val appBarSpinner = findViewById(R.id.spinner) + val searchEditText = findViewById(R.id.search_edittext) requestsListView = findViewById(R.id.requests_listview) - // Initialize the resource requests data class lists. A list is needed for all the resource requests, or the activity can crash if `MainWebViewActivity.resourceRequests` is modified after the activity loads. - val allResourceRequestsDataClassList: MutableList = mutableListOf() - val defaultResourceRequestsDataClassList: MutableList = mutableListOf() - val allowedResourceRequestsDataClassList: MutableList = mutableListOf() - val blockedResourceRequestsDataClassList: MutableList = mutableListOf() - val thirdPartyResourceRequestsDataClassList: MutableList = mutableListOf() + // Initialize the requests data class lists. A list is needed for all the requests, or the activity can crash if `MainWebViewActivity.resourceRequests` is modified after the activity loads. + val allRequestsDataClassList: MutableList = mutableListOf() + val defaultRequestsDataClassList: MutableList = mutableListOf() + val allowedRequestsDataClassList: MutableList = mutableListOf() + val blockedRequestsDataClassList: MutableList = mutableListOf() + val thirdPartyRequestsDataClassList: MutableList = mutableListOf() - // Populate the resource array lists. - for (requestDataClass in resourceRequestsDataClassList) { + // Populate the requests array lists. + for (requestDataClass in requestsDataClassList) { // Add the request data class to the list of all requests. - allResourceRequestsDataClassList.add(requestDataClass) + allRequestsDataClassList.add(requestDataClass) // Add the request data class to the other, specific, list of requests. when (requestDataClass.disposition) { - RequestDisposition.Default -> defaultResourceRequestsDataClassList.add(requestDataClass) - RequestDisposition.Allowed -> allowedResourceRequestsDataClassList.add(requestDataClass) - RequestDisposition.Blocked -> blockedResourceRequestsDataClassList.add(requestDataClass) - RequestDisposition.ThirdParty -> thirdPartyResourceRequestsDataClassList.add(requestDataClass) + RequestDisposition.Default -> defaultRequestsDataClassList.add(requestDataClass) + RequestDisposition.Allowed -> allowedRequestsDataClassList.add(requestDataClass) + RequestDisposition.Blocked -> blockedRequestsDataClassList.add(requestDataClass) + RequestDisposition.ThirdParty -> thirdPartyRequestsDataClassList.add(requestDataClass) } } - // Setup a matrix cursor for the resource lists. + // Set up a matrix cursor for the requests lists. val spinnerCursor = MatrixCursor(arrayOf("_id", "Requests")) - spinnerCursor.addRow(arrayOf(ALL_RESOURCE_REQUESTS, getString(R.string.all) + " - " + allResourceRequestsDataClassList.size)) - spinnerCursor.addRow(arrayOf(DEFAULT_RESOURCE_REQUESTS, getString(R.string.default_label) + " - " + defaultResourceRequestsDataClassList.size)) - spinnerCursor.addRow(arrayOf(ALLOWED_RESOURCE_REQUESTS, getString(R.string.allowed_plural) + " - " + allowedResourceRequestsDataClassList.size)) - spinnerCursor.addRow(arrayOf(BLOCKED_RESOURCE_REQUESTS, getString(R.string.blocked_plural) + " - " + blockedResourceRequestsDataClassList.size)) + spinnerCursor.addRow(arrayOf(ALL_REQUESTS, getString(R.string.all) + " - " + allRequestsDataClassList.size)) + spinnerCursor.addRow(arrayOf(DEFAULT_REQUESTS, getString(R.string.default_label) + " - " + defaultRequestsDataClassList.size)) + spinnerCursor.addRow(arrayOf(ALLOWED_REQUESTS, getString(R.string.allowed_plural) + " - " + allowedRequestsDataClassList.size)) + spinnerCursor.addRow(arrayOf(BLOCKED_REQUESTS, getString(R.string.blocked_plural) + " - " + blockedRequestsDataClassList.size)) if (blockAllThirdPartyRequests) - spinnerCursor.addRow(arrayOf(THIRD_PARTY_RESOURCE_REQUESTS, getString(R.string.third_party_plural) + " - " + thirdPartyResourceRequestsDataClassList.size)) + spinnerCursor.addRow(arrayOf(THIRD_PARTY_REQUESTS, getString(R.string.third_party_plural) + " - " + thirdPartyRequestsDataClassList.size)) - // Create a resource cursor adapter for the spinner. + // Create a requests cursor adapter for the spinner. val spinnerCursorAdapter: ResourceCursorAdapter = object : ResourceCursorAdapter(this, R.layout.appbar_spinner_item, spinnerCursor, 0) { override fun bindView(view: View, context: Context, cursor: Cursor) { // Get a handle for the spinner item text view. val spinnerItemTextView = view.findViewById(R.id.spinner_item_textview) - // Set the text view to display the resource list. + // Set the text view to display the request list. spinnerItemTextView.text = cursor.getString(1) } } - // Set the resource cursor adapter drop down view resource. + // Set the request cursor adapter drop down view resource. spinnerCursorAdapter.setDropDownViewResource(R.layout.appbar_spinner_dropdown_item) // Set the app bar spinner adapter. @@ -167,53 +177,48 @@ class RequestsActivity : AppCompatActivity() { // Handle taps on the spinner dropdown. appBarSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - when (id.toInt()) { - ALL_RESOURCE_REQUESTS -> { - // Get an adapter for all the requests. - val allResourceRequestsArrayAdapter = RequestsArrayAdapter(context, allResourceRequestsDataClassList) - - // Display the adapter in the list view. - requestsListView.adapter = allResourceRequestsArrayAdapter - } - - DEFAULT_RESOURCE_REQUESTS -> { - // Get an adapter for the default requests. - val defaultResourceRequestsArrayAdapter = RequestsArrayAdapter(context, defaultResourceRequestsDataClassList) - - // Display the adapter in the list view. - requestsListView.adapter = defaultResourceRequestsArrayAdapter - } - - ALLOWED_RESOURCE_REQUESTS -> { - // Get an adapter for the allowed requests. - val allowedResourceRequestsArrayAdapter = RequestsArrayAdapter(context, allowedResourceRequestsDataClassList) - - // Display the adapter in the list view. - requestsListView.adapter = allowedResourceRequestsArrayAdapter - } - - BLOCKED_RESOURCE_REQUESTS -> { - // Get an adapter for the blocked requests. - val blockedResourceRequestsArrayAdapter = RequestsArrayAdapter(context, blockedResourceRequestsDataClassList) - - // Display the adapter in the list view. - requestsListView.adapter = blockedResourceRequestsArrayAdapter - } - - THIRD_PARTY_RESOURCE_REQUESTS -> { - // Get an adapter for the third-party requests. - val thirdPartyResourceRequestsArrayAdapter = RequestsArrayAdapter(context, thirdPartyResourceRequestsDataClassList) - - //Display the adapter in the list view. - requestsListView.adapter = thirdPartyResourceRequestsArrayAdapter - } + // Get the current requests data class list. + val currentRequestsDataClassList = when (id.toInt()) { + ALL_REQUESTS -> allRequestsDataClassList + DEFAULT_REQUESTS -> defaultRequestsDataClassList + ALLOWED_REQUESTS -> allowedRequestsDataClassList + BLOCKED_REQUESTS -> blockedRequestsDataClassList + THIRD_PARTY_REQUESTS -> thirdPartyRequestsDataClassList + else -> allRequestsDataClassList } + + // Get an adapter for the current requests data class. + currentRequestsDataClassArrayAdapter = RequestsArrayAdapter(context, currentRequestsDataClassList) + + // Populate the list view with the current requests data class adapter. + requestsListView.adapter = currentRequestsDataClassArrayAdapter + + // Reapply the search if the search edit text is not empty. + if (searchEditText.text.isNotEmpty()) + currentRequestsDataClassArrayAdapter.filter.filter(searchEditText.text) } override fun onNothingSelected(parent: AdapterView<*>?) { // Do nothing. } } + + // Search for the string in the list view whenever a character changes in the search edit text. + searchEditText.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) { + // Do nothing. + } + + override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) { + // Do nothing. + } + + override fun afterTextChanged(editable: Editable) { + // Search for the text in the list view. + currentRequestsDataClassArrayAdapter.filter.filter(editable.toString()) + } + }) + // Listen for taps on entries in the list view. requestsListView.onItemClickListener = AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, position: Int, _: Long -> // Display the view request dialog. The list view is 0 based, so the position must be incremented by 1. diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/FilterListArrayAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/FilterListArrayAdapter.kt index 6d0c406f..8674ab10 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/adapters/FilterListArrayAdapter.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/adapters/FilterListArrayAdapter.kt @@ -33,7 +33,8 @@ import com.stoutner.privacybrowser.dataclasses.FilterListEntryDataClass import java.util.Locale.getDefault // `0` is the `textViewResourceId`, which is unused in this implementation. -class FilterListArrayAdapter(context: Context, private val entireFilterListEntryDataClassList: List) : ArrayAdapter(context, 0, entireFilterListEntryDataClassList) { +class FilterListArrayAdapter(context: Context, private val entireFilterListEntryDataClassList: List) : + ArrayAdapter(context, 0,entireFilterListEntryDataClassList) { // Define the class variables. private var searchedFilterListEntryDataClassList = entireFilterListEntryDataClassList diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.kt index b595c7c8..3a35fe73 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/adapters/RequestsArrayAdapter.kt @@ -24,15 +24,36 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter +import android.widget.Filter import android.widget.LinearLayout import android.widget.TextView import com.stoutner.privacybrowser.R import com.stoutner.privacybrowser.dataclasses.RequestDataClass import com.stoutner.privacybrowser.dataclasses.RequestDisposition +import java.util.Locale.getDefault // `0` is the `textViewResourceId`, which is unused in this implementation. -class RequestsArrayAdapter(context: Context, resourceRequestsDataClassList: MutableList) : ArrayAdapter(context, 0, resourceRequestsDataClassList) { +class RequestsArrayAdapter(context: Context, private val entireRequestsDataClassList: List) : + ArrayAdapter(context, 0, entireRequestsDataClassList) { + // Define the class variables. + private var searchedRequestsDataClassList = entireRequestsDataClassList + + override fun getCount(): Int { + // Return the searched requests data class list size. + return searchedRequestsDataClassList.size + } + + override fun getItem(position: Int): RequestDataClass { + // Return the searched requests data class list item. + return searchedRequestsDataClassList[position] + } + + override fun getItemId(position: Int): Long { + // Return the position as a long. + return position.toLong() + } + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { // Copy the input view to a new view. var newView = convertView @@ -48,7 +69,7 @@ class RequestsArrayAdapter(context: Context, resourceRequestsDataClassList: Muta val urlTextView = newView.findViewById(R.id.request_item_url) // Get the request data class. - val requestDataClass = getItem(position)!! + val requestDataClass = getItem(position) // The ID is one greater than the position because it is 0 based. val id = position + 1 @@ -94,4 +115,41 @@ class RequestsArrayAdapter(context: Context, resourceRequestsDataClassList: Muta // Return the modified view. return newView } + + override fun getFilter(): Filter { + // Return the custom filter. + return object : Filter() { + override fun performFiltering(charSequence: CharSequence?): FilterResults { + // Get the search string, converting to lower case. + val searchString = charSequence?.toString()?.lowercase(getDefault()) + + // Create a new filter results. + val filterResults = FilterResults() + + // Filter the list. + filterResults.values = if (searchString.isNullOrEmpty()) { // The search string is null or empty. + // Return the entire requests data class list. + entireRequestsDataClassList + } else { // The search string contains data. + // Filter the list by the request URL string. + entireRequestsDataClassList.filter { + it.requestUrlString.lowercase(getDefault()).contains(searchString) + } + } + + // Return the filter results. + return filterResults + } + + override fun publishResults(charSequence: CharSequence?, filterResults: FilterResults) { + @Suppress("UNCHECKED_CAST") + // Store the searched requests data class list. + searchedRequestsDataClassList = filterResults.values as List + + // Update the GUI. + notifyDataSetChanged() + } + + } + } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt index 25abd9c5..875f10f2 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt @@ -39,7 +39,6 @@ import androidx.core.view.ViewCompat import com.stoutner.privacybrowser.activities.MainWebViewActivity import com.stoutner.privacybrowser.dataclasses.RequestDataClass -import java.util.Collections import java.util.Date import kotlin.collections.ArrayList @@ -124,7 +123,7 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS private var pinnedSslIssuedByUName = "" private var pinnedSslStartDate = Date(0) private var pinnedSslEndDate = Date(0) - private val resourceRequestsDataClassList = Collections.synchronizedList(ArrayList()) // Using a synchronized list makes adding resource requests thread safe. + private val resourceRequestsDataClassArrayList = ArrayList() private var blockedRequests = 0 private var easyListBlockedRequests = 0 private var easyPrivacyBlockedRequests = 0 @@ -234,17 +233,17 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS // Resource requests. fun addResourceRequest(resourceRequestDataClass: RequestDataClass) { // Add the resource request to the list. - resourceRequestsDataClassList.add(resourceRequestDataClass) + resourceRequestsDataClassArrayList.add(resourceRequestDataClass) } - fun getResourceRequestsDataClassList(): List { + fun getResourceRequestsDataClassList(): ArrayList { // Return the list of resource requests as an array list. - return resourceRequestsDataClassList + return resourceRequestsDataClassArrayList } fun clearResourceRequestsDataClassList() { // Clear the resource requests. - resourceRequestsDataClassList.clear() + resourceRequestsDataClassArrayList.clear() } diff --git a/app/src/main/res/layout/bookmarks_databaseview_top_appbar.xml b/app/src/main/res/layout/bookmarks_databaseview_top_appbar.xml index 1398d8e7..ca3be10b 100644 --- a/app/src/main/res/layout/bookmarks_databaseview_top_appbar.xml +++ b/app/src/main/res/layout/bookmarks_databaseview_top_appbar.xml @@ -1,28 +1,31 @@ + You should have received a copy of the GNU General Public License along with + this program. If not, see . --> + + android:layout_width="match_parent" + android:fitsSystemWindows="true" > - + - - - - + android:layout_marginTop="15dp" /> + + - + - - - - + android:layout_marginBottom="15dp" /> + SPDX-FileCopyrightText: 2018-2022, 2024-2026 Soren Stoutner This file is part of Privacy Browser Android . @@ -50,6 +50,19 @@ android:background="?android:attr/colorBackground" android:theme="@style/PrivacyBrowserAppBar" > + + + + + SPDX-FileCopyrightText: 2018-2022, 2024-2026 Soren Stoutner This file is part of Privacy Browser Android . @@ -41,10 +41,23 @@ android:background="?android:attr/colorBackground" android:theme="@style/PrivacyBrowserAppBar" > + + + + diff --git a/app/src/main/res/layout/spinner.xml b/app/src/main/res/layout/spinner.xml deleted file mode 100644 index 59fdb4dd..00000000 --- a/app/src/main/res/layout/spinner.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/app/src/main/res/layout/spinner_app_bar.xml b/app/src/main/res/layout/spinner_app_bar.xml new file mode 100644 index 00000000..c930e188 --- /dev/null +++ b/app/src/main/res/layout/spinner_app_bar.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fddfb8b4..c3650a9c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -18,7 +18,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 -- 2.53.0