]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - RequestsActivity.kt
11efe094d9d8fc8c88a2e07eddea9154735b5cd8
[PrivacyBrowserAndroid.git] / RequestsActivity.kt
1 /*
2  * Copyright 2018-2023 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.activities
21
22 import android.content.Context
23 import android.database.Cursor
24 import android.database.MatrixCursor
25 import android.os.Bundle
26 import android.view.View
27 import android.view.WindowManager
28 import android.widget.AdapterView
29 import android.widget.ArrayAdapter
30 import android.widget.ListView
31 import android.widget.Spinner
32 import android.widget.TextView
33
34 import androidx.appcompat.app.ActionBar
35 import androidx.appcompat.app.AppCompatActivity
36 import androidx.appcompat.widget.Toolbar
37 import androidx.cursoradapter.widget.ResourceCursorAdapter
38 import androidx.fragment.app.DialogFragment
39 import androidx.preference.PreferenceManager
40
41 import com.stoutner.privacybrowser.R
42 import com.stoutner.privacybrowser.adapters.RequestsArrayAdapter
43 import com.stoutner.privacybrowser.dialogs.ViewRequestDialog.Companion.request
44 import com.stoutner.privacybrowser.dialogs.ViewRequestDialog.ViewRequestListener
45 import com.stoutner.privacybrowser.helpers.REQUEST_ALLOWED
46 import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKED
47 import com.stoutner.privacybrowser.helpers.REQUEST_DEFAULT
48 import com.stoutner.privacybrowser.helpers.REQUEST_DISPOSITION
49 import com.stoutner.privacybrowser.helpers.REQUEST_THIRD_PARTY
50
51 // Define the public constants.
52 const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests"
53
54 // Define the private class constants.
55 private const val LISTVIEW_POSITION = "listview_position"
56
57 class RequestsActivity : AppCompatActivity(), ViewRequestListener {
58     companion object {
59         // The resource requests are populated by `MainWebViewActivity` before `RequestsActivity` is launched.
60         var resourceRequests: List<Array<String>>? = null
61     }
62
63     // Define the class views.
64     private lateinit var requestsListView: ListView
65
66     public override fun onCreate(savedInstanceState: Bundle?) {
67         // Get a handle for the shared preferences.
68         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
69
70         // Get the preferences.
71         val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
72         val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
73
74         // Disable screenshots if not allowed.
75         if (!allowScreenshots) {
76             window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
77         }
78
79         // Run the default commands.
80         super.onCreate(savedInstanceState)
81
82         // Get the launching intent
83         val intent = intent
84
85         // Get the status of the third-party filter list.
86         val blockAllThirdPartyRequests = intent.getBooleanExtra(BLOCK_ALL_THIRD_PARTY_REQUESTS, false)
87
88         // Set the content view.
89         if (bottomAppBar) {
90             setContentView(R.layout.requests_bottom_appbar)
91         } else {
92             setContentView(R.layout.requests_top_appbar)
93         }
94
95         // Get a handle for the toolbar.
96         val toolbar = findViewById<Toolbar>(R.id.requests_toolbar)
97
98         // Set the support action bar.
99         setSupportActionBar(toolbar)
100
101         // Get a handle for the app bar.
102         val appBar = supportActionBar!!
103
104         // Set the app bar custom view.
105         appBar.setCustomView(R.layout.spinner)
106
107         // Display the back arrow in the app bar.
108         appBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM or ActionBar.DISPLAY_HOME_AS_UP
109
110         // Get handles for the views.
111         val appBarSpinner = findViewById<Spinner>(R.id.spinner)
112         requestsListView = findViewById(R.id.requests_listview)
113
114         // Initialize the resource array lists.  A list is needed for all the resource requests, or the activity can crash if `MainWebViewActivity.resourceRequests` is modified after the activity loads.
115         val allResourceRequests: MutableList<Array<String>> = ArrayList()
116         val defaultResourceRequests: MutableList<Array<String>> = ArrayList()
117         val allowedResourceRequests: MutableList<Array<String>> = ArrayList()
118         val thirdPartyResourceRequests: MutableList<Array<String>> = ArrayList()
119         val blockedResourceRequests: MutableList<Array<String>> = ArrayList()
120
121         // Populate the resource array lists.
122         for (request in resourceRequests!!) {
123             // Add the request to the list of all requests.
124             allResourceRequests.add(request)
125
126             when (request[REQUEST_DISPOSITION]) {
127                 REQUEST_DEFAULT -> {
128                     // Add the request to the list of default requests.
129                     defaultResourceRequests.add(request)
130                 }
131
132                 REQUEST_ALLOWED -> {
133                     // Add the request to the list of allowed requests.
134                     allowedResourceRequests.add(request)
135                 }
136
137                 REQUEST_THIRD_PARTY -> {
138                     // Add the request to the list of third-party requests.
139                     thirdPartyResourceRequests.add(request)
140                 }
141
142                REQUEST_BLOCKED -> {
143                     // Add the request to the list of blocked requests.
144                     blockedResourceRequests.add(request)
145                 }
146             }
147         }
148
149         // Setup a matrix cursor for the resource lists.
150         val spinnerCursor = MatrixCursor(arrayOf("_id", "Requests"))
151         spinnerCursor.addRow(arrayOf<Any>(0, getString(R.string.all) + " - " + allResourceRequests.size))
152         spinnerCursor.addRow(arrayOf<Any>(1, getString(R.string.default_label) + " - " + defaultResourceRequests.size))
153         spinnerCursor.addRow(arrayOf<Any>(2, getString(R.string.allowed_plural) + " - " + allowedResourceRequests.size))
154         if (blockAllThirdPartyRequests)
155             spinnerCursor.addRow(arrayOf<Any>(3, getString(R.string.third_party_plural) + " - " + thirdPartyResourceRequests.size))
156         spinnerCursor.addRow(arrayOf<Any>(4, getString(R.string.blocked_plural) + " - " + blockedResourceRequests.size))
157
158         // Create a resource cursor adapter for the spinner.
159         val spinnerCursorAdapter: ResourceCursorAdapter = object : ResourceCursorAdapter(this, R.layout.requests_appbar_spinner_item, spinnerCursor, 0) {
160             override fun bindView(view: View, context: Context, cursor: Cursor) {
161                 // Get a handle for the spinner item text view.
162                 val spinnerItemTextView = view.findViewById<TextView>(R.id.spinner_item_textview)
163
164                 // Set the text view to display the resource list.
165                 spinnerItemTextView.text = cursor.getString(1)
166             }
167         }
168
169         // Set the resource cursor adapter drop down view resource.
170         spinnerCursorAdapter.setDropDownViewResource(R.layout.requests_appbar_spinner_dropdown_item)
171
172         // Set the app bar spinner adapter.
173         appBarSpinner.adapter = spinnerCursorAdapter
174
175         // Get a handle for the context.
176         val context: Context = this
177
178         // Handle clicks on the spinner dropdown.
179         appBarSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
180             override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
181                 when (id.toInt()) {
182                     0 -> {
183                         // Get an adapter for all the requests.
184                         val allResourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, allResourceRequests)
185
186                         // Display the adapter in the list view.
187                         requestsListView.adapter = allResourceRequestsArrayAdapter
188                     }
189
190                     1 -> {
191                         // Get an adapter for the default requests.
192                         val defaultResourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, defaultResourceRequests)
193
194                         // Display the adapter in the list view.
195                         requestsListView.adapter = defaultResourceRequestsArrayAdapter
196                     }
197
198                     2 -> {
199                         // Get an adapter for the allowed requests.
200                         val allowedResourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, allowedResourceRequests)
201
202                         // Display the adapter in the list view.
203                         requestsListView.adapter = allowedResourceRequestsArrayAdapter
204                     }
205
206                     3 -> {
207                         // Get an adapter for the third-party requests.
208                         val thirdPartyResourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, thirdPartyResourceRequests)
209
210                         //Display the adapter in the list view.
211                         requestsListView.adapter = thirdPartyResourceRequestsArrayAdapter
212                     }
213
214                     4 -> {
215                         // Get an adapter for the blocked requests.
216                         val blockedResourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, blockedResourceRequests)
217
218                         // Display the adapter in the list view.
219                         requestsListView.adapter = blockedResourceRequestsArrayAdapter
220                     }
221                 }
222             }
223
224             override fun onNothingSelected(parent: AdapterView<*>?) {
225                 // Do nothing.
226             }
227         }
228
229         // Create an array adapter with the list of the resource requests.
230         val resourceRequestsArrayAdapter: ArrayAdapter<Array<String>> = RequestsArrayAdapter(context, allResourceRequests)
231
232         // Populate the list view with the resource requests adapter.
233         requestsListView.adapter = resourceRequestsArrayAdapter
234
235         // Listen for taps on entries in the list view.
236         requestsListView.onItemClickListener = AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, position: Int, _: Long ->
237             // Display the view request dialog.  The list view is 0 based, so the position must be incremented by 1.
238             launchViewRequestDialog(position + 1)
239         }
240
241         // Check to see if the activity has been restarted.
242         if (savedInstanceState != null) {
243             // Scroll to the saved position.
244             requestsListView.post { requestsListView.setSelection(savedInstanceState.getInt(LISTVIEW_POSITION)) }
245         }
246     }
247
248     public override fun onSaveInstanceState(savedInstanceState: Bundle) {
249         // Run the default commands.
250         super.onSaveInstanceState(savedInstanceState)
251
252         // Get the listview position.
253         val listViewPosition = requestsListView.firstVisiblePosition
254
255         // Store the listview position in the bundle.
256         savedInstanceState.putInt(LISTVIEW_POSITION, listViewPosition)
257     }
258
259     override fun onPrevious(currentId: Int) {
260         // Show the previous dialog.
261         launchViewRequestDialog(currentId - 1)
262     }
263
264     override fun onNext(currentId: Int) {
265         // Show the next dialog.
266         launchViewRequestDialog(currentId + 1)
267     }
268
269     private fun launchViewRequestDialog(id: Int) {
270         // Determine if this is the last request in the list.
271         val isLastRequest = (id == requestsListView.count)
272
273         // Get the string array for the selected resource request.  The resource requests list view is zero based.  There is no need to check to make sure each string is not null because
274         @Suppress("UNCHECKED_CAST") val selectedRequestStringArray = (requestsListView.getItemAtPosition(id - 1) as Array<String>)
275
276         // Create a view request dialog.
277         val viewRequestDialogFragment: DialogFragment = request(id, isLastRequest, selectedRequestStringArray)
278
279         // Make it so.
280         viewRequestDialogFragment.show(supportFragmentManager, getString(R.string.request_details))
281     }
282 }