aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt1
-rw-r--r--app/src/web/ts/click_a.ts93
-rw-r--r--app/src/web/ts/context_a.ts33
3 files changed, 92 insertions, 35 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
index 81ade98f..b06208a6 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostUrlOverlayValidator.kt
@@ -75,7 +75,6 @@ fun FrostWebView.requestWebOverlay(url: String): Boolean {
}
if (!Prefs.overlayEnabled) return false
if (context is WebOverlayActivityBase) {
- L.v { "Check web request from overlay" }
val shouldUseDesktop = url.formattedFbUrl.shouldUseDesktopAgent
//already overlay; manage user agent
if (userAgentString != USER_AGENT_DESKTOP && shouldUseDesktop) {
diff --git a/app/src/web/ts/click_a.ts b/app/src/web/ts/click_a.ts
index 5023610e..8d1d545b 100644
--- a/app/src/web/ts/click_a.ts
+++ b/app/src/web/ts/click_a.ts
@@ -1,34 +1,81 @@
(function () {
let prevented = false;
+ /**
+ * 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
+ }
+
+ /**
+ * Attempts to find a url entry at most [depth] away
+ * A url is found if the element has tag 'A', and the url isn't blank
+ */
+ function _parentUrl(el: HTMLElement, depth: number): string | null {
+ const element = _parentEl(el, depth, (el) => el.tagName === 'A');
+ if (!element) {
+ return null;
+ }
+ const url = element.getAttribute('href');
+ if (!url || url === '#') {
+ return null;
+ }
+ return url
+ }
+
+ /**
+ * Given event and target, return true if handled and false otherwise.
+ */
+ type EventHandler = (e: Event, target: HTMLElement) => Boolean
+
+ const _frostGeneral: EventHandler = (e, target) => {
+ // Notifications are two layers under
+ const url = _parentUrl(target, 2);
+ return Frost.loadUrl(url);
+ };
+
+ const _frostLaunchpadClick: EventHandler = (e, target) => {
+ if (!_parentEl(target, 6, (el) => el.id === 'launchpad')) {
+ return false
+ }
+ console.log('Clicked launchpad');
+ const url = _parentUrl(target, 5);
+ return Frost.loadUrl(url);
+ };
+
+ const handlers: EventHandler[] = [_frostLaunchpadClick, _frostGeneral];
+
const _frostAClick = (e: Event) => {
- // check for valid target
+ if (prevented) {
+ console.log("Click intercept prevented");
+ return
+ }
+ /*
+ * Commonality; check for valid target
+ */
const target = e.target || e.currentTarget || e.srcElement;
- if (!(target instanceof Element)) {
+ if (!(target instanceof HTMLElement)) {
console.log("No element found");
return
}
- let element: Element = target;
- // Notifications are two layers under
- for (let i = 0; i < 2; i++) {
- if (element.tagName !== 'A') {
- element = <Element>element.parentElement;
- }
- }
- if (element.tagName === 'A') {
- if (!prevented) {
- const url = element.getAttribute('href');
- if (!url || url === '#') {
- return
- }
- console.log(`Click intercept ${url}`);
- // If Frost is injected, check if loading the url through an overlay works
- if (Frost.loadUrl(url)) {
- e.stopPropagation();
- e.preventDefault();
- }
- } else {
- console.log("Click intercept prevented")
+ for (const h of handlers) {
+ if (h(e, target)) {
+ e.stopPropagation();
+ e.preventDefault();
+ return
}
}
};
diff --git a/app/src/web/ts/context_a.ts b/app/src/web/ts/context_a.ts
index 5eec7611..b9549f3f 100644
--- a/app/src/web/ts/context_a.ts
+++ b/app/src/web/ts/context_a.ts
@@ -7,6 +7,25 @@
let longClick = false;
/**
+ * 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
+ }
+
+ /**
* Given event and target, return true if handled and false otherwise.
*/
type EventHandler = (e: Event, target: HTMLElement) => Boolean
@@ -55,16 +74,8 @@
* Opens image activity for posts with just one image
*/
const _frostImage: EventHandler = (e, target) => {
- let element: Element = target;
- // Notifications are two layers under
- for (let i = 0; i < 2; i++) {
- if (element.tagName !== 'A') {
- element = <Element>element.parentElement;
- } else {
- break
- }
- }
- if (element.tagName !== 'A') {
+ const element = _parentEl(target, 2, (el) => el.tagName === 'A');
+ if (!element) {
return false;
}
const url = element.getAttribute('href');
@@ -92,7 +103,7 @@
return true;
};
- const handlers = [_frostImage, _frostCopyComment, _frostCopyPost];
+ const handlers: EventHandler[] = [_frostImage, _frostCopyComment, _frostCopyPost];
const _frostAContext = (e: Event) => {
Frost.longClick(true);