]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/commitdiff
Switch the FragmentPagerAdapters to FragmentStateAdapters. https://redmine.stoutner...
authorSoren Stoutner <soren@stoutner.com>
Wed, 17 May 2023 16:35:54 +0000 (09:35 -0700)
committerSoren Stoutner <soren@stoutner.com>
Wed, 17 May 2023 16:35:54 +0000 (09:35 -0700)
39 files changed:
app/src/main/assets/de/about_changelog.html
app/src/main/assets/en/about_changelog.html
app/src/main/assets/es/about_changelog.html
app/src/main/assets/fr/about_changelog.html
app/src/main/assets/it/about_changelog.html
app/src/main/assets/it/about_licenses.html
app/src/main/assets/it/guide_requests.html
app/src/main/assets/pt-rBR/about_changelog.html
app/src/main/assets/ru/about_changelog.html
app/src/main/assets/tr/about_changelog.html
app/src/main/assets/zh-rCN/about_changelog.html
app/src/main/java/com/stoutner/privacybrowser/activities/AboutActivity.kt
app/src/main/java/com/stoutner/privacybrowser/activities/GuideActivity.kt
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt
app/src/main/java/com/stoutner/privacybrowser/adapters/AboutPagerAdapter.kt [deleted file]
app/src/main/java/com/stoutner/privacybrowser/adapters/AboutStateAdapter.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/adapters/GuidePagerAdapter.kt [deleted file]
app/src/main/java/com/stoutner/privacybrowser/adapters/GuideStateAdapter.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/adapters/PinnedMismatchPagerAdapter.kt
app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewPagerAdapter.kt [deleted file]
app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewStateAdapter.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/coroutines/SaveUrlCoroutine.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/HttpAuthenticationDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/PinnedMismatchDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/SslCertificateErrorDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/UrlHistoryDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/ViewSslCertificateDialog.kt
app/src/main/java/com/stoutner/privacybrowser/views/NoSwipeViewPager.kt [deleted file]
app/src/main/res/layout/about_bottom_appbar.xml
app/src/main/res/layout/about_top_appbar.xml
app/src/main/res/layout/guide_bottom_appbar.xml
app/src/main/res/layout/guide_top_appbar.xml
app/src/main/res/layout/main_framelayout_bottom_appbar.xml
app/src/main/res/layout/main_framelayout_top_appbar.xml
app/src/main/res/values-it/strings.xml
fastlane/metadata/android/de-DE/changelogs/69.txt [new file with mode: 0644]
fastlane/metadata/android/it-IT/images/phoneScreenshots/03-OptionsMenu-it.png
fastlane/metadata/android/ru-RU/changelogs/69.txt [new file with mode: 0644]
gradle.properties

index 2dca81640c14822b06802e776f9d24f5993cd8d7..bb1999bc65cc123bc39afc9e0afec949ad38c0ed 100644 (file)
     </head>
 
     <body>
-        <h3>3.14 (Version Code 69)</h3>
-        <p>6. Mai 2023 - Mindest-API 24, Ziel-API 33</p>
-        <ul>
-            <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
-            <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
-            <li>Standardize the <a href="https://redmine.stoutner.com/issues/951">suggested file names</a>.</li>
-            <li>Update the app bar <a href="https://redmine.stoutner.com/issues/998">proxy background color</a>.</li>
-            <li><a href="https://redmine.stoutner.com/issues/700">Restore the scroll position</a> when restarting the settings app.</li>
-            <li>Migrate the last of the code to <a href="https://redmine.stoutner.com/issues/989">Kotlin</a> and remove the deprecated <a href="https://redmine.stoutner.com/issues/987">AsyncTasks</a>.</li>
-            <li>Optimize <a href="https://redmine.stoutner.com/issues/990">several</a> <a href="https://redmine.stoutner.com/issues/991">pieces</a> of the
-                <a href="https://redmine.stoutner.com/issues/953">code</a> to run more efficiently.</li>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (Version Code 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6. Mai 2023</a> - Mindest-API 24, Ziel-API 33</p>
+        <ul>
+            <li><a href="https://redmine.stoutner.com/issues/886">Nicht den voreingestellten Werten entsprechende Domain-Einstellungen</a> werden nun durch einen geänderten Hintergrund hervorgehoben.</li>
+            <li>Die Bezeichnungen <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> und <code>blacklist</code></a> wurden aus dem Projekt entfernt.</li>
+            <li><a href="https://redmine.stoutner.com/issues/951">Vorgeschlagene Dateinamen</a> wurden vereinheitlicht.</li>
+            <li><a href="https://redmine.stoutner.com/issues/998">Hintergrundfarbe der App-Leiste bei Verwendung von Proxies</a> wurde geändert.</li>
+            <li><a href="https://redmine.stoutner.com/issues/700">Die Scroll-Position wird wiederhergestellt</a>, wenn der Einstellungs-Dialog neu gestartet wird.</li>
+            <li>Letzte Programmteile nach <a href="https://redmine.stoutner.com/issues/989">Kotlin</a> migriert und veraltete <a href="https://redmine.stoutner.com/issues/987">AsyncTasks</a> entfernt.</li>
+            <li><a href="https://redmine.stoutner.com/issues/990">Diverse</a> <a href="https://redmine.stoutner.com/issues/991">kleine</a>
+                <a href="https://redmine.stoutner.com/issues/953">Code-Optimierungen</a> für einen effizienteren Programmablauf.</li>
             <li>Aktualisierte deutsche Übersetzung von Bernhard G. Keller.</li>
         </ul>
 
index 8fc614c1470c9af4edbe1a74eba32f90fac6f9d4..f8fce6c9331148a59094d77c2d16275b6ca5992a 100644 (file)
@@ -27,8 +27,8 @@
     </head>
 
     <body>
-        <h3>3.14 (version code 69)</h3>
-        <p>6 May 2023 - minimum API 24, target API 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (version code 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 May 2023</a> - minimum API 24, target API 33</p>
         <ul>
             <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
             <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
index d99ffd5c411da8d887393ea4d7a31391bda1ee8a..532917fd16d97467f944cae61a1296749d3f520c 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>3.14 (código de versión 69)</h3>
-        <p>6 de mayo de 2023 - API mínimo 24, API objetivo 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (código de versión 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 de mayo de 2023</a> - API mínimo 24, API objetivo 33</p>
         <ul>
             <li>Resaltar el fondo de las configuraciones de dominio que no son <a href="https://redmine.stoutner.com/issues/886">por defecto</a>.</li>
             <li>Eliminar los términos <a href="https://redmine.stoutner.com/issues/705"><code>lista blanca</code> y <code>lista negra</code></a> del proyecto.</li>
index c37363f0926a45b527e28c26d656a5a7820c2159..9a48e7fad7ba8841cd91e95540fb02add9cec6fa 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>3.14 (version du code 69)</h3>
-        <p>6 Mai 2023 - API minimale : 24, API optimale : 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (version du code 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 Mai 2023</a> - API minimale : 24, API optimale : 33</p>
         <ul>
             <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
             <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
index 3666257a9b1f3f8f3f4cb16681fd234c402dbb4c..ba6f4805e28399be2c76cd83772d5a09f4fd605a 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>3.14 (versione codice 69)</h3>
-        <p>6 Maggio 2023 - minima API 24, target API 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (versione codice 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 Maggio 2023</a> - minima API 24, target API 33</p>
         <ul>
             <li>Colorazione dello sfondo delle impostazioni dei domini diverse dalle impostazioni <a href="https://redmine.stoutner.com/issues/886">di default</a>.</li>
             <li>Eliminazione dei termini <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> e <code>blacklist</code></a> dal progetto.</li>
index 17339e6c4c13d18d823bf3f14f7aa3377f7f6c5b..3d7ae86c411ed24be72d19f908440a37388b7007 100644 (file)
@@ -1,7 +1,7 @@
 <!--
   Copyright 2017-2023 Soren Stoutner <soren@stoutner.com>.
 
-  Translation 2017-2020,2022 Francesco Buratti.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+  Translation 2017-2020,2022-2023 Francesco Buratti.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
@@ -42,7 +42,7 @@
             E' inoltre ammessa la modifica e la pubblicazione di questa traduzione, ma solamente in accordo ai termini <a href="https://www.gnu.org/licenses/translations.html">qui</a> riportati.
             Il codice sorgente è disponibile su <a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=summary">gitweb.stoutner.com</a>.</p>
 
-        <h3>Filter Lists</h3>
+        <h3>Lista dei filtri</h3>
         <p><a href="https://easylist.to/easylist/easylist.txt">EasyList</a> e <a href="https://easylist.to/easylist/easyprivacy.txt">EasyPrivacy</a>
             sono <a href="https://easylist.to/pages/licence.html">sotto doppia licenza</a> con le licenze <a href="https://www.gnu.org/licenses/gpl-3.0.html">GPLv3+</a>
             e <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0+ Unported</a>. Privacy Browser le incorpora utilizzando l'opzione GPLv3+.</p>
@@ -51,7 +51,7 @@
             sono rilasciate sotto la licenza <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported</a>,
             che è <a href="https://www.gnu.org/licenses/license-list.en.html#ccby">compatibile con la licenza GPLv3+</a>. Le liste sono incluse senza modifiche in Privacy Browser.</p>
 
-        <p>More information about the filter lists can be found on the <a href="https://easylist.to/">EasyList website</a>.</p>
+        <p>E' possibile ottenere maggiori informazioni sulle liste dei filtri sul <a href="https://easylist.to/">sito web di EasyList</a>.</p>
 
         <h3>Librerie</h3>
         <p>Privacy Browser è compilato utilizzando le <a href="https://developer.android.com/jetpack/androidx/">Librerie AndroidX</a>,
index ee239f68d8e9e48be85a10a0dec54f6c615b5111..939809bfe824fbb945b462c088c28989369dc5d1 100644 (file)
@@ -1,7 +1,7 @@
 <!--
   Copyright 2018-2020,2022-2023 Soren Stoutner <soren@stoutner.com>.
 
-  Translation 2018 Francesco Buratti.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
+  Translation 2018,2023 Francesco Buratti.  Copyright assigned to Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
 
         <img class="center" src="images/request_details.png"/>
 
-        <p>Privacy Browser includes four <a href="https://easylist.to/">common filter lists</a> based on the <a href="https://adblockplus.org/filters">Adblock syntax</a>:
-            EasyList, EasyPrivacy, Fanboy’s Annoyance List, and Fanboy’s Social Blocking List.
-            These filter lists are processed by Privacy Browser into the following 22 sublists, which check resource requests in the order listed.</p>
+        <p>Privacy Browser è dotato di quattro <a href="https://easylist.to/">liste di filtri comuni</a> basati sulla <a href="https://adblockplus.org/filters">sintassi Adblock</a>:
+            EasyList, EasyPrivacy, lista Fanboy’s Annoyance, e lista Fanboy’s Social Blocking.
+            Queste liste di filtri sono processate da Privacy Browser nelle seguenti 22 sottoliste, che verificano le richieste di risorse nell'ordine sottostante.</p>
 
         <ol>
-            <li>Main Allow List</li>
-            <li>Final Allow List</li>
-            <li>Domain Allow List</li>
-            <li>Domain Initial Allow List</li>
-            <li>Domain Final Allow List</li>
-            <li>Third-Party Allow List</li>
-            <li>Third-Party Domain Allow List</li>
-            <li>Third-Party Domain Initial Allow List</li>
-            <li>Main Block List</li>
-            <li>Initial Block List</li>
-            <li>Final Block List</li>
-            <li>Domain Block List</li>
-            <li>Domain Initial Block List</li>
-            <li>Domain Final Block List</li>
-            <li>Domain Regular Expression Block List</li>
-            <li>Third-Party Block List</li>
-            <li>Third-Party Initial Block List</li>
-            <li>Third-Party Domain Block List</li>
-            <li>Third-Party Domain Initial Block List</li>
-            <li>Third-Party Regular Expression Block List</li>
-            <li>Third-Party Domain Regular Expression Block List</li>
-            <li>Regular Expression Block List</li>
+            <li>Lista principale dei permessi</li>
+            <li>Lista finale dei permessi</li>
+            <li>Lista dei domini permessi</li>
+            <li>Lista iniziale dei domini permessi</li>
+            <li>Lista finale dei domini permessi</li>
+            <li>Lista di terze parti permesse</li>
+            <li>Lista dei domini di terze parti permessi</li>
+            <li>Lista iniziale dei domini di terze parti permessi</li>
+            <li>Lista principale bloccati</li>
+            <li>Lista iniziale bloccati</li>
+            <li>Lista finale bloccati</li>
+            <li>Lista domini bloccati</li>
+            <li>Lista iniziale domini bloccati</li>
+            <li>Lista finale domini bloccati</li>
+            <li>Lista di blocco espressioni regolari dei domini</li>
+            <li>Lista di blocco terze parti</li>
+            <li>Lista di blocco iniziale terze parti</li>
+            <li>Lista di blocco dei domini di terze parti</li>
+            <li>Lista di blocco iniziale dei domini di terze parti</li>
+            <li>Lista di blocco espressioni regolari di terze parti</li>
+            <li>Lista di blocco espressioni regolari domini di terze parti</li>
+            <li>Lista di blocco espressioni regolari</li>
         </ol>
 
         <p>Le liste iniziali servono per la verifica della parte iniziale delle URL. Le liste iniziali servono per la verifica della parte finale delle URL.
             Ogni oggetto delle liste secondarie ha uno o più elementi.
             Nel caso delle liste secondarie dei domini, la richiesta di risorse è verificata solo se il primo elemento combacia con il dominio della URL principale.</p>
 
-        <p>Because of limitations in Android’s WebView, and to speed up processing of requests, Privacy Browser implements a simplified interpretation of the Adblock syntax.
-            This can sometimes lead to false positives, where resources are allowed or blocked in ways that weren’t intended by the original entry.
-            A more detailed description of how the filter list entries are processed is available at <a href="https://www.stoutner.com/privacy-browser-android/filter-lists/">stoutner.com</a>.</p>
+        <p>A causa delle limitazioni della WebView di Android, e per velocizzare il processo delle richieste, Privacy Browser implementa una interpretazione semplificata della sintassi di Adblock.
+            Queso può a volte portare a falsi positivi, laddove le risorse sono permesse o bloccate in modalità che non sono quelle previste dalla voce originale.
+            Una descrizione più dettagliata di come le liste dei filtri sono processate è disponibile su <a href="https://www.stoutner.com/privacy-browser-android/filter-lists/">stoutner.com</a>.</p>
 
-        <p>Privacy Browser has three additional filter lists.
-            <a href="https://www.stoutner.com/privacy-browser-android/filter-lists/ultralist/">UltraList</a> and
+        <p>Privacy Browser liste di filtri aggiuntive.
+            <a href="https://www.stoutner.com/privacy-browser-android/filter-lists/ultralist/">UltraList</a> e
             <a href="https://www.stoutner.com/privacy-browser-android/filter-lists/ultraprivacy/">UltraPrivacy</a>
-            filters ads and trackers that EasyList and EasyPrivacy do not. The third blocks all third-party requests.
-            A request is only considered third-party if the base domain of the request is different than the base domain of the URL.
-            For example, if <code>www.website.com</code> loads a picture from <code>images.website.com</code>,
-            this is not blocked as a third-party request because they both share the same base domain of <code>website.com</code>.
-            Blocking all third-party requests increases privacy, but this filter list is disabled by default because it breaks a large number of websites.</p>
+            filtrano gli annunci e i tracker che EasyList e EasyPrivacy non filtrano. La terza blocca tutte le richieste di terze parti.
+            Una richiesta è considerata di terza parte solo se il dominio base della richiesta è diverso dal dominio base della URL.
+            Per esempio se <code>www.website.com</code> carica immagini da <code>images.website.com</code>,
+            questo non è bloccato come richiesta di terza parte perchè entrambi condividono lo stesso dominio base <code>website.com</code>.
+            Il blocco di tutte le richieste di terze parti aumenta la privacy, ma questa lista di filtri è per default disabilitata perché impedisce la visualizzazione di un elevato numero di siti web.</p>
     </body>
 </html>
index 8f17569370fe1d00a1df555dfe5061a31f30868c..56ca1ab74c7310fa70ca281cb40783e0e7c88fc9 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>3.14 (código de versão 69)</h3>
-        <p>6 de maio de 2023 - minimum API 24, target API 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (código de versão 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 de maio de 2023</a> - minimum API 24, target API 33</p>
         <ul>
             <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
             <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
index b086d76f8f31b1e524262552711c6a502cb856a4..cc7ecda4b056bacd610e0c934bb479a522f1233f 100644 (file)
     </head>
 
     <body>
-        <h3>3.14 (код версии 69)</h3>
-        <p>6 июня 2023 года - минимальный API 24, целевой API 33</p>
-        <ul>
-            <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
-            <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
-            <li>Standardize the <a href="https://redmine.stoutner.com/issues/951">suggested file names</a>.</li>
-            <li>Update the app bar <a href="https://redmine.stoutner.com/issues/998">proxy background color</a>.</li>
-            <li><a href="https://redmine.stoutner.com/issues/700">Restore the scroll position</a> when restarting the settings app.</li>
-            <li>Migrate the last of the code to <a href="https://redmine.stoutner.com/issues/989">Kotlin</a> and remove the deprecated <a href="https://redmine.stoutner.com/issues/987">AsyncTasks</a>.</li>
-            <li>Optimize <a href="https://redmine.stoutner.com/issues/990">several</a> <a href="https://redmine.stoutner.com/issues/991">pieces</a> of the
-                <a href="https://redmine.stoutner.com/issues/953">code</a> to run more efficiently.</li>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (код версии 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 июня 2023 года</a> - минимальный API 24, целевой API 33</p>
+        <ul>
+            <li>Подсвечивание фона параметров домена, которые не являются настройками <a href="https://redmine.stoutner.com/issues/886">по умолчанию</a>.</li>
+            <li>Из проекта исключены термины <a href="https://redmine.stoutner.com/issues/705"><code>белый список</code> и <code>черный список</code></a>.</li>
+            <li>Стандартизированы <a href="https://redmine.stoutner.com/issues/951">предлагаемые имена файлов</a>.</li>
+            <li>Обновлен цвет фона <a href="https://redmine.stoutner.com/issues/998">панели панели приложений</a>.</li>
+            <li><a href="https://redmine.stoutner.com/issues/700">При перезапуске приложения после смены настроек</a> восстанавливается положение экрана.</li>
+            <li>Выполнена миграция последней части кода на <a href="https://redmine.stoutner.com/issues/989">Kotlin</a> и удаление устаревших
+                <a href="https://redmine.stoutner.com/issues/987">AsyncTasks</a>.</li>
+            <li>Оптимизирован <a href="https://redmine.stoutner.com/issues/990">код</a> <a href="https://redmine.stoutner.com/issues/991">некоторых</a>
+                <a href="https://redmine.stoutner.com/issues/953">фрагментов</a> для более эффективной работы.</li>
         </ul>
 
         <h3><a href="https://www.stoutner.com/privacy-browser-android-3-13-4/">3.13.4</a> (код версии 68)</h3>
index 6285aa3e2c092a3fcfd4e5a88947de2c3e26b44a..95963e0b2ee6d66f07b300c860dcdde176834506 100644 (file)
@@ -27,8 +27,8 @@
     </head>
 
     <body>
-        <h3>3.14 (version code 69)</h3>
-        <p>6 Mayıs 2023 - minimum API 24, target API 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (version code 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 Mayıs 2023</a> - minimum API 24, target API 33</p>
         <ul>
             <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
             <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
index 0d04aba4dcee567bb0ea6ed2634d50a8986cbe90..325a26121ce6aae327467b96ed1961495c1ff9dc 100644 (file)
@@ -29,8 +29,8 @@
     </head>
 
     <body>
-        <h3>3.14 (version code 69)</h3>
-        <p>6 May 2023 - minimum API 24, target API 33</p>
+        <h3><a href="https://www.stoutner.com/privacy-browser-android-3-14/">3.14</a> (version code 69)</h3>
+        <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff;h=6d4644db8bed024d0f4d4cfb7cc8d1dcef3789fe">6 May 2023</a> - minimum API 24, target API 33</p>
         <ul>
             <li>Highlight the background of domain settings that are <a href="https://redmine.stoutner.com/issues/886">not default</a>.</li>
             <li>Remove the terms <a href="https://redmine.stoutner.com/issues/705"><code>whitelist</code> and <code>blacklist</code></a> from the project.</li>
index bd5c34e0caa34a98748c151f1635b4d92f0cdc05..49901e44f19039464bd6d82a97dca655b8fbc7e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -25,12 +25,13 @@ import android.view.WindowManager
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.widget.Toolbar
 import androidx.preference.PreferenceManager
-import androidx.viewpager.widget.ViewPager
+import androidx.viewpager2.widget.ViewPager2
 
 import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayoutMediator
 
 import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.adapters.AboutPagerAdapter
+import com.stoutner.privacybrowser.adapters.AboutStateAdapter
 
 const val FILTERLIST_VERSIONS = "filterlist_versions"
 
@@ -66,7 +67,7 @@ class AboutActivity : AppCompatActivity() {
         // Get handles for the views.
         val toolbar = findViewById<Toolbar>(R.id.about_toolbar)
         val aboutTabLayout = findViewById<TabLayout>(R.id.about_tablayout)
-        val aboutViewPager = findViewById<ViewPager>(R.id.about_viewpager)
+        val aboutViewPager2 = findViewById<ViewPager2>(R.id.about_viewpager2)
 
         // Set the support action bar.
         setSupportActionBar(toolbar)
@@ -77,16 +78,25 @@ class AboutActivity : AppCompatActivity() {
         // Display the home arrow on the action bar.
         actionBar.setDisplayHomeAsUpEnabled(true)
 
-        // Initialize the about pager adapter.
-        val aboutPagerAdapter = AboutPagerAdapter(supportFragmentManager, applicationContext, filterListVersions)
+        // Initialize the about state adapter.
+        val aboutStateAdapter = AboutStateAdapter(this, filterListVersions)
 
         // Set the view pager adapter.
-        aboutViewPager.adapter = aboutPagerAdapter
-
-        // Keep all the tabs in memory.  This prevents the memory usage updater from running multiple times.
-        aboutViewPager.offscreenPageLimit = 10
-
-        // Connect the tab layout to the view pager.
-        aboutTabLayout.setupWithViewPager(aboutViewPager)
+        aboutViewPager2.adapter = aboutStateAdapter
+
+        // Create a tab layout mediator.  Tab numbers start at 0.
+        TabLayoutMediator(aboutTabLayout, aboutViewPager2) { tab, position ->
+            // Set the tab text based on the position.
+            tab.text = when (position) {
+                0 -> getString(R.string.version)
+                1 -> getString(R.string.permissions)
+                2 -> getString(R.string.privacy_policy)
+                3 -> getString(R.string.changelog)
+                4 -> getString(R.string.licenses)
+                5 -> getString(R.string.contributors)
+                6 -> getString(R.string.links)
+                else -> ""
+            }
+        }.attach()
     }
 }
index 2462e28e61f7a62ef06856ce2f548b2143a8976a..e421586b76e12ceb148f03246a2c5df7f7eee27e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2016-2023 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
  *
@@ -25,12 +25,13 @@ import android.view.WindowManager
 import androidx.appcompat.app.AppCompatActivity
 import androidx.appcompat.widget.Toolbar
 import androidx.preference.PreferenceManager
-import androidx.viewpager.widget.ViewPager
+import androidx.viewpager2.widget.ViewPager2
 
 import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayoutMediator
 
 import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.adapters.GuidePagerAdapter
+import com.stoutner.privacybrowser.adapters.GuideStateAdapter
 
 class GuideActivity : AppCompatActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -58,8 +59,8 @@ class GuideActivity : AppCompatActivity() {
 
         // Get handles for the views.
         val toolbar = findViewById<Toolbar>(R.id.guide_toolbar)
-        val guideViewPager = findViewById<ViewPager>(R.id.guide_viewpager)
         val guideTabLayout = findViewById<TabLayout>(R.id.guide_tablayout)
+        val guideViewPager2 = findViewById<ViewPager2>(R.id.guide_viewpager2)
 
         // Set the support action bar.
         setSupportActionBar(toolbar)
@@ -70,16 +71,28 @@ class GuideActivity : AppCompatActivity() {
         // Display the home arrow on the action bar.
         actionBar.setDisplayHomeAsUpEnabled(true)
 
-        // Initialize the guide pager adapter.
-        val guidePagerAdapter = GuidePagerAdapter(supportFragmentManager, applicationContext)
+        // Initialize the guide state adapter.
+        val guideStateAdapter = GuideStateAdapter(this)
 
         // Set the view pager adapter.
-        guideViewPager.adapter = guidePagerAdapter
-
-        // Keep all the tabs in memory.  This prevents the memory usage adapter from running multiple times.
-        guideViewPager.offscreenPageLimit = 10
-
-        // Link the tab layout to the view pager.
-        guideTabLayout.setupWithViewPager(guideViewPager)
+        guideViewPager2.adapter = guideStateAdapter
+
+        // Create a tab layout mediator.  Tab numbers start at 0.
+        TabLayoutMediator(guideTabLayout, guideViewPager2) { tab, position ->
+            // Set the tab text based on the position.
+            tab.text = when (position) {
+                0 -> getString(R.string.overview)
+                1 -> getString(R.string.javascript)
+                2 -> getString(R.string.local_storage)
+                3 -> getString(R.string.user_agent)
+                4 -> getString(R.string.requests)
+                5 -> getString(R.string.domain_settings)
+                6 -> getString(R.string.ssl_certificates)
+                7 -> getString(R.string.proxies)
+                8 -> getString(R.string.tracking_ids)
+                9 -> getString(R.string.gui)
+                else -> ""
+            }
+        }.attach()
     }
 }
index 23436fc104f1939451deba6ae51d936f4dad5eb5..e257118714d0d3dafb41060dc9741617df6b4c3b 100644 (file)
@@ -105,7 +105,7 @@ import androidx.drawerlayout.widget.DrawerLayout
 import androidx.fragment.app.DialogFragment
 import androidx.preference.PreferenceManager
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-import androidx.viewpager.widget.ViewPager
+import androidx.viewpager2.widget.ViewPager2
 import androidx.webkit.WebSettingsCompat
 import androidx.webkit.WebViewFeature
 
@@ -116,7 +116,7 @@ import com.google.android.material.snackbar.Snackbar
 import com.google.android.material.tabs.TabLayout
 
 import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.adapters.WebViewPagerAdapter
+import com.stoutner.privacybrowser.adapters.WebViewStateAdapter
 import com.stoutner.privacybrowser.coroutines.GetHostIpAddressesCoroutine
 import com.stoutner.privacybrowser.coroutines.PopulateFilterListsCoroutine
 import com.stoutner.privacybrowser.coroutines.PrepareSaveDialogCoroutine
@@ -211,7 +211,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val pendingDialogsArrayList = ArrayList<PendingDialogDataClass>()
         var proxyMode = ProxyHelper.NONE
         var restartFromBookmarksActivity = false
-        var webViewPagerAdapter: WebViewPagerAdapter? = null
+        var webViewStateAdapter: WebViewStateAdapter? = null
 
         // Declare the public static variables.
         lateinit var appBarLayout: AppBarLayout
@@ -296,7 +296,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
     private lateinit var tabsLinearLayout: LinearLayout
     private lateinit var toolbar: Toolbar
     private lateinit var webViewDefaultUserAgent: String
-    private lateinit var webViewPager: ViewPager
+    private lateinit var webViewViewPager2: ViewPager2
     private lateinit var ultraList: ArrayList<List<Array<String>>>
     private lateinit var urlEditText: EditText
     private lateinit var urlRelativeLayout: RelativeLayout
@@ -532,7 +532,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             tabsLinearLayout = findViewById(R.id.tabs_linearlayout)
             tabLayout = findViewById(R.id.tablayout)
             swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
-            webViewPager = findViewById(R.id.webviewpager)
+            webViewViewPager2 = findViewById(R.id.webview_viewpager2)
             val navigationView = findViewById<NavigationView>(R.id.navigationview)
             bookmarksListView = findViewById(R.id.bookmarks_drawer_listview)
             bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview)
@@ -576,14 +576,17 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Initially hide the user interface so that only the filter list loading screen is shown (if reloading).
             drawerLayout.visibility = View.GONE
 
-            // Initialize the WebView pager adapter.
-            webViewPagerAdapter = WebViewPagerAdapter(supportFragmentManager)
+            // Initialize the WebView state adapter.
+            webViewStateAdapter = WebViewStateAdapter(this)
 
             // Set the pager adapter on the web view pager.
-            webViewPager.adapter = webViewPagerAdapter
+            webViewViewPager2.adapter = webViewStateAdapter
 
             // Store up to 100 tabs in memory.
-            webViewPager.offscreenPageLimit = 100
+            webViewViewPager2.offscreenPageLimit = 100
+
+            // Disable swiping between pages in the view pager.
+            webViewViewPager2.isUserInputEnabled = false
 
             // Get a handle for the cookie manager.
             cookieManager = CookieManager.getInstance()
@@ -748,9 +751,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             updateDomainsSettingsSet()
 
             // Reapply the domain settings for each tab.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -791,11 +794,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Run the default commands.
         super.onStart()
 
-        // Resume any WebViews if the pager adapter exists.  If the app is restarting to change the initial app theme it won't have been populated yet.
-        if (webViewPagerAdapter != null) {
-            for (i in 0 until webViewPagerAdapter!!.count) {
+        // Resume any WebViews if the state adapter exists.  If the app is restarting to change the initial app theme it won't have been populated yet.
+        if (webViewStateAdapter != null) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -850,16 +853,16 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Run the default commands.
         super.onSaveInstanceState(savedInstanceState)
 
-        // Only save the instance state if the WebView pager adapter is not null, which will be the case if the app is restarting to change the initial app theme.
-        if (webViewPagerAdapter != null) {
+        // Only save the instance state if the WebView state adapter is not null, which will be the case if the app is restarting to change the initial app theme.
+        if (webViewStateAdapter != null) {
             // Initialize the saved state array lists.
             savedStateArrayList = ArrayList<Bundle>()
             savedNestedScrollWebViewStateArrayList = ArrayList<Bundle>()
 
             // Get the URLs from each tab.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -899,12 +902,12 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Run the default commands.
         super.onStop()
 
-        // Only pause the WebViews if the pager adapter is not null, which is the case if the app is restarting to change the initial app theme.
-        if (webViewPagerAdapter != null) {
+        // Only pause the WebViews if the state adapter is not null, which is the case if the app is restarting to change the initial app theme.
+        if (webViewStateAdapter != null) {
             // Pause each web view.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -1298,11 +1301,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                 // Display a snackbar.
                 if (currentWebView!!.settings.javaScriptEnabled)  // JavaScrip is enabled.
-                    Snackbar.make(webViewPager, R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show()
                 else if (cookieManager.acceptCookie())  // JavaScript is disabled, but cookies are enabled.
-                    Snackbar.make(webViewPager, R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show()
                 else  // Privacy mode.
-                    Snackbar.make(webViewPager, R.string.privacy_mode, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.privacy_mode, Snackbar.LENGTH_SHORT).show()
 
                 // Reload the current WebView.
                 currentWebView!!.reload()
@@ -1345,11 +1348,11 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                 // Display a snackbar.
                 if (cookieManager.acceptCookie())  // Cookies are enabled.
-                    Snackbar.make(webViewPager, R.string.cookies_enabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.cookies_enabled, Snackbar.LENGTH_SHORT).show()
                 else if (currentWebView!!.settings.javaScriptEnabled)  // JavaScript is still enabled.
-                    Snackbar.make(webViewPager, R.string.cookies_disabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.cookies_disabled, Snackbar.LENGTH_SHORT).show()
                 else  // Privacy mode.
-                    Snackbar.make(webViewPager, R.string.privacy_mode, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.privacy_mode, Snackbar.LENGTH_SHORT).show()
 
                 // Reload the current WebView.
                 currentWebView!!.reload()
@@ -1370,9 +1373,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
                 // Display a snackbar.
                 if (currentWebView!!.settings.domStorageEnabled)
-                    Snackbar.make(webViewPager, R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show()
                 else
-                    Snackbar.make(webViewPager, R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show()
 
                 // Reload the current WebView.
                 currentWebView!!.reload()
@@ -1393,9 +1396,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Display a snackbar.
                 @Suppress("DEPRECATION")
                 if (currentWebView!!.settings.saveFormData)
-                    Snackbar.make(webViewPager, R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show()
                 else
-                    Snackbar.make(webViewPager, R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show()
+                    Snackbar.make(webViewViewPager2, R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show()
 
                 // Update the privacy icon.
                 updatePrivacyIcons(true)
@@ -1409,7 +1412,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             R.id.clear_cookies -> {  // Clear cookies.
                 // Create a snackbar.
-                Snackbar.make(webViewPager, R.string.cookies_deleted, Snackbar.LENGTH_LONG)
+                Snackbar.make(webViewViewPager2, R.string.cookies_deleted, Snackbar.LENGTH_LONG)
                     .setAction(R.string.undo) {}  // Everything will be handled by `onDismissed()` below.
                     .addCallback(object : Snackbar.Callback() {
                         override fun onDismissed(snackbar: Snackbar, event: Int) {
@@ -1427,7 +1430,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             R.id.clear_dom_storage -> {  // Clear DOM storage.
                 // Create a snackbar.
-                Snackbar.make(webViewPager, R.string.dom_storage_deleted, Snackbar.LENGTH_LONG)
+                Snackbar.make(webViewViewPager2, R.string.dom_storage_deleted, Snackbar.LENGTH_LONG)
                     .setAction(R.string.undo) {}  // Everything will be handled by `onDismissed()` below.
                     .addCallback(object : Snackbar.Callback() {
                         override fun onDismissed(snackbar: Snackbar, event: Int) {
@@ -1484,7 +1487,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             R.id.clear_form_data -> {  // Clear form data.  This can be remove once the minimum API >= 26.
                 // Create a snackbar.
-                Snackbar.make(webViewPager, R.string.form_data_deleted, Snackbar.LENGTH_LONG)
+                Snackbar.make(webViewViewPager2, R.string.form_data_deleted, Snackbar.LENGTH_LONG)
                     .setAction(R.string.undo) {}  // Everything will be handled by `onDismissed()` below.
                     .addCallback(object : Snackbar.Callback() {
                         override fun onDismissed(snackbar: Snackbar, event: Int) {
@@ -2691,7 +2694,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         newTab.setCustomView(R.layout.tab_custom_view)
 
         // Add the new WebView page.
-        webViewPagerAdapter!!.addPage(newTabNumber, webViewPager, urlString, moveToTab)
+        webViewStateAdapter!!.addPage(newTabNumber, webViewViewPager2, urlString, moveToTab)
 
         // Show the app bar if it is at the bottom of the screen and the new tab is taking focus.
         if (bottomAppBar && moveToTab && appBarLayout.translationY != 0f) {
@@ -2780,9 +2783,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             }
 
             // Set the app bar scrolling for each WebView.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -2875,7 +2878,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 nestedScrollWebView.initializeFavoriteIcon()
 
                 // Get the current page position.
-                val currentPagePosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                 // Get the corresponding tab.
                 val tab = tabLayout.getTabAt(currentPagePosition)
@@ -3361,9 +3364,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Reload the WebViews if requested and not waiting for the proxy.
         if (reloadWebViews && !waitingForProxy) {
             // Reload the WebViews.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the fragment view.
                 val fragmentView = webViewTabFragment.view
@@ -3499,9 +3502,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Clear the cache.
         if (clearEverything || sharedPreferences.getBoolean(getString(R.string.clear_cache_key), true)) {
             // Clear the cache from each WebView.
-            for (i in 0 until webViewPagerAdapter!!.count) {
+            for (i in 0 until webViewStateAdapter!!.itemCount) {
                 // Get the WebView tab fragment.
-                val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                 // Get the WebView fragment view.
                 val webViewFragmentView = webViewTabFragment.view
@@ -3534,9 +3537,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         }
 
         // Wipe out each WebView.
-        for (i in 0 until webViewPagerAdapter!!.count) {
+        for (i in 0 until webViewStateAdapter!!.itemCount) {
             // Get the WebView tab fragment.
-            val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+            val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
             // Get the WebView frame layout.
             val webViewFrameLayout = webViewTabFragment.view as FrameLayout?
@@ -3614,7 +3617,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
 
             // Delete the current page.  If the selected page number did not change during the delete (because the newly selected tab has has same number as the previously deleted tab), it will return true,
             // meaning that the current WebView must be reset.  Otherwise it will happen automatically as the selected tab number changes.
-            if (webViewPagerAdapter!!.deletePage(currentTabNumber, webViewPager))
+            if (webViewStateAdapter!!.deletePage(currentTabNumber, webViewViewPager2))
                 setCurrentWebView(currentTabNumber)
         } else {  // There is only one tab open.
             clearAndExit()
@@ -3801,7 +3804,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         // Check to see if the activity has been restarted with a saved state.
         if ((savedStateArrayList == null) || (savedStateArrayList!!.size == 0)) {  // The activity has not been restarted or it was restarted on start to change the theme.
             // Add the first tab.
-            addNewTab("", true)
+            addNewTab("", false)
         } else {  // The activity has been restarted.
             // Restore each tab.
             for (i in savedStateArrayList!!.indices) {
@@ -3815,7 +3818,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 newTab.setCustomView(R.layout.tab_custom_view)
 
                 // Add the new page.
-                webViewPagerAdapter!!.restorePage(savedStateArrayList!![i], savedNestedScrollWebViewStateArrayList!![i])
+                webViewStateAdapter!!.restorePage(savedStateArrayList!![i], savedNestedScrollWebViewStateArrayList!![i])
             }
 
             // Reset the saved state variables.
@@ -3828,7 +3831,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 setCurrentWebView(0)
             } else {  // The first tab is not selected.
                 // Move to the selected tab.
-                webViewPager.currentItem = savedTabPosition
+                webViewViewPager2.currentItem = savedTabPosition
             }
 
             // Get the intent that started the app.
@@ -3947,9 +3950,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     }
 
                     // Reload existing URLs and load any URLs that are waiting for the proxy.
-                    for (i in 0 until webViewPagerAdapter!!.count) {
+                    for (i in 0 until webViewStateAdapter!!.itemCount) {
                         // Get the WebView tab fragment.
-                        val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(i)
+                        val webViewTabFragment = webViewStateAdapter!!.getPageFragment(i)
 
                         // Get the fragment view.
                         val fragmentView = webViewTabFragment.view
@@ -3989,9 +3992,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         val createBookmarkFab = findViewById<FloatingActionButton>(R.id.create_bookmark_fab)
 
         // Update the WebView pager every time a tab is modified.
-        webViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
-            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
-
+        webViewViewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
             override fun onPageSelected(position: Int) {
                 // Close the find on page bar if it is open.
                 closeFindOnPage(null)
@@ -4011,15 +4012,13 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     }
                 }
             }
-
-            override fun onPageScrollStateChanged(state: Int) {}
         })
 
         // Handle tab selections.
         tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
             override fun onTabSelected(tab: TabLayout.Tab) {
                 // Select the same page in the view pager.
-                webViewPager.currentItem = tab.position
+                webViewViewPager2.currentItem = tab.position
             }
 
             override fun onTabUnselected(tab: TabLayout.Tab) {}
@@ -4593,7 +4592,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                     nestedScrollWebView.setFavoriteIcon(icon)
 
                     // Get the current page position.
-                    val currentPosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                    val currentPosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                     // Get the current tab.
                     val tab = tabLayout.getTabAt(currentPosition)
@@ -4618,7 +4617,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
             // Save a copy of the title when it changes.
             override fun onReceivedTitle(view: WebView, title: String) {
                 // Get the current page position.
-                val currentPosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                val currentPosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                 // Get the current tab.
                 val tab = tabLayout.getTabAt(currentPosition)
@@ -4855,10 +4854,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 }
 
                 // Get the current WebView page position.
-                val webViewPagePosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                val webViewPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                 // Determine if the WebView is currently displayed.
-                val webViewDisplayed = webViewPagePosition == tabLayout.selectedTabPosition
+                val webViewDisplayed = (webViewPagePosition == tabLayout.selectedTabPosition)
 
                 // Block third-party requests if enabled.
                 if (isThirdPartyRequest && nestedScrollWebView.blockAllThirdPartyRequests) {
@@ -5184,7 +5183,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 nestedScrollWebView.resetRequestsCounters()
 
                 // Get the current page position.
-                val currentPagePosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                 // Update the URL text bar if the page is currently selected and the URL edit text is not currently being edited.
                 if ((tabLayout.selectedTabPosition == currentPagePosition) && !urlEditText.hasFocus()) {
@@ -5208,7 +5207,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 val currentDomainName = currentUri.host
 
                 // Get the IP addresses for the current domain.
-                if ((currentDomainName != null) && currentDomainName.isNotEmpty())
+                if (!currentDomainName.isNullOrEmpty())
                     GetHostIpAddressesCoroutine.checkPinnedMismatch(currentDomainName, nestedScrollWebView, supportFragmentManager, getString(R.string.pinned_mismatch))
 
                 // Replace Refresh with Stop if the options menu has been created and the WebView is currently displayed.  (The first WebView typically begins loading before the menu items are instantiated.)
@@ -5275,7 +5274,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 }
 
                 // Get the current page position.
-                val currentPagePosition = webViewPagerAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
+                val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
 
                 // Get the current URL from the nested scroll WebView.  This is more accurate than using the URL passed into the method, which is sometimes not the final one.
                 val currentUrl = nestedScrollWebView.url
@@ -5748,7 +5747,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
         swipeRefreshLayout.isRefreshing = false
 
         // Get the WebView tab fragment.
-        val webViewTabFragment = webViewPagerAdapter!!.getPageFragment(pageNumber)
+        val webViewTabFragment = webViewStateAdapter!!.getPageFragment(pageNumber)
 
         // Get the fragment view.
         val webViewFragmentView = webViewTabFragment.view
@@ -5816,7 +5815,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook
                 // Remove any background on the URL relative layout.
                 urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.color.transparent)
             }
-        } else if (pageNumber == savedTabPosition) {  // The app is being restored but the saved tab position fragment has not been populated yet.  Try again in 100 milliseconds.
+        } else if ((pageNumber == savedTabPosition) || (pageNumber == (webViewStateAdapter!!.itemCount - 1))) {  // The tab has not been populated yet.
+            //  Try again in 100 milliseconds if the app is being restored or the a new tab has been added (the last tab).
             // Create a handler to set the current WebView.
             val setCurrentWebViewHandler = Handler(Looper.getMainLooper())
 
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/AboutPagerAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/AboutPagerAdapter.kt
deleted file mode 100644 (file)
index e893c70..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright © 2016-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.content.Context
-
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.FragmentPagerAdapter
-
-import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.fragments.AboutVersionFragment
-import com.stoutner.privacybrowser.fragments.AboutWebViewFragment
-
-import java.util.LinkedList
-
-class AboutPagerAdapter(fragmentManager: FragmentManager, private val context: Context, private val filterListVersions: Array<String>) :
-    FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
-
-    // Define the class variables.
-    private val aboutFragmentList = LinkedList<Fragment>()
-
-    // Get the number of tabs.
-    override fun getCount(): Int {
-        // There are seven tabs.
-        return 7
-    }
-
-    // Setup each tab.
-    override fun getItem(tabNumber: Int): Fragment {
-        // Create the tab fragment and add it to the list.
-        if (tabNumber == 0) {
-            // Add the version tab to the list.
-            aboutFragmentList.add(AboutVersionFragment.createTab(filterListVersions))
-        } else {
-            // Add the WebView tab to the list.
-            aboutFragmentList.add(AboutWebViewFragment.createTab(tabNumber))
-        }
-
-        // Return the tab fragment.
-        return aboutFragmentList[tabNumber]
-    }
-
-    // Get the name of each tab.  Tab numbers start at 0.
-    override fun getPageTitle(tab: Int): CharSequence {
-        return when (tab) {
-            0 -> context.getString(R.string.version)
-            1 -> context.getString(R.string.permissions)
-            2 -> context.getString(R.string.privacy_policy)
-            3 -> context.getString(R.string.changelog)
-            4 -> context.getString(R.string.licenses)
-            5 -> context.getString(R.string.contributors)
-            6 -> context.getString(R.string.links)
-            else -> ""
-        }
-    }
-}
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/AboutStateAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/AboutStateAdapter.kt
new file mode 100644 (file)
index 0000000..9e110a5
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2016-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 androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+import com.stoutner.privacybrowser.fragments.AboutVersionFragment
+import com.stoutner.privacybrowser.fragments.AboutWebViewFragment
+
+class AboutStateAdapter(fragmentActivity: FragmentActivity, private val filterListVersions: Array<String>) : FragmentStateAdapter(fragmentActivity) {
+    // Get the number of tabs.
+    override fun getItemCount(): Int {
+        // There are seven tabs.
+        return 7
+    }
+
+    // Create the tab.
+    override fun createFragment(tabNumber: Int): Fragment {
+        // Return the tab fragment.
+        return if (tabNumber == 0)  // Return the about tab fragment.
+            AboutVersionFragment.createTab(filterListVersions)
+        else  // Return a WebView tab.
+            AboutWebViewFragment.createTab(tabNumber)
+    }
+}
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/GuidePagerAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/GuidePagerAdapter.kt
deleted file mode 100644 (file)
index cd74689..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2016-2020,2022-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.content.Context
-
-import androidx.fragment.app.Fragment
-import androidx.fragment.app.FragmentManager
-import androidx.fragment.app.FragmentPagerAdapter
-
-import com.stoutner.privacybrowser.R
-import com.stoutner.privacybrowser.fragments.GuideWebViewFragment
-
-class GuidePagerAdapter(fragmentManager: FragmentManager, private val context: Context) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
-    // Get the count of the number of tabs.
-    override fun getCount(): Int {
-        return 10
-    }
-
-    // Setup each tab.
-    override fun getItem(tabNumber: Int): Fragment {
-        return GuideWebViewFragment.createTab(tabNumber)
-    }
-
-    // Get the name of each tab.  Tab numbers start at 0.
-    override fun getPageTitle(tab: Int): CharSequence {
-        return when (tab) {
-            0 -> context.getString(R.string.overview)
-            1 -> context.getString(R.string.javascript)
-            2 -> context.getString(R.string.local_storage)
-            3 -> context.getString(R.string.user_agent)
-            4 -> context.getString(R.string.requests)
-            5 -> context.getString(R.string.domain_settings)
-            6 -> context.getString(R.string.ssl_certificates)
-            7 -> context.getString(R.string.proxies)
-            8 -> context.getString(R.string.tracking_ids)
-            9 -> context.getString(R.string.gui)
-            else -> ""
-        }
-    }
-}
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/GuideStateAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/GuideStateAdapter.kt
new file mode 100644 (file)
index 0000000..50a1162
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016-2020,2022-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 androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+import com.stoutner.privacybrowser.fragments.GuideWebViewFragment
+
+class GuideStateAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
+    // Get the number of tabs.
+    override fun getItemCount(): Int {
+        // There are 10 tabs.
+        return 10
+    }
+
+    // Create the tab.
+    override fun createFragment(tabNumber: Int): Fragment {
+        // Return the tab fragment.
+        return GuideWebViewFragment.createTab(tabNumber)
+    }
+}
index 6c9ea8bbc11fb1253eefaa7441ec6de5efd29de3..9a0d10907f9ade83780834bae5620d3c5616bc8a 100644 (file)
@@ -63,10 +63,10 @@ class PinnedMismatchPagerAdapter(private val context: Context, private val layou
     // Setup each tab.
     override fun instantiateItem(container: ViewGroup, tabNumber: Int): Any {
         // Get the current position of this WebView fragment.
-        val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(webViewFragmentId)
+        val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
 
         // Get the WebView tab fragment.
-        val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+        val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
         // Get the WebView fragment view.
         val webViewFragmentView = webViewTabFragment.requireView()
@@ -271,4 +271,4 @@ class PinnedMismatchPagerAdapter(private val context: Context, private val layou
         // Return the tab layout.
         return tabLayout
     }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewPagerAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewPagerAdapter.kt
deleted file mode 100644 (file)
index 6aef0cd..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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)
-        }
-    }
-}
diff --git a/app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewStateAdapter.kt b/app/src/main/java/com/stoutner/privacybrowser/adapters/WebViewStateAdapter.kt
new file mode 100644 (file)
index 0000000..0d0fdef
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * 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.widget.FrameLayout
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.recyclerview.widget.RecyclerView.NO_ID
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import androidx.viewpager2.widget.ViewPager2
+
+import com.stoutner.privacybrowser.R
+import com.stoutner.privacybrowser.fragments.WebViewTabFragment
+import com.stoutner.privacybrowser.views.NestedScrollWebView
+
+import java.util.LinkedList
+
+class WebViewStateAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
+    // Define the class variables.
+    private val webViewFragmentsList = LinkedList<WebViewTabFragment>()
+
+    // Get a page fragment.
+    override fun createFragment(pageNumber: Int): Fragment {
+        // Get the fragment for a particular page.  Page numbers are 0 indexed.
+        return webViewFragmentsList[pageNumber]
+    }
+
+    override fun containsItem(itemId: Long): Boolean {
+        // 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 == itemId) {
+                // Store the position if they are a match.
+                position = i
+            }
+
+            // Increment the counter.
+            i++
+        }
+
+        // Return true if the item was found in the WebView fragments list.
+        return (position != -1)
+    }
+
+    // Get the number of tabs.
+    override fun getItemCount(): Int {
+        // Return the number of pages.
+        return webViewFragmentsList.size
+    }
+
+    // Get the unique ID for the item.
+    override fun getItemId(position: Int): Long {
+        // Return the unique ID for this page.
+        return if ((position >= 0) && (position < webViewFragmentsList.size))  // The position is 0 based, so it is contained in the WebView fragment list.
+            webViewFragmentsList[position].fragmentId
+        else  // The item does not exist.
+            NO_ID
+    }
+
+    fun addPage(pageNumber: Int, webViewViewPager2: ViewPager2, url: String, moveToNewPage: Boolean) {
+        // Add a new page.
+        webViewFragmentsList.add(WebViewTabFragment.createPage(pageNumber, url))
+
+        // Update the view pager.
+        notifyItemInserted(pageNumber)
+
+        // Move to the new page if indicated.
+        if (moveToNewPage)
+            webViewViewPager2.currentItem = pageNumber
+    }
+
+    fun deletePage(pageNumber: Int, webViewPager2: ViewPager2): 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.
+        notifyItemRemoved(pageNumber)
+
+        // 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 (webViewPager2.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, which is one less than the size because it is zero based.
+        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.  The position is zero indexed.
+        notifyItemInserted(webViewFragmentsList.size - 1)
+    }
+}
index c6fd36a284478ff7e6bdfcd38e0267829572257e..d2765814b7b210291addee03dd37a5ba5fbce54e 100644 (file)
@@ -27,11 +27,12 @@ import android.provider.OpenableColumns
 import android.util.Base64
 import android.webkit.CookieManager
 
+import androidx.viewpager2.widget.ViewPager2
+
 import com.google.android.material.snackbar.Snackbar
 
 import com.stoutner.privacybrowser.R
 import com.stoutner.privacybrowser.helpers.ProxyHelper
-import com.stoutner.privacybrowser.views.NoSwipeViewPager
 
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -70,10 +71,10 @@ class SaveUrlCoroutine {
             }
 
             // Get a handle for the no swipe view pager.
-            val noSwipeViewPager = activity.findViewById<NoSwipeViewPager>(R.id.webviewpager)
+            val webViewViewPager2 = activity.findViewById<ViewPager2>(R.id.webview_viewpager2)
 
             // Create a saving file snackbar.
-            val savingFileSnackbar = Snackbar.make(noSwipeViewPager, activity.getString(R.string.saving_file, 0, fileNameString), Snackbar.LENGTH_INDEFINITE)
+            val savingFileSnackbar = Snackbar.make(webViewViewPager2, activity.getString(R.string.saving_file, 0, fileNameString), Snackbar.LENGTH_INDEFINITE)
 
             // Display the saving file snackbar.
             savingFileSnackbar.show()
@@ -204,7 +205,7 @@ class SaveUrlCoroutine {
                         savingFileSnackbar.dismiss()
 
                         // Display the file saved snackbar.
-                        Snackbar.make(noSwipeViewPager, activity.getString(R.string.saved, fileNameString), Snackbar.LENGTH_LONG).show()
+                        Snackbar.make(webViewViewPager2, activity.getString(R.string.saved, fileNameString), Snackbar.LENGTH_LONG).show()
                     }
                 } catch (exception: Exception) {
                     // Update the UI.
@@ -213,7 +214,7 @@ class SaveUrlCoroutine {
                         savingFileSnackbar.dismiss()
 
                         // Display the file saving error.
-                        Snackbar.make(noSwipeViewPager, activity.getString(R.string.error_saving_file, fileNameString, exception), Snackbar.LENGTH_INDEFINITE).show()
+                        Snackbar.make(webViewViewPager2, activity.getString(R.string.error_saving_file, fileNameString, exception), Snackbar.LENGTH_INDEFINITE).show()
                     }
                 }
             }
index 07a3f0b6dbdf1b3d510f3868b4d8b8159c199200..b2c749bdeea2c9071657b877636770e835366bab 100644 (file)
@@ -86,10 +86,10 @@ class HttpAuthenticationDialog : DialogFragment() {
         // Try to populate the alert dialog.
         try {  // Getting the WebView tab fragment will fail if Privacy Browser has been restarted.
             // Get the current position of this WebView fragment.
-            val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(webViewFragmentId)
+            val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
 
             // Get the WebView tab fragment.
-            val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+            val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
             // Get the fragment view.
             val fragmentView = webViewTabFragment.requireView()
index 66b08bbbd13937f10c32c9983402f1538be88a31..1a0ad7e3b03155e35364cb88862285c34da6bf4f 100644 (file)
@@ -85,10 +85,10 @@ class PinnedMismatchDialog : DialogFragment() {
         val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
 
         // Get the current position of this WebView fragment.
-        val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(webViewFragmentId)
+        val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
 
         // Get the WebView tab fragment.
-        val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+        val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
         // Get the fragment view.
         val fragmentView = webViewTabFragment.requireView()
index 9a81641f8b8c24a155c930f9328b780ad741447e..aa0ae90856ef798a1eb75f9a0c411f6eacff2ca4 100644 (file)
@@ -112,10 +112,10 @@ class SslCertificateErrorDialog : DialogFragment() {
         val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
 
         // Get the current position of this WebView fragment.
-        val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(webViewFragmentId)
+        val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
 
         // Get the WebView tab fragment.
-        val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+        val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
         // Get the fragment view.
         val fragmentView = webViewTabFragment.requireView()
index 81c06e951f1a11133f3b7c529cb5b0a695567c97..008abef74fd4d8de073c6c8125d8befc7f22d4be 100644 (file)
@@ -86,10 +86,10 @@ class UrlHistoryDialog : DialogFragment() {
         val webViewFragmentId = requireArguments().getLong(WEBVIEW_FRAGMENT_ID)
 
         // Get the current position of this WebView fragment.
-        val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(webViewFragmentId)
+        val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(webViewFragmentId)
 
         // Get the WebView tab fragment.
-        val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+        val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
         // Get the fragment view.
         val fragmentView = webViewTabFragment.requireView()
index 3d572b5db42a2e3ad2e0d4112d19ef7ecfcf8177..98ad3fa56d959972164618485c2ee6d12991d4f9 100644 (file)
@@ -113,10 +113,10 @@ class ViewSslCertificateDialog : DialogFragment() {
         // Populate the class variables.
         if (savedInstanceState == null) {  // The dialog is starting for the first time.
             // Get the current position of this WebView fragment.
-            val webViewPosition = MainWebViewActivity.webViewPagerAdapter!!.getPositionForId(requireArguments().getLong(WEBVIEW_FRAGMENT_ID))
+            val webViewPosition = MainWebViewActivity.webViewStateAdapter!!.getPositionForId(requireArguments().getLong(WEBVIEW_FRAGMENT_ID))
 
             // Get the WebView tab fragment.
-            val webViewTabFragment = MainWebViewActivity.webViewPagerAdapter!!.getPageFragment(webViewPosition)
+            val webViewTabFragment = MainWebViewActivity.webViewStateAdapter!!.getPageFragment(webViewPosition)
 
             // Get the fragment view.
             val fragmentView = webViewTabFragment.requireView()
diff --git a/app/src/main/java/com/stoutner/privacybrowser/views/NoSwipeViewPager.kt b/app/src/main/java/com/stoutner/privacybrowser/views/NoSwipeViewPager.kt
deleted file mode 100644 (file)
index 9bd6028..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2019,2021-2022 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.views
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.MotionEvent
-
-import androidx.viewpager.widget.ViewPager
-
-class NoSwipeViewPager @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null) : ViewPager(context, attributeSet) {
-    // It is necessary to override `performClick()` when overriding `onTouchEvent()`
-    override fun performClick(): Boolean {
-        // Run the default commands.
-        super.performClick()
-
-        // Do not consume the events.
-        return false
-    }
-
-    override fun onTouchEvent(event: MotionEvent): Boolean {
-        // `onTouchEvent()` requires calling `performClick()`.
-        performClick()
-
-        // Do not allow swiping.
-        return false
-    }
-
-    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
-        // Do not allow swiping.
-        return false
-    }
-}
\ No newline at end of file
index 2a5eb5a758fe8a3ff2d6f95191760f04c2787c88..c231b07845c24162b35c823b23e07193e14c0cf5 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2016-2017,2019-2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2016-2017,2019-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
@@ -34,8 +34,8 @@
         app:layout_dodgeInsetEdges="bottom" >
 
         <!-- `android:layout_weight="1"` makes the view pager fill the rest of the screen. -->
-        <androidx.viewpager.widget.ViewPager
-            android:id="@+id/about_viewpager"
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/about_viewpager2"
             android:layout_height="0dp"
             android:layout_width="match_parent"
             android:layout_weight="1" />
index 97650b81354c60a556fef3b41149ef66d6170c87..47144216b24d1a107079f5b4f8b29d43f33af7f8 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2016-2017,2019-2020,2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2016-2017,2019-2020,2022-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
@@ -52,8 +52,8 @@
         </com.google.android.material.appbar.AppBarLayout>
 
         <!-- `android:layout_weight="1"` makes the view pager fill the rest of the screen. -->
-        <androidx.viewpager.widget.ViewPager
-            android:id="@+id/about_viewpager"
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/about_viewpager2"
             android:layout_height="0dp"
             android:layout_width="match_parent"
             android:layout_weight="1" />
index 665ff3ea9cf58facea566864241490b4aac57f02..3a6a41304c06c8aba86926e044a60e63d6e9d838 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2016-2017,2019-2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2016-2017,2019-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
@@ -34,8 +34,8 @@
         app:layout_dodgeInsetEdges="bottom" >
 
         <!-- `android:layout_weight="1"` makes the view pager fill the rest of the screen. -->
-        <androidx.viewpager.widget.ViewPager
-            android:id="@+id/guide_viewpager"
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/guide_viewpager2"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1" />
index 05f6bbc2f17760c788f8f9da3236e09a39e11995..f3a3d1ef023ce35805b899553c9dd9cd5129d48c 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2016-2017,2019-2022 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2016-2017,2019-2023 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
 
@@ -52,8 +52,8 @@
         </com.google.android.material.appbar.AppBarLayout>
 
         <!-- `android:layout_weight="1"` makes the view pager fill the rest of the screen. -->
-        <androidx.viewpager.widget.ViewPager
-            android:id="@+id/guide_viewpager"
+        <androidx.viewpager2.widget.ViewPager2
+            android:id="@+id/guide_viewpager2"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:layout_weight="1" />
index edbe9cf1ed4f8c963a4a32f69b7abfb0a88a4467..b4a845fa536478c528772287ec74ef86aa1ceb3e 100644 (file)
@@ -44,8 +44,8 @@
                     android:layout_width="match_parent"
                     android:layout_height="match_parent" >
 
-                    <com.stoutner.privacybrowser.views.NoSwipeViewPager
-                        android:id="@+id/webviewpager"
+                    <androidx.viewpager2.widget.ViewPager2
+                        android:id="@+id/webview_viewpager2"
                         android:layout_height="match_parent"
                         android:layout_width="match_parent" />
                 </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
index ec3aa96bf7273bdf706d902fb5a8740166f43fdc..12258ec17364067a6243369148efcf2eb3581740 100644 (file)
                 android:layout_height="match_parent"
                 app:layout_behavior="@string/appbar_scrolling_view_behavior" >
 
-                    <com.stoutner.privacybrowser.views.NoSwipeViewPager
-                        android:id="@+id/webviewpager"
+                    <androidx.viewpager2.widget.ViewPager2
+                        android:id="@+id/webview_viewpager2"
                         android:layout_height="match_parent"
                         android:layout_width="match_parent" />
             </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
index c6d1976f203086eb39bd4bd3eaf812b1cbf7ceec..31919afbc459e3181ebc684bfdead709ae1e713b 100644 (file)
         <string name="blocked">Bloccata</string>
         <string name="request_blocked">%1$d. Bloccata</string>
         <string name="blocked_plural">Bloccate</string>
+    <string name="filterlist">Lista dei Filtri</string>
     <string name="sublist">Sublist</string>
+        <string name="main_allowlist">Lista principale dei permessi</string>
+        <string name="final_allowlist">Lista finale dei permessi</string>
+        <string name="domain_allowlist">Lista domini permessi</string>
+        <string name="domain_initial_allowlist">Lista iniziale domini permessi</string>
+        <string name="domain_final_allowlist">Lista finale domini permessi</string>
+        <string name="third_party_allowlist">Lista di terze parti permesse</string>
+        <string name="third_party_domain_allowlist">Lista domini di terze parti permessi</string>
+        <string name="third_party_domain_initial_allowlist">Lista iniziale domini di terze parti permessi</string>
+        <string name="main_blocklist">Lista principale bloccati</string>
+        <string name="initial_blocklist">Lista iniziale bloccati</string>
+        <string name="final_blocklist">Lista finale bloccati</string>
+        <string name="domain_blocklist">Lista domini bloccati</string>
+        <string name="domain_initial_blocklist">Lista iniziale domini bloccati</string>
+        <string name="domain_final_blocklist">Lista finale domini bloccati</string>
+        <string name="domain_regular_expression_blocklist">Lista di blocco espressioni regolari nei domini</string>
+        <string name="third_party_blocklist">Lista di terze parti bloccate</string>
+        <string name="third_party_initial_blocklist">Lista iniziale di terze parti bloccate</string>
+        <string name="third_party_domain_blocklist">Lista domini di terze parti bloccati</string>
+        <string name="third_party_domain_initial_blocklist">Lista iniziale domini di terze parti bloccati</string>
+        <string name="third_party_regular_expression_blocklist">Lista di blocco espressioni regolari di terze parti</string>
+        <string name="third_party_domain_regular_expression_blocklist">Lista di blocco espressioni regolari domini di terze parti</string>
+        <string name="regular_expression_blocklist">Lista di blocco espressioni regolari</string>
+    <string name="filterlist_entries">Elementi della lista dei filtri</string>
+    <string name="filterlist_original_entry">Elemento originale della lista dei filtri</string>
 
     <!-- Domains. -->
     <string name="domains">Domini</string>
         <string name="allow_screenshots">Permetti gli screenshot</string>
         <string name="allow_screenshots_summary">Permette gli screenshot, la registrazione di video, e la possibilità di visualizzare su schermi non sicuri.
             La modifica di questa impostazione provoca il riavvio di Privacy Browser.</string>
+    <string name="filterlists">Lista dei filtri</string>
         <string name="easylist">EasyList</string>
+        <string name="easylist_summary">Lista principale dei filtri degli annunci.</string>
         <string name="easyprivacy">EasyPrivacy</string>
+        <string name="easyprivacy_summary">Lista principale dei filtri per i tracker.</string>
         <string name="fanboys_annoyance_list">Fanboy’s annoyance list</string>
+        <string name="fanboys_annoyance_list_summary">Filtra collegamenti e popups fastidiosi.  Include le liste Fanboy’s social blocking.</string>
         <string name="fanboys_social_blocking_list">Fanboy’s social blocking list</string>
+        <string name="fanboys_social_blocking_list_summary">Filtra i contenuti dei social media di terze parti.</string>
         <string name="ultralist">UltraList</string>
+        <string name="ultralist_summary">UltraList filtra gli annunci che EasyList non è in grado di bloccare per non rendere inaccessibili i siti web.</string>
         <string name="ultraprivacy">UltraPrivacy</string>
+        <string name="ultraprivacy_summary">UltraPrivacy filtra i trackers che EasyList non è in grado di bloccare per non rendere inaccessibili i siti web.</string>
         <string name="block_all_third_party_requests">Blocca tutte le richieste di Terze Parti</string>
         <string name="block_all_third_party_requests_summary">Il blocco di tutte le richieste di Terze Parti aumenta privacy, ma impedisce la visualizzazione di molti siti web.</string>
     <string name="url_modification">Modifica delle URL</string>
diff --git a/fastlane/metadata/android/de-DE/changelogs/69.txt b/fastlane/metadata/android/de-DE/changelogs/69.txt
new file mode 100644 (file)
index 0000000..eb37b4e
--- /dev/null
@@ -0,0 +1,8 @@
+• Nicht den voreingestellten Werten entsprechende Domain-Einstellungen werden nun durch einen geänderten Hintergrund hervorgehoben.
+• Die Bezeichnungen whitelist und blacklist wurden aus dem Projekt entfernt.
+• Vorgeschlagene Dateinamen wurden vereinheitlicht.
+• Hintergrundfarbe der App-Leiste bei Verwendung von Proxies wurde geändert.
+• Die Scroll-Position wird wiederhergestellt, wenn der Einstellungs-Dialog neu gestartet wird.
+• Letzte Programmteile nach Kotlin migriert und veraltete AsyncTasks entfernt.
+• Diverse kleine Code-Optimierungen für einen effizienteren Programmablauf.
+• Aktualisierte deutsche Übersetzung von Bernhard G. Keller.
\ No newline at end of file
index 0b0db152277ffa724da728af5b234a4155fcb27f..acf89f0b7f07ea95b615180f3c684434b25ed924 100644 (file)
Binary files a/fastlane/metadata/android/it-IT/images/phoneScreenshots/03-OptionsMenu-it.png and b/fastlane/metadata/android/it-IT/images/phoneScreenshots/03-OptionsMenu-it.png differ
diff --git a/fastlane/metadata/android/ru-RU/changelogs/69.txt b/fastlane/metadata/android/ru-RU/changelogs/69.txt
new file mode 100644 (file)
index 0000000..cc8e1d0
--- /dev/null
@@ -0,0 +1,7 @@
+• Подсвечивание фона параметров домена, которые не являются настройками по умолчанию.
+• Из проекта исключены термины белый список и черный список.
+• Стандартизированы предлагаемые имена файлов.
+• Обновлен цвет фона панели панели приложений.
+• При перезапуске приложения после смены настроек восстанавливается положение экрана.
+• Выполнена миграция последней части кода на Kotlin и удаление устаревших AsyncTasks.
+• Оптимизирован код некоторых фрагментов для более эффективной работы.
\ No newline at end of file
index 4bc0643bbc311d807dc6f5ba0e780e77d38a2976..e360d698c496ef7c3bf02fa2085ddc74eee55ea2 100644 (file)
@@ -35,6 +35,9 @@ org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
 # Use AndroidX.
 android.useAndroidX=true
 
+# Use the experimental configuration cache, which can speed up the build process in nothing in the configuration has changed.
+org.gradle.unsafe.configuration-cache=true
+
 android.defaults.buildfeatures.buildconfig=true
 android.nonTransitiveRClass=false
 android.nonFinalResIds=false