]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewStateAdapter.kt
e67a99a3abeb717fdf406196b4646b89bc2118eb
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / adapters / WebViewStateAdapter.kt
1 /*
2  * Copyright 2019-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.adapters
21
22 import android.os.Bundle
23 import android.widget.FrameLayout
24
25 import androidx.fragment.app.Fragment
26 import androidx.fragment.app.FragmentActivity
27 import androidx.recyclerview.widget.RecyclerView.NO_ID
28 import androidx.viewpager2.adapter.FragmentStateAdapter
29 import androidx.viewpager2.widget.ViewPager2
30
31 import com.google.android.material.tabs.TabLayout
32
33 import com.stoutner.privacybrowser.R
34 import com.stoutner.privacybrowser.fragments.WebViewTabFragment
35 import com.stoutner.privacybrowser.views.NestedScrollWebView
36
37 import java.util.LinkedList
38
39 class WebViewStateAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
40     // Define the class variables.
41     private val webViewFragmentsList = LinkedList<WebViewTabFragment>()
42
43     // Get a page fragment.
44     override fun createFragment(pageNumber: Int): Fragment {
45         // Get the fragment for a particular page.  Page numbers are 0 indexed.
46         return webViewFragmentsList[pageNumber]
47     }
48
49     override fun containsItem(itemId: Long): Boolean {
50         // Initialize the position variable.
51         var position = -1
52
53         // Initialize the while counter.
54         var i = 0
55
56         // Find the current position of the WebView fragment with the given ID.
57         while ((position < 0) && (i < webViewFragmentsList.size)) {
58             // Check to see if the tab ID of this WebView matches the page ID.
59             if (webViewFragmentsList[i].fragmentId == itemId) {
60                 // Store the position if they are a match.
61                 position = i
62             }
63
64             // Increment the counter.
65             i++
66         }
67
68         // Return true if the item was found in the WebView fragments list.
69         return (position != -1)
70     }
71
72     // Get the number of tabs.
73     override fun getItemCount(): Int {
74         // Return the number of pages.
75         return webViewFragmentsList.size
76     }
77
78     // Get the unique ID for the item.
79     override fun getItemId(position: Int): Long {
80         // Return the unique ID for this page.
81         return if ((position >= 0) && (position < webViewFragmentsList.size))  // The position is 0 based, so it is contained in the WebView fragment list.
82             webViewFragmentsList[position].fragmentId
83         else  // The item does not exist.
84             NO_ID
85     }
86
87     fun addPage(pageNumber: Int, newTab: TabLayout.Tab, url: String, moveToNewPage: Boolean) {
88         // Add a new page.
89         webViewFragmentsList.add(WebViewTabFragment.createPage(pageNumber, url))
90
91         // Update the view pager.
92         notifyItemInserted(pageNumber)
93
94         // Move to the new page if indicated.
95         if (moveToNewPage) {
96             // Select the newTab.
97             newTab.select()
98         }
99     }
100
101     fun deletePage(pageNumber: Int, webViewPager2: ViewPager2): Boolean {
102         // Get the WebView tab fragment.
103         val webViewTabFragment = webViewFragmentsList[pageNumber]
104
105         // Get the WebView frame layout.
106         val webViewFrameLayout = (webViewTabFragment.view as FrameLayout)
107
108         // Get a handle for the nested scroll WebView.
109         val nestedScrollWebView = webViewFrameLayout.findViewById<NestedScrollWebView>(R.id.nestedscroll_webview)
110
111         // Pause the current WebView.
112         nestedScrollWebView.onPause()
113
114         // Remove all the views from the frame layout.
115         webViewFrameLayout.removeAllViews()
116
117         // Destroy the current WebView.
118         nestedScrollWebView.destroy()
119
120         // Delete the page.
121         webViewFragmentsList.removeAt(pageNumber)
122
123         // Update the view pager.
124         notifyItemRemoved(pageNumber)
125
126         // Return true if the selected page number did not change after the delete (because the newly selected tab has has same number as the previously deleted tab).
127         // This will cause the calling method to reset the current WebView to the new contents of this page number.
128         return (webViewPager2.currentItem == pageNumber)
129     }
130
131     fun getPageFragment(pageNumber: Int): WebViewTabFragment {
132         // Return the page fragment.
133         return webViewFragmentsList[pageNumber]
134     }
135
136     fun getPositionForId(fragmentId: Long): Int {
137         // Initialize the position variable.
138         var position = -1
139
140         // Initialize the while counter.
141         var i = 0
142
143         // Find the current position of the WebView fragment with the given ID.
144         while ((position < 0) && (i < webViewFragmentsList.size)) {
145             // Check to see if the tab ID of this WebView matches the page ID.
146             if (webViewFragmentsList[i].fragmentId == fragmentId) {
147                 // Store the position if they are a match.
148                 position = i
149             }
150
151             // Increment the counter.
152             i++
153         }
154
155         // Set the position to be the last tab if it is not found.
156         // Sometimes there is a race condition in populating the webView fragments list when resuming Privacy Browser and displaying an SSL certificate error while loading a new intent.
157         // In that case, the last tab should be the one it is looking for, which is one less than the size because it is zero based.
158         if (position == -1)
159             position = (webViewFragmentsList.size - 1)
160
161         // Return the position.
162         return position
163     }
164
165     fun restorePage(savedState: Bundle, savedNestedScrollWebViewState: Bundle) {
166         // Restore the page.
167         webViewFragmentsList.add(WebViewTabFragment.restorePage(savedState, savedNestedScrollWebViewState))
168
169         // Update the view pager.  The position is zero indexed.
170         notifyItemInserted(webViewFragmentsList.size - 1)
171     }
172 }