From 965301c079852f9d310145d823628d107e940588 Mon Sep 17 00:00:00 2001 From: brook hong Date: Sat, 13 Jul 2024 09:08:20 +0800 Subject: [PATCH] Fixed #2107 extract a common function to locate focus node for modes insert and visual Create FUNDING.yml Auto enter insert mode only when the real target is drawn. --- .github/FUNDING.yml | 14 ++++++++++++++ src/content_scripts/common/hints.js | 18 +++++++---------- src/content_scripts/common/insert.js | 16 ++------------- src/content_scripts/common/normal.js | 3 ++- src/content_scripts/common/utils.js | 29 ++++++++++++++++++++++++++++ src/content_scripts/common/visual.js | 21 +++----------------- 6 files changed, 57 insertions(+), 44 deletions(-) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..46f27dcb3 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,14 @@ +# These are supported funding model platforms + +github: brookhong +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: # Replace with a single Buy Me a Coffee username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/src/content_scripts/common/hints.js b/src/content_scripts/common/hints.js index 9eee6ddc6..3edf1a284 100644 --- a/src/content_scripts/common/hints.js +++ b/src/content_scripts/common/hints.js @@ -390,20 +390,16 @@ div.hint-scrollable { }; self.genLabels = function(total) { - var ch, hint, hints, i, len, offset; - hints = [""]; - offset = 0; - while (hints.length - offset < total || hints.length === 1) { - hint = hints[offset++]; - for (i = 0, len = characters.length; i < len; i++) { - ch = characters[i]; - hints.push(ch + hint); + let chars = characters.toUpperCase(); + var hints = [""], offset = 0; + while (hints.length - offset < total || offset == 0) { + var prefix = hints[offset++]; + for (var i = 0; i < chars.length; i++) { + hints.push(prefix + chars[i]); } } hints = hints.slice(offset, offset + total); - return hints.map(function(str) { - return str.reverse().toUpperCase(); - }); + return hints }; self.coordinate = function() { diff --git a/src/content_scripts/common/insert.js b/src/content_scripts/common/insert.js index 2aac761c8..e8ae89c56 100644 --- a/src/content_scripts/common/insert.js +++ b/src/content_scripts/common/insert.js @@ -6,6 +6,7 @@ import { createElementWithContent, getRealEdit, isEditable, + locateFocusNode, scrollIntoViewIfNeeded, setSanitizedContent, } from './utils.js'; @@ -39,9 +40,6 @@ function createInsert() { document.getSelection().setPosition(node, node.childNodes.length); } } - // blink cursor to bring cursor into view - Visual.showCursor(); - Visual.hideCursor(); } } } @@ -74,9 +72,6 @@ function createInsert() { // for contenteditable div var selection = document.getSelection(); selection.setPosition(selection.focusNode, 0); - // blink cursor to bring cursor into view - Visual.showCursor(); - Visual.hideCursor(); } } }); @@ -236,14 +231,7 @@ function createInsert() { document.body.append(_emojiDiv); _emojiDiv.style.display = ""; _emojiDiv.querySelector('#sk_emoji>div').classList.add("selected"); - var br; - if (isInput) { - br = getCursorPixelPos(input); - } else { - Visual.showCursor(); - br = Visual.getCursorPixelPos(); - Visual.hideCursor(); - } + var br = isInput ? getCursorPixelPos(input) : locateFocusNode(document.getSelection()); var top = br.top + br.height + 4; if (window.innerHeight - top < _emojiDiv.offsetHeight) { top = br.top - _emojiDiv.offsetHeight; diff --git a/src/content_scripts/common/normal.js b/src/content_scripts/common/normal.js index e685e854b..912ba3658 100644 --- a/src/content_scripts/common/normal.js +++ b/src/content_scripts/common/normal.js @@ -6,6 +6,7 @@ import { getRealEdit, isEditable, isElementClickable, + isElementDrawn, isElementPartiallyInViewport, isInUIFrame, mapInMode, @@ -174,7 +175,7 @@ function createNormal(insert) { var _once = false; self.addEventListener('keydown', function(event) { var realTarget = getRealEdit(event); - if (isEditable(realTarget) && event.isTrusted) { + if (isEditable(realTarget) && isElementDrawn(realTarget) && event.isTrusted) { if (Mode.isSpecialKeyOf("", event.sk_keyName)) { realTarget.blur(); insert.exit(); diff --git a/src/content_scripts/common/utils.js b/src/content_scripts/common/utils.js index 89f48527a..6e4d5631f 100644 --- a/src/content_scripts/common/utils.js +++ b/src/content_scripts/common/utils.js @@ -446,6 +446,33 @@ function getTextRect() { return rects; } +function locateFocusNode(selection) { + let se = selection.focusNode.parentElement + scrollIntoViewIfNeeded(se, true); + var r = getTextRect(selection.focusNode, selection.focusOffset)[0]; + if (!r) { + r = selection.focusNode.getBoundingClientRect(); + } + if (r) { + r = { + left: r.left, + top: r.top, + width: r.width, + height: r.height + }; + if (r.left < 0 || r.left >= window.innerWidth) { + se.scrollLeft += r.left - window.innerWidth / 2; + r.left = window.innerWidth / 2; + } + if (r.top < 0 || r.top >= window.innerHeight) { + se.scrollTop += r.top - window.innerHeight / 2; + r.top = window.innerHeight / 2; + } + return r; + } + return null; +} + function getNearestWord(text, offset) { var ret = [0, text.length]; var nonWord = /\W/; @@ -909,9 +936,11 @@ export { insertJS, isEditable, isElementClickable, + isElementDrawn, isElementPartiallyInViewport, isInUIFrame, listElements, + locateFocusNode, mapInMode, parseAnnotation, refreshHints, diff --git a/src/content_scripts/common/visual.js b/src/content_scripts/common/visual.js index e82116b4c..cebd27d1e 100644 --- a/src/content_scripts/common/visual.js +++ b/src/content_scripts/common/visual.js @@ -12,6 +12,7 @@ import { getTextRect, getVisibleElements, getWordUnderCursor, + locateFocusNode, scrollIntoViewIfNeeded, setSanitizedContent, tabOpenLink, @@ -463,27 +464,11 @@ function createVisual(clipboard, hints) { if (selection.focusNode && (selection.focusNode.offsetHeight > 0 || selection.focusNode.parentNode.offsetHeight > 0)) { // https://developer.mozilla.org/en-US/docs/Web/API/Selection // If focusNode is a text node, this is the number of characters within focusNode preceding the focus. If focusNode is an element, this is the number of child nodes of the focusNode preceding the focus. - scrollIntoViewIfNeeded(selection.focusNode.parentElement, true); - - var r = getTextRect(selection.focusNode, selection.focusOffset)[0]; - if (!r) { - r = selection.focusNode.getBoundingClientRect(); - } + let r = locateFocusNode(selection) if (r) { cursor.style.position = "fixed"; cursor.style.left = r.left + 'px'; - if (r.left < 0 || r.left >= window.innerWidth) { - document.scrollingElement.scrollLeft += r.left - window.innerWidth / 2; - cursor.style.left = window.innerWidth / 2 + 'px'; - } else { - cursor.style.left = r.left + 'px'; - } - if (r.top < 0 || r.top >= window.innerHeight) { - document.scrollingElement.scrollTop += r.top - window.innerHeight / 2; - cursor.style.top = window.innerHeight / 2 + 'px'; - } else { - cursor.style.top = r.top + 'px'; - } + cursor.style.top = r.top + 'px'; cursor.style.height = r.height + 'px'; }