aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2019-07-02 16:29:28 -0700
committerAllan Wang <me@allanwang.ca>2019-07-02 16:29:28 -0700
commit4c551386b100ea4b694c1e8f44596ba369e6b068 (patch)
treef18e167cf804e70820703e6951060004ef12e774
parent99e70f4489ce210e514c9194cdac288d2de651c4 (diff)
downloadfrost-4c551386b100ea4b694c1e8f44596ba369e6b068.tar.gz
frost-4c551386b100ea4b694c1e8f44596ba369e6b068.tar.bz2
frost-4c551386b100ea4b694c1e8f44596ba369e6b068.zip
Prevent horizontal swipes if html element can scroll horizontally
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt1
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt18
-rw-r--r--app/src/web/ts/click_a.ts10
-rw-r--r--app/src/web/ts/horizontal_scrolling.ts61
-rw-r--r--app/src/web/typings/frost.d.ts26
7 files changed, 102 insertions, 21 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
index ad42418e..d46422b8 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
@@ -34,7 +34,7 @@ import java.util.Locale
*/
enum class JsAssets : InjectorContract {
MENU, CLICK_A, CONTEXT_A, MEDIA, HEADER_BADGES, TEXTAREA_LISTENER, NOTIF_MSG,
- DOCUMENT_WATCHER
+ DOCUMENT_WATCHER, HORIZONTAL_SCROLLING
;
@VisibleForTesting
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
index 0d980ba0..d75a4f1f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt
@@ -140,4 +140,9 @@ class FrostJSI(val web: FrostWebView) {
html ?: return
header?.offer(html)
}
+
+ @JavascriptInterface
+ fun allowHorizontalScrolling(enable: Boolean) {
+ activity?.viewPager?.enableSwipe = enable
+ }
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
index 003ed7f9..85914f33 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
@@ -102,6 +102,7 @@ open class FrostWebViewClient(val web: FrostWebView) : BaseWebViewClient() {
Prefs.aggressiveRecents
),
JsAssets.DOCUMENT_WATCHER,
+ JsAssets.HORIZONTAL_SCROLLING,
JsAssets.CLICK_A,
CssHider.ADS.maybe(!Prefs.showFacebookAds),
JsAssets.CONTEXT_A,
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
index 7c3c48e7..da0ebf0d 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/NestedWebView.kt
@@ -120,10 +120,20 @@ open class NestedWebView @JvmOverloads constructor(
dxUnconsumed: Int,
dyUnconsumed: Int,
offsetInWindow: IntArray?
- ) = childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
-
- final override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?) =
- childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
+ ) = childHelper.dispatchNestedScroll(
+ dxConsumed,
+ dyConsumed,
+ dxUnconsumed,
+ dyUnconsumed,
+ offsetInWindow
+ )
+
+ final override fun dispatchNestedPreScroll(
+ dx: Int,
+ dy: Int,
+ consumed: IntArray?,
+ offsetInWindow: IntArray?
+ ) = childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
final override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean) =
childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
diff --git a/app/src/web/ts/click_a.ts b/app/src/web/ts/click_a.ts
index 8d1d545b..1fd63683 100644
--- a/app/src/web/ts/click_a.ts
+++ b/app/src/web/ts/click_a.ts
@@ -91,14 +91,16 @@
prevented = true;
};
+ const _frostAllowClick = () => {
+ prevented = false;
+ clearTimeout(clickTimeout)
+ };
+
document.addEventListener('click', _frostAClick, true);
let clickTimeout: number | undefined = undefined;
document.addEventListener('touchstart', () => {
clickTimeout = setTimeout(_frostPreventClick, 400);
}, true);
- document.addEventListener('touchend', () => {
- prevented = false;
- clearTimeout(clickTimeout)
- }, true);
+ document.addEventListener('touchend', _frostAllowClick, true);
}).call(undefined);
diff --git a/app/src/web/ts/horizontal_scrolling.ts b/app/src/web/ts/horizontal_scrolling.ts
new file mode 100644
index 00000000..b104725e
--- /dev/null
+++ b/app/src/web/ts/horizontal_scrolling.ts
@@ -0,0 +1,61 @@
+(function () {
+
+ /**
+ * Go up at most [depth] times, to retrieve a parent matching the provided predicate
+ * If one is found, it is returned immediately.
+ * Otherwise, null is returned.
+ */
+ function _parentEl(el: HTMLElement, depth: number, predicate: (el: HTMLElement) => boolean): HTMLElement | null {
+ for (let i = 0; i < depth + 1; i++) {
+ if (predicate(el)) {
+ return el
+ }
+ const parent = el.parentElement;
+ if (!parent) {
+ return null
+ }
+ el = parent
+ }
+ return null
+ }
+
+ /**
+ * Check if element can scroll horizontally.
+ * We primarily rely on the overflow-x field.
+ * For performance reasons, we will check scrollWidth first to see if scrolling is a possibility
+ */
+ function _canScrollHorizontally(el: HTMLElement): boolean {
+ /*
+ * Sometimes the offsetWidth is off by < 10px. We use the multiplier
+ * since the trays are typically more than 2 times greater
+ */
+ if (el.scrollWidth > el.offsetWidth * 1.2) {
+ return true
+ }
+ const styles = window.getComputedStyle(el);
+ /*
+ * Works well in testing, but on mobile it just shows 'visible'
+ */
+ return styles.overflowX === 'scroll';
+ }
+
+ const _frostCheckHorizontalScrolling = (e: Event) => {
+ const target = e.target || e.currentTarget || e.srcElement;
+ if (!(target instanceof HTMLElement)) {
+ return
+ }
+ const scrollable = _parentEl(target, 5, _canScrollHorizontally) !== null;
+ if (scrollable) {
+ console.log('Pause horizontal scrolling');
+ Frost.allowHorizontalScrolling(false);
+ }
+ };
+
+ const _frostResetHorizontalScrolling = (e: Event) => {
+ Frost.allowHorizontalScrolling(true)
+ };
+
+ document.addEventListener('touchstart', _frostCheckHorizontalScrolling, true);
+ document.addEventListener('touchend', _frostResetHorizontalScrolling, true);
+}).call(undefined);
+
diff --git a/app/src/web/typings/frost.d.ts b/app/src/web/typings/frost.d.ts
index 8f60c9dd..ae7c97ab 100644
--- a/app/src/web/typings/frost.d.ts
+++ b/app/src/web/typings/frost.d.ts
@@ -1,27 +1,29 @@
declare interface FrostJSI {
- loadUrl(url: string | null): boolean
+ loadUrl(url: string | null): boolean
- loadVideo(url: string | null, isGif: boolean): boolean
+ loadVideo(url: string | null, isGif: boolean): boolean
- reloadBaseUrl(animate: boolean)
+ reloadBaseUrl(animate: boolean)
- contextMenu(url: string | null, text: string | null)
+ contextMenu(url: string | null, text: string | null)
- longClick(start: boolean)
+ longClick(start: boolean)
- disableSwipeRefresh(disable: boolean)
+ disableSwipeRefresh(disable: boolean)
- loadLogin()
+ loadLogin()
- loadImage(imageUrl: string, text: string | null)
+ loadImage(imageUrl: string, text: string | null)
- emit(flag: number)
+ emit(flag: number)
- isReady()
+ isReady()
- handleHtml(html: string | null)
+ handleHtml(html: string | null)
- handleHeader(html: string | null)
+ handleHeader(html: string | null)
+
+ allowHorizontalScrolling(enable: boolean)
}
declare var Frost: FrostJSI;