-/*
- * Copyright © 2019-2023 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
- *
- * Privacy Browser Android is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Privacy Browser Android is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.stoutner.privacybrowser.adapters
-
-import android.os.Bundle
-import android.os.Handler
-import android.os.Looper
-import android.widget.FrameLayout
-
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.FragmentPagerAdapter
-import androidx.viewpager.widget.ViewPager
-
-import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.fragments.WebViewTabFragment
-import com.stoutner.privacybrowser.fragments.WebViewTabFragment.Companion.createPage
-import com.stoutner.privacybrowser.views.NestedScrollWebView
-
-import java.util.LinkedList
-
-class WebViewPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
- // Define the class values.
- private val webViewFragmentsList = LinkedList<WebViewTabFragment>()
-
- override fun getCount(): Int {
- // Return the number of pages.
- return webViewFragmentsList.size
- }
-
- override fun getItem(pageNumber: Int): Fragment {
- // Get the fragment for a particular page. Page numbers are 0 indexed.
- return webViewFragmentsList[pageNumber]
- }
-
- override fun getItemId(position: Int): Long {
- // Return the unique ID for this page.
- return webViewFragmentsList[position].fragmentId
- }
-
- override fun getItemPosition(`object`: Any): Int {
- return if (webViewFragmentsList.contains(`object`)) {
- // Return the current page position.
- webViewFragmentsList.indexOf(`object`)
- } else {
- // The tab has been deleted.
- POSITION_NONE
- }
- }
-
- fun addPage(pageNumber: Int, webViewPager: ViewPager, url: String, moveToNewPage: Boolean) {
- // Add a new page.
- webViewFragmentsList.add(createPage(pageNumber, url))
-
- // Update the view pager.
- notifyDataSetChanged()
-
- // Move to the new page if indicated.
- if (moveToNewPage) {
- moveToNewPage(pageNumber, webViewPager)
- }
- }
-
- fun deletePage(pageNumber: Int, webViewPager: ViewPager): Boolean {
- // Get the WebView tab fragment.
- val webViewTabFragment = webViewFragmentsList[pageNumber]
-
- // Get the WebView frame layout.
- val webViewFrameLayout = (webViewTabFragment.view as FrameLayout?)!!
-
- // Get a handle for the nested scroll WebView.
- val nestedScrollWebView = webViewFrameLayout.findViewById<NestedScrollWebView>(R.id.nestedscroll_webview)
-
- // Pause the current WebView.
- nestedScrollWebView.onPause()
-
- // Remove all the views from the frame layout.
- webViewFrameLayout.removeAllViews()
-
- // Destroy the current WebView.
- nestedScrollWebView.destroy()
-
- // Delete the page.
- webViewFragmentsList.removeAt(pageNumber)
-
- // Update the view pager.
- notifyDataSetChanged()
-
- // 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).
- // This will cause the calling method to reset the current WebView to the new contents of this page number.
- return webViewPager.currentItem == pageNumber
- }
-
- fun getPageFragment(pageNumber: Int): WebViewTabFragment {
- // Return the page fragment.
- return webViewFragmentsList[pageNumber]
- }
-
- fun getPositionForId(fragmentId: Long): Int {
- // Initialize the position variable.
- var position = -1
-
- // Initialize the while counter.
- var i = 0
-
- // Find the current position of the WebView fragment with the given ID.
- while (position < 0 && i < webViewFragmentsList.size) {
- // Check to see if the tab ID of this WebView matches the page ID.
- if (webViewFragmentsList[i].fragmentId == fragmentId) {
- // Store the position if they are a match.
- position = i
- }
-
- // Increment the counter.
- i++
- }
-
- // Set the position to be the last tab if it is not found.
- // 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.
- // In that case, the last tab should be the one it is looking for.
- if (position == -1) {
- position = webViewFragmentsList.size - 1
- }
-
- // Return the position.
- return position
- }
-
- fun restorePage(savedState: Bundle, savedNestedScrollWebViewState: Bundle) {
- // Restore the page.
- webViewFragmentsList.add(WebViewTabFragment.restorePage(savedState, savedNestedScrollWebViewState))
-
- // Update the view pager.
- notifyDataSetChanged()
- }
-
- private fun moveToNewPage(pageNumber: Int, webViewPager: ViewPager) {
- // Check to see if the new page has been populated.
- if (webViewPager.childCount >= pageNumber) { // The new page is ready.
- // Move to the new page.
- webViewPager.currentItem = pageNumber
- } else { // The new page is not yet ready.
- // Create a handler.
- val moveToNewPageHandler = Handler(Looper.getMainLooper())
-
- // Create a runnable.
- val moveToNewPageRunnable = Runnable {
- // Move to the new page.
- webViewPager.currentItem = pageNumber
- }
-
- // Try again to move to the new page after 50 milliseconds.
- moveToNewPageHandler.postDelayed(moveToNewPageRunnable, 50)
- }
- }
-}