From 49c75c3093734b90e25674ae2fa8a3886bb299fc Mon Sep 17 00:00:00 2001
From: oakkitten <oakkitten@users.noreply.github.com>
Date: Fri, 1 Jul 2022 22:12:55 +0100
Subject: Do not change selection if user selected text manually (#2186)

* Do not change selection if user selected text manually

* Remove capture argument for selectionchange listener

It is not applicable

* Make a note of user selection when Yomichan is enabled

User might have some text selected on a page prior to enabling Yomichan
via the toolbar icon; let it stay intact.

* Extract selection change by user listener into a method
---
 ext/js/language/text-scanner.js | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index 9c4a7267..1ef92115 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -87,6 +87,9 @@ class TextScanner extends EventDispatcher {
         this._pointerIdTypeMap = new Map();
 
         this._canClearSelection = true;
+
+        this._yomichanIsChangingTextSelectionNow = false;
+        this._userHasNotSelectedAnythingManually = true;
     }
 
     get canClearSelection() {
@@ -141,6 +144,7 @@ class TextScanner extends EventDispatcher {
 
         if (value) {
             this._hookEvents();
+            this._userHasNotSelectedAnythingManually = window.getSelection().isCollapsed;
         }
     }
 
@@ -259,8 +263,10 @@ class TextScanner extends EventDispatcher {
 
     setCurrentTextSource(textSource) {
         this._textSourceCurrent = textSource;
-        if (this._selectText) {
+        if (this._selectText && this._userHasNotSelectedAnythingManually) {
+            this._yomichanIsChangingTextSelectionNow = true;
             this._textSourceCurrent.select();
+            setTimeout(() => this._yomichanIsChangingTextSelectionNow = false, 0);
             this._textSourceCurrentSelected = true;
         } else {
             this._textSourceCurrentSelected = false;
@@ -371,6 +377,11 @@ class TextScanner extends EventDispatcher {
         this._preventNextClickScan = true;
     }
 
+    _onSelectionChangeCheckUserSelection() {
+        if (this._yomichanIsChangingTextSelectionNow) { return; }
+        this._userHasNotSelectedAnythingManually = window.getSelection().isCollapsed;
+    }
+
     _onSearchClickMouseDown(e) {
         if (e.button !== 0) { return; }
         this._resetPreventNextClickScan();
@@ -754,6 +765,8 @@ class TextScanner extends EventDispatcher {
             eventListenerInfos.push(...this._getMouseClickOnlyEventListeners2(capture));
         }
 
+        eventListenerInfos.push(this._getSelectionChangeCheckUserSelectionListener());
+
         for (const args of eventListenerInfos) {
             this._eventListeners.addEventListener(...args);
         }
@@ -815,6 +828,10 @@ class TextScanner extends EventDispatcher {
         return entries;
     }
 
+    _getSelectionChangeCheckUserSelectionListener() {
+        return [document, 'selectionchange', this._onSelectionChangeCheckUserSelection.bind(this)];
+    }
+
     _getTouch(touchList, identifier) {
         for (const touch of touchList) {
             if (touch.identifier === identifier) {
-- 
cgit v1.2.3