From 330bf2857396b15752afadb030c981a1cb2848fe Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 5 Feb 2019 22:13:41 -0500 Subject: Enhancement/js (#1344) * Attempt to add package json * Add initial typescript components * Convert remaining files * Remove some null checks * Reorganize folders * Add missing js and tests for file paths * Delete unused babelrc * Remove unused packages --- app/src/web/assets/js/context_a.js | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 app/src/web/assets/js/context_a.js (limited to 'app/src/web/assets/js/context_a.js') diff --git a/app/src/web/assets/js/context_a.js b/app/src/web/assets/js/context_a.js new file mode 100644 index 00000000..7e636cea --- /dev/null +++ b/app/src/web/assets/js/context_a.js @@ -0,0 +1,68 @@ +"use strict"; +/** + * Context menu for links + * Largely mimics click_a.js + */ +(function () { + var longClick = false; + var _frostAContext = function (e) { + Frost.longClick(true); + longClick = true; + /* + * Commonality; check for valid target + */ + var target = e.target || e.currentTarget || e.srcElement; + if (!(target instanceof Element)) { + console.log("No element found"); + return; + } + var element = target; + // Notifications are two layers under + for (var i = 0; i < 2; i++) { + if (element.tagName != 'A') { + element = element.parentElement; + } + } + if (element.tagName == 'A') { + var url = element.getAttribute('href'); + if (!url || url == '#') { + return; + } + var text = element.parentElement.innerText; + // Check if image item exists, first in children and then in parent + var image = element.querySelector("[style*=\"background-image: url(\"]"); + if (!image) { + image = element.parentElement.querySelector("[style*=\"background-image: url(\"]"); + } + if (image) { + var imageUrl = window.getComputedStyle(image, null).backgroundImage.trim().slice(4, -1); + console.log("Context image: " + imageUrl); + Frost.loadImage(imageUrl, text); + e.stopPropagation(); + e.preventDefault(); + return; + } + // Check if true img exists + var img = element.querySelector("img[src*=scontent]"); + if (img instanceof HTMLMediaElement) { + var imgUrl = img.src; + console.log("Context img: " + imgUrl); + Frost.loadImage(imgUrl, text); + e.stopPropagation(); + e.preventDefault(); + return; + } + console.log("Context content " + url + " " + text); + Frost.contextMenu(url, text); + e.stopPropagation(); + e.preventDefault(); + } + }; + document.addEventListener('contextmenu', _frostAContext, true); + document.addEventListener('touchend', function () { + if (longClick) { + Frost.longClick(false); + longClick = false; + } + }, true); +}).call(undefined); -- cgit v1.2.3 From 87469aba96cee61b4252d9a6d023324598355244 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 5 Feb 2019 22:40:24 -0500 Subject: Strip images and update context handler --- app/src/main/res/xml/frost_changelog.xml | 4 +- app/src/web/assets/js/click_a.js | 9 --- app/src/web/assets/js/click_debugger.js | 2 - app/src/web/assets/js/context_a.js | 100 ++++++++++++++------------ app/src/web/assets/js/context_a.ts | 108 +++++++++++++++++++---------- app/src/web/assets/js/document_watcher.js | 1 - app/src/web/assets/js/header_badges.js | 1 - app/src/web/assets/js/media.js | 2 - app/src/web/assets/js/menu.js | 2 - app/src/web/assets/js/notif_msg.js | 1 - app/src/web/assets/js/textarea_listener.js | 8 --- app/src/web/tsconfig.json | 3 +- 12 files changed, 133 insertions(+), 108 deletions(-) (limited to 'app/src/web/assets/js/context_a.js') diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml index f90ecf37..ed014604 100644 --- a/app/src/main/res/xml/frost_changelog.xml +++ b/app/src/main/res/xml/frost_changelog.xml @@ -8,8 +8,8 @@ - - + + diff --git a/app/src/web/assets/js/click_a.js b/app/src/web/assets/js/click_a.js index 7faafc15..be69bb8c 100644 --- a/app/src/web/assets/js/click_a.js +++ b/app/src/web/assets/js/click_a.js @@ -2,14 +2,12 @@ (function () { var prevented = false; var _frostAClick = function (e) { - // check for valid target var target = e.target || e.currentTarget || e.srcElement; if (!(target instanceof Element)) { console.log("No element found"); return; } var element = target; - // Notifications are two layers under for (var i = 0; i < 2; i++) { if (element.tagName !== 'A') { element = element.parentElement; @@ -22,7 +20,6 @@ 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(); @@ -33,12 +30,6 @@ } } }; - /* - * On top of the click event, we must stop it for long presses - * Since that will conflict with the context menu - * Note that we only override it on conditions where the context menu - * Will occur - */ var _frostPreventClick = function () { console.log("Click _frostPrevented"); prevented = true; diff --git a/app/src/web/assets/js/click_debugger.js b/app/src/web/assets/js/click_debugger.js index aab4572d..16729899 100644 --- a/app/src/web/assets/js/click_debugger.js +++ b/app/src/web/assets/js/click_debugger.js @@ -1,8 +1,6 @@ "use strict"; -// For desktop only (function () { var _frostAContext = function (e) { - // Commonality; check for valid target var element = e.target || e.currentTarget || e.srcElement; if (!(element instanceof Element)) { console.log("No element found"); diff --git a/app/src/web/assets/js/context_a.js b/app/src/web/assets/js/context_a.js index 7e636cea..0573a17a 100644 --- a/app/src/web/assets/js/context_a.js +++ b/app/src/web/assets/js/context_a.js @@ -1,61 +1,75 @@ "use strict"; -/** - * Context menu for links - * Largely mimics click_a.js - */ (function () { var longClick = false; + var _frostCopyPost = function (e, target) { + if (target.tagName != 'A') { + return false; + } + var parent1 = target.parentElement; + if (!parent1 || parent1.tagName != 'DIV') { + return false; + } + var parent2 = parent1.parentElement; + if (!parent2 || !parent2.classList.contains('story_body_container')) { + return false; + } + var url = target.getAttribute('href'); + var text = parent1.innerText; + Frost.contextMenu(url, text); + return true; + }; + var _frostImage = function (e, target) { + var element = target; + for (var i = 0; i < 2; i++) { + if (element.tagName != 'A') { + element = element.parentElement; + } + } + if (element.tagName != 'A') { + return false; + } + var url = element.getAttribute('href'); + if (!url || url == '#') { + return false; + } + var text = element.parentElement.innerText; + var image = element.querySelector("[style*=\"background-image: url(\"]"); + if (!image) { + image = element.parentElement.querySelector("[style*=\"background-image: url(\"]"); + } + if (image) { + var imageUrl = window.getComputedStyle(image, null).backgroundImage.trim().slice(4, -1); + console.log("Context image: " + imageUrl); + Frost.loadImage(imageUrl, text); + return true; + } + var img = element.querySelector("img[src*=scontent]"); + if (img instanceof HTMLMediaElement) { + var imgUrl = img.src; + console.log("Context img: " + imgUrl); + Frost.loadImage(imgUrl, text); + return true; + } + console.log("Context content " + url + " " + text); + Frost.contextMenu(url, text); + return true; + }; + var handlers = [_frostCopyPost, _frostImage]; var _frostAContext = function (e) { Frost.longClick(true); longClick = true; - /* - * Commonality; check for valid target - */ var target = e.target || e.currentTarget || e.srcElement; if (!(target instanceof Element)) { console.log("No element found"); return; } - var element = target; - // Notifications are two layers under - for (var i = 0; i < 2; i++) { - if (element.tagName != 'A') { - element = element.parentElement; - } - } - if (element.tagName == 'A') { - var url = element.getAttribute('href'); - if (!url || url == '#') { - return; - } - var text = element.parentElement.innerText; - // Check if image item exists, first in children and then in parent - var image = element.querySelector("[style*=\"background-image: url(\"]"); - if (!image) { - image = element.parentElement.querySelector("[style*=\"background-image: url(\"]"); - } - if (image) { - var imageUrl = window.getComputedStyle(image, null).backgroundImage.trim().slice(4, -1); - console.log("Context image: " + imageUrl); - Frost.loadImage(imageUrl, text); - e.stopPropagation(); - e.preventDefault(); - return; - } - // Check if true img exists - var img = element.querySelector("img[src*=scontent]"); - if (img instanceof HTMLMediaElement) { - var imgUrl = img.src; - console.log("Context img: " + imgUrl); - Frost.loadImage(imgUrl, text); + for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) { + var h = handlers_1[_i]; + if (h(e, target)) { e.stopPropagation(); e.preventDefault(); return; } - console.log("Context content " + url + " " + text); - Frost.contextMenu(url, text); - e.stopPropagation(); - e.preventDefault(); } }; document.addEventListener('contextmenu', _frostAContext, true); diff --git a/app/src/web/assets/js/context_a.ts b/app/src/web/assets/js/context_a.ts index 16ed33a9..06d2f4a2 100644 --- a/app/src/web/assets/js/context_a.ts +++ b/app/src/web/assets/js/context_a.ts @@ -2,8 +2,78 @@ * Context menu for links * Largely mimics click_a.js */ + (function () { let longClick = false; + + /** + * Given event and target, return true if handled and false otherwise. + */ + type EventHandler = (e: Event, target: Element) => Boolean + + /** + * Posts should click a tag, with two parents up being div.story_body_container + */ + const _frostCopyPost: EventHandler = (e, target) => { + if (target.tagName != 'A') { + return false; + } + const parent1 = target.parentElement; + if (!parent1 || parent1.tagName != 'DIV') { + return false; + } + const parent2 = parent1.parentElement; + if (!parent2 || !parent2.classList.contains('story_body_container')) { + return false; + } + const url = target.getAttribute('href')!; + const text = parent1.innerText; + Frost.contextMenu(url, text); + return true; + }; + + 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.parentElement; + } + } + if (element.tagName != 'A') { + return false + } + const url = element.getAttribute('href'); + if (!url || url == '#') { + return false + } + const text = (element.parentElement).innerText; + // Check if image item exists, first in children and then in parent + let image = element.querySelector("[style*=\"background-image: url(\"]"); + if (!image) { + image = (element.parentElement).querySelector("[style*=\"background-image: url(\"]") + } + if (image) { + const imageUrl = (window.getComputedStyle(image, null).backgroundImage).trim().slice(4, -1); + console.log(`Context image: ${imageUrl}`); + Frost.loadImage(imageUrl, text); + return true + } + // Check if true img exists + const img = element.querySelector("img[src*=scontent]"); + if (img instanceof HTMLMediaElement) { + const imgUrl = img.src; + console.log(`Context img: ${imgUrl}`); + Frost.loadImage(imgUrl, text); + return true + } + console.log(`Context content ${url} ${text}`); + Frost.contextMenu(url, text); + return true + }; + + const handlers = [_frostCopyPost, _frostImage]; + const _frostAContext = (e: Event) => { Frost.longClick(true); longClick = true; @@ -16,46 +86,12 @@ 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.parentElement; - } - } - if (element.tagName == 'A') { - const url = element.getAttribute('href'); - if (!url || url == '#') { - return - } - const text = (element.parentElement).innerText; - // Check if image item exists, first in children and then in parent - let image = element.querySelector("[style*=\"background-image: url(\"]"); - if (!image) { - image = (element.parentElement).querySelector("[style*=\"background-image: url(\"]") - } - if (image) { - const imageUrl = (window.getComputedStyle(image, null).backgroundImage).trim().slice(4, -1); - console.log(`Context image: ${imageUrl}`); - Frost.loadImage(imageUrl, text); - e.stopPropagation(); - e.preventDefault(); - return - } - // Check if true img exists - const img = element.querySelector("img[src*=scontent]"); - if (img instanceof HTMLMediaElement) { - const imgUrl = img.src; - console.log(`Context img: ${imgUrl}`); - Frost.loadImage(imgUrl, text); + for (const h of handlers) { + if (h(e, target)) { e.stopPropagation(); e.preventDefault(); return } - console.log(`Context content ${url} ${text}`); - Frost.contextMenu(url, text); - e.stopPropagation(); - e.preventDefault(); } }; diff --git a/app/src/web/assets/js/document_watcher.js b/app/src/web/assets/js/document_watcher.js index f3c4ab25..12252201 100644 --- a/app/src/web/assets/js/document_watcher.js +++ b/app/src/web/assets/js/document_watcher.js @@ -1,5 +1,4 @@ "use strict"; -// Emit key once half the viewport is covered (function () { var isReady = function () { return document.body.scrollHeight > innerHeight + 100; diff --git a/app/src/web/assets/js/header_badges.js b/app/src/web/assets/js/header_badges.js index daaf540a..b1ceee05 100644 --- a/app/src/web/assets/js/header_badges.js +++ b/app/src/web/assets/js/header_badges.js @@ -1,5 +1,4 @@ "use strict"; -// Fetches the header contents if it exists (function () { var header = document.getElementById('mJewelNav'); if (header) { diff --git a/app/src/web/assets/js/media.js b/app/src/web/assets/js/media.js index 571168d6..baeba0a1 100644 --- a/app/src/web/assets/js/media.js +++ b/app/src/web/assets/js/media.js @@ -1,5 +1,4 @@ "use strict"; -// Handles media events (function () { var _frostMediaClick = function (e) { var target = e.target || e.srcElement; @@ -30,7 +29,6 @@ return; } var url = dataStore.src; - // !startsWith; see https://stackoverflow.com/a/36876507/4407321 if (!url || url.lastIndexOf('http', 0) !== 0) { return; } diff --git a/app/src/web/assets/js/menu.js b/app/src/web/assets/js/menu.js index c30e93cf..b6a30209 100644 --- a/app/src/web/assets/js/menu.js +++ b/app/src/web/assets/js/menu.js @@ -1,5 +1,4 @@ "use strict"; -// Click menu and move contents to main view (function () { var viewport = document.querySelector("#viewport"); var root = document.querySelector("#root"); @@ -35,7 +34,6 @@ if (menu) { x.disconnect(); console.log("Found side menu"); - // Transfer elements while (root.firstChild) { root.removeChild(root.firstChild); } diff --git a/app/src/web/assets/js/notif_msg.js b/app/src/web/assets/js/notif_msg.js index 20a89e88..bcff697b 100644 --- a/app/src/web/assets/js/notif_msg.js +++ b/app/src/web/assets/js/notif_msg.js @@ -1,5 +1,4 @@ "use strict"; -// Binds callback to an invisible webview to take in the search events (function () { var finished = false; var x = new MutationObserver(function () { diff --git a/app/src/web/assets/js/textarea_listener.js b/app/src/web/assets/js/textarea_listener.js index 9a8783c1..02336382 100644 --- a/app/src/web/assets/js/textarea_listener.js +++ b/app/src/web/assets/js/textarea_listener.js @@ -1,12 +1,4 @@ "use strict"; -/* - * focus listener for textareas - * since swipe to refresh is quite sensitive, we will disable it - * when we detect a user typing - * note that this extends passed having a keyboard opened, - * as a user may still be reviewing his/her post - * swiping should automatically be reset on refresh - */ (function () { var _frostFocus = function (e) { var element = e.target || e.srcElement; diff --git a/app/src/web/tsconfig.json b/app/src/web/tsconfig.json index 711fdcbb..ea88e28e 100644 --- a/app/src/web/tsconfig.json +++ b/app/src/web/tsconfig.json @@ -16,7 +16,8 @@ "strictNullChecks": true, "noImplicitAny": true, "allowUnreachableCode": true, - "allowUnusedLabels": true + "allowUnusedLabels": true, + "removeComments": true }, "include": [ "assets/js", "assets/typings" -- cgit v1.2.3 From 8b850711ceb7c38f9368ce840831c1c0bdb4ba74 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 5 Feb 2019 22:44:47 -0500 Subject: Add log and strict equality --- app/src/web/assets/js/context_a.js | 11 ++++++----- app/src/web/assets/js/context_a.ts | 11 ++++++----- app/src/web/assets/js/textarea_listener.js | 2 +- app/src/web/assets/js/textarea_listener.ts | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) (limited to 'app/src/web/assets/js/context_a.js') diff --git a/app/src/web/assets/js/context_a.js b/app/src/web/assets/js/context_a.js index 0573a17a..d0f5c622 100644 --- a/app/src/web/assets/js/context_a.js +++ b/app/src/web/assets/js/context_a.js @@ -2,11 +2,11 @@ (function () { var longClick = false; var _frostCopyPost = function (e, target) { - if (target.tagName != 'A') { + if (target.tagName !== 'A') { return false; } var parent1 = target.parentElement; - if (!parent1 || parent1.tagName != 'DIV') { + if (!parent1 || parent1.tagName !== 'DIV') { return false; } var parent2 = parent1.parentElement; @@ -15,21 +15,22 @@ } var url = target.getAttribute('href'); var text = parent1.innerText; + console.log("Copy post " + url + " " + text); Frost.contextMenu(url, text); return true; }; var _frostImage = function (e, target) { var element = target; for (var i = 0; i < 2; i++) { - if (element.tagName != 'A') { + if (element.tagName !== 'A') { element = element.parentElement; } } - if (element.tagName != 'A') { + if (element.tagName !== 'A') { return false; } var url = element.getAttribute('href'); - if (!url || url == '#') { + if (!url || url === '#') { return false; } var text = element.parentElement.innerText; diff --git a/app/src/web/assets/js/context_a.ts b/app/src/web/assets/js/context_a.ts index 06d2f4a2..2a079f39 100644 --- a/app/src/web/assets/js/context_a.ts +++ b/app/src/web/assets/js/context_a.ts @@ -15,11 +15,11 @@ * Posts should click a tag, with two parents up being div.story_body_container */ const _frostCopyPost: EventHandler = (e, target) => { - if (target.tagName != 'A') { + if (target.tagName !== 'A') { return false; } const parent1 = target.parentElement; - if (!parent1 || parent1.tagName != 'DIV') { + if (!parent1 || parent1.tagName !== 'DIV') { return false; } const parent2 = parent1.parentElement; @@ -28,6 +28,7 @@ } const url = target.getAttribute('href')!; const text = parent1.innerText; + console.log(`Copy post ${url} ${text}`); Frost.contextMenu(url, text); return true; }; @@ -36,15 +37,15 @@ let element: Element = target; // Notifications are two layers under for (let i = 0; i < 2; i++) { - if (element.tagName != 'A') { + if (element.tagName !== 'A') { element = element.parentElement; } } - if (element.tagName != 'A') { + if (element.tagName !== 'A') { return false } const url = element.getAttribute('href'); - if (!url || url == '#') { + if (!url || url === '#') { return false } const text = (element.parentElement).innerText; diff --git a/app/src/web/assets/js/textarea_listener.js b/app/src/web/assets/js/textarea_listener.js index 02336382..1ec9b663 100644 --- a/app/src/web/assets/js/textarea_listener.js +++ b/app/src/web/assets/js/textarea_listener.js @@ -6,7 +6,7 @@ return; } console.log("FrostJSI focus, " + element.tagName); - if (element.tagName == 'TEXTAREA') { + if (element.tagName === 'TEXTAREA') { Frost.disableSwipeRefresh(true); } }; diff --git a/app/src/web/assets/js/textarea_listener.ts b/app/src/web/assets/js/textarea_listener.ts index 9d5fd388..062f5bf6 100644 --- a/app/src/web/assets/js/textarea_listener.ts +++ b/app/src/web/assets/js/textarea_listener.ts @@ -13,7 +13,7 @@ return } console.log(`FrostJSI focus, ${element.tagName}`); - if (element.tagName == 'TEXTAREA') { + if (element.tagName === 'TEXTAREA') { Frost.disableSwipeRefresh(true); } }; -- cgit v1.2.3 From ddfc310fde5f50ba52ef930287449c2e08faaca8 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 5 Feb 2019 23:02:50 -0500 Subject: Add ability to copy comments, resolves #454 --- .../com/pitchedapps/frost/utils/WebContextMenu.kt | 44 ++++++++++++---------- .../kotlin/com/pitchedapps/frost/web/FrostJSI.kt | 5 +-- app/src/web/assets/js/context_a.js | 13 ++++++- app/src/web/assets/js/context_a.ts | 28 +++++++++----- app/src/web/assets/typings/frost.d.ts | 2 +- docs/Changelog.md | 2 + 6 files changed, 59 insertions(+), 35 deletions(-) (limited to 'app/src/web/assets/js/context_a.js') diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt index 62330e4d..fbaa4574 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/WebContextMenu.kt @@ -20,7 +20,6 @@ import android.content.Context import ca.allanwang.kau.utils.copyToClipboard import ca.allanwang.kau.utils.shareText import ca.allanwang.kau.utils.string -import ca.allanwang.kau.utils.toast import com.pitchedapps.frost.R import com.pitchedapps.frost.activities.MainActivity import com.pitchedapps.frost.facebook.formattedFbUrl @@ -29,19 +28,19 @@ import com.pitchedapps.frost.facebook.formattedFbUrl * Created by Allan Wang on 2017-07-07. */ fun Context.showWebContextMenu(wc: WebContext) { - - var title = wc.url + if (wc.isEmpty) return + var title = wc.url ?: string(R.string.menu) title = title.substring(title.indexOf("m/") + 1) //just so if defaults to 0 in case it's not .com/ if (title.length > 100) title = title.substring(0, 100) + '\u2026' + val menuItems = WebContextType.values + .filter { it.constraint(wc) } + materialDialogThemed { title(title) - items(WebContextType.values.map { - if (it == WebContextType.COPY_TEXT && wc.text == null) return@map null - this@showWebContextMenu.string(it.textId) - }.filterNotNull()) + items(menuItems.map { string(it.textId) }) itemsCallback { _, _, position, _ -> - WebContextType[position].onClick(this@showWebContextMenu, wc) + menuItems[position].onClick(this@showWebContextMenu, wc) } dismissListener { //showing the dialog interrupts the touch down event, so we must ensure that the viewpager's swipe is enabled @@ -50,18 +49,23 @@ fun Context.showWebContextMenu(wc: WebContext) { } } -class WebContext(val unformattedUrl: String, val text: String?) { - val url = unformattedUrl.formattedFbUrl +class WebContext(val unformattedUrl: String?, val text: String?) { + val url: String? = unformattedUrl?.formattedFbUrl + inline val hasUrl get() = unformattedUrl != null + inline val hasText get() = text != null + inline val isEmpty get() = !hasUrl && !hasText } -enum class WebContextType(val textId: Int, val onClick: (c: Context, wc: WebContext) -> Unit) { - OPEN_LINK(R.string.open_link, { c, wc -> c.launchWebOverlay(wc.unformattedUrl) }), - COPY_LINK(R.string.copy_link, { c, wc -> c.copyToClipboard(wc.url) }), - COPY_TEXT( - R.string.copy_text, - { c, wc -> if (wc.text != null) c.copyToClipboard(wc.text) else c.toast(R.string.no_text) }), - SHARE_LINK(R.string.share_link, { c, wc -> c.shareText(wc.url) }), - DEBUG_LINK(R.string.debug_link, { c, wc -> +enum class WebContextType( + val textId: Int, + val constraint: (wc: WebContext) -> Boolean, + val onClick: (c: Context, wc: WebContext) -> Unit +) { + OPEN_LINK(R.string.open_link, { it.hasUrl }, { c, wc -> c.launchWebOverlay(wc.unformattedUrl!!) }), + COPY_LINK(R.string.copy_link, { it.hasUrl }, { c, wc -> c.copyToClipboard(wc.url) }), + COPY_TEXT(R.string.copy_text, { it.hasText }, { c, wc -> c.copyToClipboard(wc.text) }), + SHARE_LINK(R.string.share_link, { it.hasUrl }, { c, wc -> c.shareText(wc.url) }), + DEBUG_LINK(R.string.debug_link, { it.hasUrl }, { c, wc -> c.materialDialogThemed { title(R.string.debug_link) content(R.string.debug_link_desc) @@ -69,8 +73,8 @@ enum class WebContextType(val textId: Int, val onClick: (c: Context, wc: WebCont onPositive { _, _ -> c.sendFrostEmail(R.string.debug_link_subject) { message = c.string(R.string.debug_link_content) - addItem("Unformatted url", wc.unformattedUrl) - addItem("Formatted url", wc.url) + addItem("Unformatted url", wc.unformattedUrl!!) + addItem("Formatted url", wc.url!!) } } } 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 19d16e87..50a5e2e1 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -76,10 +76,9 @@ class FrostJSI(val web: FrostWebView) { } @JavascriptInterface - fun contextMenu(url: String, text: String?) { - if (!text.isIndependent) return + fun contextMenu(url: String?, text: String?) { //url will be formatted through webcontext - web.post { context.showWebContextMenu(WebContext(url, text)) } + web.post { context.showWebContextMenu(WebContext(url.takeIf { it.isIndependent }, text)) } } /** diff --git a/app/src/web/assets/js/context_a.js b/app/src/web/assets/js/context_a.js index d0f5c622..410553bd 100644 --- a/app/src/web/assets/js/context_a.js +++ b/app/src/web/assets/js/context_a.js @@ -1,6 +1,15 @@ "use strict"; (function () { var longClick = false; + var _frostCopyComment = function (e, target) { + if (!target.hasAttribute('data-commentid')) { + return false; + } + var text = target.innerText; + console.log("Copy comment " + text); + Frost.contextMenu(null, text); + return true; + }; var _frostCopyPost = function (e, target) { if (target.tagName !== 'A') { return false; @@ -55,12 +64,12 @@ Frost.contextMenu(url, text); return true; }; - var handlers = [_frostCopyPost, _frostImage]; + var handlers = [_frostCopyComment, _frostCopyPost, _frostImage]; var _frostAContext = function (e) { Frost.longClick(true); longClick = true; var target = e.target || e.currentTarget || e.srcElement; - if (!(target instanceof Element)) { + if (!(target instanceof HTMLElement)) { console.log("No element found"); return; } diff --git a/app/src/web/assets/js/context_a.ts b/app/src/web/assets/js/context_a.ts index 2a079f39..4751bbdc 100644 --- a/app/src/web/assets/js/context_a.ts +++ b/app/src/web/assets/js/context_a.ts @@ -9,7 +9,17 @@ /** * Given event and target, return true if handled and false otherwise. */ - type EventHandler = (e: Event, target: Element) => Boolean + type EventHandler = (e: Event, target: HTMLElement) => Boolean + + const _frostCopyComment: EventHandler = (e, target) => { + if (!target.hasAttribute('data-commentid')) { + return false; + } + const text = target.innerText; + console.log(`Copy comment ${text}`); + Frost.contextMenu(null, text); + return true; + }; /** * Posts should click a tag, with two parents up being div.story_body_container @@ -26,7 +36,7 @@ if (!parent2 || !parent2.classList.contains('story_body_container')) { return false; } - const url = target.getAttribute('href')!; + const url = target.getAttribute('href'); const text = parent1.innerText; console.log(`Copy post ${url} ${text}`); Frost.contextMenu(url, text); @@ -42,11 +52,11 @@ } } if (element.tagName !== 'A') { - return false + return false; } const url = element.getAttribute('href'); if (!url || url === '#') { - return false + return false; } const text = (element.parentElement).innerText; // Check if image item exists, first in children and then in parent @@ -58,7 +68,7 @@ const imageUrl = (window.getComputedStyle(image, null).backgroundImage).trim().slice(4, -1); console.log(`Context image: ${imageUrl}`); Frost.loadImage(imageUrl, text); - return true + return true; } // Check if true img exists const img = element.querySelector("img[src*=scontent]"); @@ -66,14 +76,14 @@ const imgUrl = img.src; console.log(`Context img: ${imgUrl}`); Frost.loadImage(imgUrl, text); - return true + return true; } console.log(`Context content ${url} ${text}`); Frost.contextMenu(url, text); - return true + return true; }; - const handlers = [_frostCopyPost, _frostImage]; + const handlers = [_frostCopyComment, _frostCopyPost, _frostImage]; const _frostAContext = (e: Event) => { Frost.longClick(true); @@ -83,7 +93,7 @@ * 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 } diff --git a/app/src/web/assets/typings/frost.d.ts b/app/src/web/assets/typings/frost.d.ts index a3591f66..8f60c9dd 100644 --- a/app/src/web/assets/typings/frost.d.ts +++ b/app/src/web/assets/typings/frost.d.ts @@ -5,7 +5,7 @@ declare interface FrostJSI { reloadBaseUrl(animate: boolean) - contextMenu(url: string, text: string | null) + contextMenu(url: string | null, text: string | null) longClick(start: boolean) diff --git a/docs/Changelog.md b/docs/Changelog.md index abf15cd9..09345c5e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -2,6 +2,8 @@ ## v2.2.2 * New marketplace shortcut +* Fix crash when internet disconnects (may still need app restart) +* Improve JS code ## v2.2.1 * Update theme -- cgit v1.2.3