]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt
First wrong button text in View Headers in night theme. https://redmine.stoutner...
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / dialogs / UrlHistoryDialog.kt
1 /*
2  * Copyright 2016-2024 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.dialogs
21
22 import android.app.Dialog
23 import android.content.Context
24 import android.content.DialogInterface
25 import android.graphics.drawable.BitmapDrawable
26 import android.os.Bundle
27 import android.view.View
28 import android.view.WindowManager
29 import android.widget.AdapterView
30 import android.widget.AdapterView.OnItemClickListener
31 import android.widget.ListView
32
33 import androidx.appcompat.app.AlertDialog
34 import androidx.core.content.ContextCompat
35 import androidx.fragment.app.DialogFragment
36 import androidx.preference.PreferenceManager
37
38 import com.stoutner.privacybrowser.R
39 import com.stoutner.privacybrowser.activities.MainWebViewActivity
40 import com.stoutner.privacybrowser.adapters.HistoryArrayAdapter
41 import com.stoutner.privacybrowser.dataclasses.HistoryDataClass
42 import com.stoutner.privacybrowser.views.NestedScrollWebView
43
44 // Define the class constants.
45 private const val WEBVIEW_FRAGMENT_ID = "A"
46
47 class UrlHistoryDialog : DialogFragment() {
48     companion object {
49         fun loadBackForwardList(webViewFragmentId: Long): UrlHistoryDialog {
50             // Create an arguments bundle.
51             val argumentsBundle = Bundle()
52
53             // Store the WebView fragment ID in the bundle.
54             argumentsBundle.putLong(WEBVIEW_FRAGMENT_ID, webViewFragmentId)
55
56             // Create a new instance of the URL history dialog.
57             val urlHistoryDialog = UrlHistoryDialog()
58
59             // Add the arguments bundle to the new dialog.
60             urlHistoryDialog.arguments = argumentsBundle
61
62             // Return the new dialog.
63             return urlHistoryDialog
64         }
65     }
66
67     // Declare the class variables.
68     private lateinit var navigateHistoryListener: NavigateHistoryListener
69
70     // The public interface is used to send information back to the parent activity.
71     interface NavigateHistoryListener {
72         fun navigateHistory(steps: Int)
73     }
74
75     override fun onAttach(context: Context) {
76         // Run the default commands.
77         super.onAttach(context)
78
79         // Get a handle for the listener from the launching context.
80         navigateHistoryListener = context as NavigateHistoryListener
81     }
82
83     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
84         // Get the WebView fragment ID from the arguments.
85         val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
86
87         // Get the current position of this WebView fragment.
88         val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
89
90         // Get the WebView tab fragment.
91         val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
92
93         // Get the fragment view.
94         val fragmentView = webViewTabFragment.requireView()
95
96         // Get a handle for the current nested scroll WebView.
97         val nestedScrollWebView: NestedScrollWebView = fragmentView.findViewById(R.id.nestedscroll_webview)
98
99         // Get the web back forward list from the nested scroll WebView.
100         val webBackForwardList = nestedScrollWebView.copyBackForwardList()
101
102         // Store the current page index.
103         val currentPageIndex = webBackForwardList.currentIndex
104
105         // Get the default favorite icon drawable.  `ContextCompat` must be used until the minimum API >= 21.
106         val defaultFavoriteIconDrawable = ContextCompat.getDrawable(requireContext(), R.drawable.world)
107
108         // Convert the default favorite icon drawable to a bitmap drawable.
109         val defaultFavoriteIconBitmapDrawable = (defaultFavoriteIconDrawable as BitmapDrawable)
110
111         // Extract a bitmap from the default favorite icon bitmap drawable.
112         val defaultFavoriteIcon = defaultFavoriteIconBitmapDrawable.bitmap
113
114         // Create a history array list.
115         val historyDataClassArrayList = ArrayList<HistoryDataClass>()
116
117         // Populate the history array list, descending from the end of the list so that the newest entries are at the top.  `-1` is needed because the history array list is zero-based.
118         for (i in webBackForwardList.size - 1 downTo 0) {
119             // Store the favorite icon bitmap.
120             val favoriteIconBitmap = if (webBackForwardList.getItemAtIndex(i).favicon == null) {
121                 // If the web back forward list does not have a favorite icon, use Privacy Browser's default world icon.
122                 defaultFavoriteIcon
123             } else {  // Use the icon from the web back forward list.
124                 webBackForwardList.getItemAtIndex(i).favicon
125             }
126
127             // Store the favorite icon and the URL in history entry.
128             val historyDataClassEntry = HistoryDataClass(favoriteIconBitmap!!, webBackForwardList.getItemAtIndex(i).url)
129
130             // Add this history entry to the history array list.
131             historyDataClassArrayList.add(historyDataClassEntry)
132         }
133
134         // Subtract the original current page ID from the array size because the order of the array is reversed so that the newest entries are at the top.  `-1` is needed because the array is zero-based.
135         val currentPageId = webBackForwardList.size - 1 - currentPageIndex
136
137         // Use an alert dialog builder to create the alert dialog.
138         val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.PrivacyBrowserAlertDialog)
139
140         // Set the title.
141         dialogBuilder.setTitle(R.string.history)
142
143         // Set the view.
144         dialogBuilder.setView(R.layout.url_history_dialog)
145
146         // Setup the clear history button listener.
147         dialogBuilder.setNegativeButton(R.string.clear_history) { _: DialogInterface, _: Int ->
148             // Clear the history.
149             nestedScrollWebView.clearHistory()
150         }
151
152         // Set the close button listener.  Using `null` as the listener closes the dialog without doing anything else.
153         dialogBuilder.setPositiveButton(R.string.close, null)
154
155         // Create an alert dialog from the alert dialog builder.
156         val alertDialog = dialogBuilder.create()
157
158         // Get a handle for the shared preferences.
159         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext())
160
161         // Get the screenshot preference.
162         val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
163
164         // Disable screenshots if not allowed.
165         if (!allowScreenshots) {
166             // Disable screenshots.
167             alertDialog.window!!.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
168         }
169
170         //The alert dialog must be shown before the contents can be modified.
171         alertDialog.show()
172
173         // Instantiate a history array adapter.
174         val historyArrayAdapter = HistoryArrayAdapter(requireContext(), historyDataClassArrayList, currentPageId)
175
176         // Get a handle for the list view.
177         val listView = alertDialog.findViewById<ListView>(R.id.history_listview)!!
178
179         // Set the list view adapter.
180         listView.adapter = historyArrayAdapter
181
182         // Listen for clicks on entries in the list view.
183         listView.onItemClickListener = OnItemClickListener { _: AdapterView<*>?, _: View, _: Int, id: Long ->
184             // Convert the long ID to an int.
185             val itemId = id.toInt()
186
187             // Only consume the click if it is not on the current page ID.
188             if (itemId != currentPageId) {
189                 // Invoke the navigate history listener in the calling activity.  Those commands cannot be run here because they need access to `applyDomainSettings()`.
190                 navigateHistoryListener.navigateHistory(currentPageId - itemId)
191
192                 // Dismiss the alert dialog.
193                 alertDialog.dismiss()
194             }
195         }
196
197         // Return the alert dialog.
198         return alertDialog
199     }
200 }