From fd8556e4e7c0db9f58e1cf14a2e0c6590f91305e Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Wed, 3 Jun 2020 12:19:59 -0700 Subject: [PATCH] Fix problems with swipe to refresh. https://redmine.stoutner.com/issues/514 --- .../activities/MainWebViewActivity.java | 93 +++++++++++++------ app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values-es/strings.xml | 3 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 3 +- app/src/main/res/values-ru/strings.xml | 3 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 78 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index becbd5ac..89a73f25 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -4050,23 +4050,29 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh); - // Apply swipe to refresh according to the default. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. - swipeRefreshLayout.setEnabled(defaultSwipeToRefresh); + // Update the swipe refresh layout. + if (defaultSwipeToRefresh) { // Swipe to refresh is enabled. + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); + } else { // Swipe to refresh is disabled. + // Disable the swipe refresh layout. + swipeRefreshLayout.setEnabled(false); + } break; case DomainsDatabaseHelper.ENABLED: // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(true); - // Enable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. - swipeRefreshLayout.setEnabled(true); + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); break; case DomainsDatabaseHelper.DISABLED: // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(false); - // Disable swipe to refresh. This can be removed once the minimum API >= 23 because it is continuously set by an on scroll change listener. + // Disable swipe to refresh. swipeRefreshLayout.setEnabled(false); } @@ -4154,8 +4160,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.setSwipeToRefresh(defaultSwipeToRefresh); - // Apply swipe to refresh according to the default. - swipeRefreshLayout.setEnabled(defaultSwipeToRefresh); + // Update the swipe refresh layout. + if (defaultSwipeToRefresh) { // Swipe to refresh is enabled. + // Only enable the swipe refresh layout if the WebView is scrolled to the top. It is updated every time the scroll changes. + swipeRefreshLayout.setEnabled(currentWebView.getY() == 0); + } else { // Swipe to refresh is disabled. + // Disable the swipe refresh layout. + swipeRefreshLayout.setEnabled(false); + } // Reset the pinned variables. nestedScrollWebView.setDomainSettingsDatabaseId(-1); @@ -5176,26 +5188,55 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook }); // Update the status of swipe to refresh based on the scroll position of the nested scroll WebView. Also reinforce full screen browsing mode. - // Once the minimum API >= 23 this can be replaced with `nestedScrollWebView.setOnScrollChangeListener()`. - nestedScrollWebView.getViewTreeObserver().addOnScrollChangedListener(() -> { - if (nestedScrollWebView.getSwipeToRefresh()) { - // Only enable swipe to refresh if the WebView is scrolled to the top. - swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); - } + // On API < 23, `getViewTreeObserver().addOnScrollChangedListener()` must be used, but it is a little bit buggy and appears to get garbage collected from time to time. + if (Build.VERSION.SDK_INT >= 23) { + nestedScrollWebView.setOnScrollChangeListener((view, i, i1, i2, i3) -> { + if (nestedScrollWebView.getSwipeToRefresh()) { + // Only enable swipe to refresh if the WebView is scrolled to the top. + swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); + } else { + // Disable swipe to refresh. + swipeRefreshLayout.setEnabled(false); + } - // Reinforce the system UI visibility flags if in full screen browsing mode. - // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. - if (inFullScreenBrowsingMode) { - /* Hide the system bars. - * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. - */ - rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | - View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); - } - }); + // Reinforce the system UI visibility flags if in full screen browsing mode. + // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. + if (inFullScreenBrowsingMode) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + }); + } else { + nestedScrollWebView.getViewTreeObserver().addOnScrollChangedListener(() -> { + if (nestedScrollWebView.getSwipeToRefresh()) { + // Only enable swipe to refresh if the WebView is scrolled to the top. + swipeRefreshLayout.setEnabled(nestedScrollWebView.getScrollY() == 0); + } else { + // Disable swipe to refresh. + swipeRefreshLayout.setEnabled(false); + } + + + // Reinforce the system UI visibility flags if in full screen browsing mode. + // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard. + if (inFullScreenBrowsingMode) { + /* Hide the system bars. + * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown. + */ + rootFrameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); + } + }); + } // Set the web chrome client. nestedScrollWebView.setWebChromeClient(new WebChromeClient() { diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4c5b84a4..5e282ead 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -492,7 +492,8 @@ Eigener User Agent Inkognito-Modus - Löscht den Verlauf und den Cache nach jedem fertigen Laden einer Webseite. Zurück und vorwärts funktioniert im Inkognito-Modus nicht. + Löscht den Verlauf und den Cache nach jedem fertigen Laden einer Webseite. + Im Incognito-Modus schliesst \'Zurück\'-Button den aktive Tab (oder die App, wenn nur ein Tab geöffnet wurde). Nicht verfolgen (Do not track) Einen "Do Not Track-Header" senden, der freundlich anfragt, dass Webserver diesen Browser nicht nachverfolgen sollen. Screenshots zulassen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2928a6ed..1152e50c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -489,7 +489,8 @@ Agente de usuario personalizado Modo incógnito - Borrar el historial y el caché después de que cada página web termine de cargar. Adelante y atrás no funcionan en el Modo incógnito. + Borrar el historial y el caché después de que cada página web termine de cargar. + En el modo Incógnito, Atrás cierra la pestaña (o la app si hay solo una pestaña). No rastrear Enviar la cabecera de no rastrear (DNT) que educadamente sugiere que los servidores web no rastreen este navegador. Permitir capturas de pantalla diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index afd9e9dc..a2923cee 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -489,7 +489,7 @@ User agent personnalisé Mode Incognito - Vider l\'historique et le cache après le chargement de chaque page. Précédent et Suivant ne fonctionnent pas en mode Incognito. + Vider l\'historique et le cache après le chargement de chaque page. In Incognito Mode, back closes the tab (or the app if there is only one tab). Ne pas me pister Envoyer aux sites web un signal «Ne pas me pister» indiquant poliement que vous ne souhaitez pas être pisté Autoriser captures d\'écrans diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 051a38b1..874c6972 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -488,7 +488,8 @@ User agent personalizzato Modalità Incognito - Cancella la cronologia e la cache al termine del caricamento di ogni pagina. I pulsanti Avanti e Indietro non funzionano in modalità incognito. + Cancella la cronologia e la cache al termine del caricamento di ogni pagina. + In Modalità Incognito, il tasto "Indietro" chiude la scheda (o l\'applicazione se è aperta solo una scheda). Non tracciare Invia un\'intestazione di non tracciamento per chiedere al web server di non tracciare il browser. Permetti gli screenshot diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 51fafbd9..4e32aa5c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -483,7 +483,8 @@ Настраиваемый user agent Режим инкогнито - Очистка журнала и кэша после завершения загрузки каждой веб-страницы. Кнопки \'Вперед\' и \'Назад\' не работают в этом режиме. + Очистка журнала и кэша по завершении загрузки каждой веб-страницы. + В режиме инкогнито нажатие кнопки Назад приведет к закрытию вкладки (или приложения, если открыта только одна вкладка). Не отслеживать Отправлять заголовок \'Не отслеживать\', предлагающий веб-серверу не отслеживать этот браузер. Разрешить скриншоты diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 87c8351c..5f0b590c 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -461,7 +461,7 @@ Özel kullanıcı aracısı Gizli Mod - Her web sayfasının yüklenmesi bittikten sonra geçmişi ve önbelleği temizler. İleri ve geri seçenekleri Gizli Mod aktifken çalışmaz. + Her web sayfasının yüklenmesi bittikten sonra geçmişi ve önbelleği temizler. In Incognito Mode, back closes the tab (or the app if there is only one tab). Takip Etme Web Serverlarına bu tarayıcıyı takip etmemesi için Takip Etme Başlığı gönderir. Ekran görüntülerine izin ver diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e6c35629..91df074d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -525,7 +525,7 @@ Custom user agent System default user agent Incognito Mode - Clear the history and cache after each webpage finishes loading. Forward and back do not work in Incognito Mode. + Clear the history and cache after each webpage finishes loading. In Incognito Mode, back closes the tab (or the app if there is only one tab). Do Not Track Send the Do Not Track header, which politely suggests that web servers not track this browser. Allow screenshots -- 2.45.2