diff --git a/ext/data/schemas/options-schema.json b/ext/data/schemas/options-schema.json index bee1a5cfe..75f2b2405 100644 --- a/ext/data/schemas/options-schema.json +++ b/ext/data/schemas/options-schema.json @@ -499,7 +499,8 @@ "scanOnPenPress": true, "scanOnPenRelease": false, "preventTouchScrolling": false, - "preventPenScrolling": false + "preventPenScrolling": false, + "minimumTouchTime": 0 } }, { @@ -524,7 +525,8 @@ "scanOnPenPress": true, "scanOnPenRelease": false, "preventTouchScrolling": true, - "preventPenScrolling": true + "preventPenScrolling": true, + "minimumTouchTime": 0 } } ], @@ -583,7 +585,8 @@ "scanOnPenPress", "scanOnPenRelease", "preventTouchScrolling", - "preventPenScrolling" + "preventPenScrolling", + "minimumTouchTime" ], "properties": { "showAdvanced": { @@ -641,6 +644,10 @@ "preventPenScrolling": { "type": "boolean", "default": true + }, + "minimumTouchTime": { + "type": "number", + "default": 0 } } } diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index 1329d9dc7..3d3c8b52c 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -568,6 +568,7 @@ export class OptionsUtil { this._updateVersion54, this._updateVersion55, this._updateVersion56, + this._updateVersion57, ]; /* eslint-enable @typescript-eslint/unbound-method */ if (typeof targetVersion === 'number' && targetVersion < result.length) { @@ -642,6 +643,7 @@ export class OptionsUtil { scanOnPenPress: true, scanOnPenRelease: false, preventTouchScrolling: true, + minimumTouchTime: 0, }); for (const {options: profileOptions} of options.profiles) { profileOptions.general.usePopupWindow = false; @@ -1539,6 +1541,18 @@ export class OptionsUtil { } } + /** + * - Added scanning.inputs[].options.minimumTouchTime. + * @type {import('options-util').UpdateFunction} + */ + async _updateVersion57(options) { + for (const profile of options.profiles) { + for (const input of profile.options.scanning.inputs) { + input.options.minimumTouchTime = 0; + } + } + } + /** * @param {string} url * @returns {Promise} diff --git a/ext/js/display/display.js b/ext/js/display/display.js index a933cf86b..790f8600a 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -2069,6 +2069,7 @@ export class Display extends EventDispatcher { scanOnPenRelease: false, preventTouchScrolling: false, preventPenScrolling: false, + minimumTouchTime: 0, }, }], deepContentScan: scanningOptions.deepDomScan, diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index 13ee0d356..08789b163 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -144,6 +144,8 @@ export class TextScanner extends EventDispatcher { /** @type {boolean} */ this._touchTapValid = false; + /** @type {number} */ + this._touchPressTime = 0; /** @type {?number} */ this._primaryTouchIdentifier = null; /** @type {boolean} */ @@ -723,6 +725,7 @@ export class TextScanner extends EventDispatcher { this._preventNextMouseDown = false; this._preventNextClick = false; this._touchTapValid = true; + this._touchPressTime = Date.now(); const languageNotNull = this._language !== null ? this._language : ''; const selection = window.getSelection(); @@ -760,6 +763,7 @@ export class TextScanner extends EventDispatcher { * @param {boolean} allowSearch */ _onPrimaryTouchEnd(e, x, y, allowSearch) { + const touchReleaseTime = Date.now(); this._primaryTouchIdentifier = null; this._preventScroll = false; this._preventNextClick = false; @@ -770,6 +774,7 @@ export class TextScanner extends EventDispatcher { const inputInfo = this._getMatchingInputGroupFromEvent('touch', 'touchEnd', e); if (inputInfo === null || inputInfo.input === null) { return; } + if (touchReleaseTime - this._touchPressTime < inputInfo.input.minimumTouchTime) { return; } if (inputInfo.input.scanOnTouchRelease || (inputInfo.input.scanOnTouchTap && this._touchTapValid)) { void this._searchAtFromTouchEnd(x, y, inputInfo); } @@ -1493,6 +1498,7 @@ export class TextScanner extends EventDispatcher { scanOnPenRelease: this._getInputBoolean(options.scanOnPenRelease), preventTouchScrolling: this._getInputBoolean(options.preventTouchScrolling), preventPenScrolling: this._getInputBoolean(options.preventPenScrolling), + minimumTouchTime: this._getInputNumber(options.minimumTouchTime), }; } @@ -1528,6 +1534,14 @@ export class TextScanner extends EventDispatcher { return typeof value === 'boolean' && value; } + /** + * @param {unknown} value + * @returns {number} + */ + _getInputNumber(value) { + return typeof value === 'number' ? value : -1; + } + /** * @param {PointerEvent} e * @returns {string} diff --git a/ext/js/pages/settings/scan-inputs-controller.js b/ext/js/pages/settings/scan-inputs-controller.js index cfd5cc7ce..229e5814b 100644 --- a/ext/js/pages/settings/scan-inputs-controller.js +++ b/ext/js/pages/settings/scan-inputs-controller.js @@ -219,6 +219,7 @@ export class ScanInputsController { scanOnPenRelease: false, preventTouchScrolling: true, preventPenScrolling: true, + minimumTouchTime: 0, }, }; } @@ -392,6 +393,10 @@ class ScanInputField { const {property} = typeCheckbox.dataset; typeCheckbox.dataset.setting = `scanning.inputs[${index}].${property}`; } + for (const typeInput of /** @type {NodeListOf} */ (this._node.querySelectorAll('.scan-input-settings-input'))) { + const {property} = typeInput.dataset; + typeInput.dataset.setting = `scanning.inputs[${index}].${property}`; + } } /** */ diff --git a/ext/templates-settings.html b/ext/templates-settings.html index 82e47d8d3..3a47c7a01 100644 --- a/ext/templates-settings.html +++ b/ext/templates-settings.html @@ -238,6 +238,10 @@ Prevent touch scrolling +
Pen options:
diff --git a/test/options-util.test.js b/test/options-util.test.js index 28ea2f43f..48fb2bce3 100644 --- a/test/options-util.test.js +++ b/test/options-util.test.js @@ -387,6 +387,7 @@ function createProfileOptionsUpdatedTestData1() { scanOnPenRelease: false, preventTouchScrolling: true, preventPenScrolling: true, + minimumTouchTime: 0, }, }, { @@ -412,6 +413,7 @@ function createProfileOptionsUpdatedTestData1() { scanOnPenRelease: false, preventTouchScrolling: true, preventPenScrolling: true, + minimumTouchTime: 0, }, }, { @@ -437,6 +439,7 @@ function createProfileOptionsUpdatedTestData1() { scanOnPenRelease: false, preventTouchScrolling: true, preventPenScrolling: true, + minimumTouchTime: 0, }, }, ], @@ -669,7 +672,7 @@ function createOptionsUpdatedTestData1() { }, ], profileCurrent: 0, - version: 56, + version: 57, global: { database: { prefixWildcardsSupported: false, diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts index 12c883e09..f95e93bfa 100644 --- a/types/ext/settings.d.ts +++ b/types/ext/settings.d.ts @@ -228,6 +228,7 @@ export type ScanningInputOptions = { scanOnPenRelease: boolean; preventTouchScrolling: boolean; preventPenScrolling: boolean; + minimumTouchTime: number; }; export type ScanningPreventMiddleMouseOptions = { diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts index e9c5bb9d4..862be66c7 100644 --- a/types/ext/text-scanner.d.ts +++ b/types/ext/text-scanner.d.ts @@ -68,6 +68,7 @@ export type InputOptions = { scanOnPenRelease: boolean; preventTouchScrolling: boolean; preventPenScrolling: boolean; + minimumTouchTime: number; }; export type SentenceParsingOptions = { @@ -93,6 +94,7 @@ export type InputConfig = { scanOnPenRelease: boolean; preventTouchScrolling: boolean; preventPenScrolling: boolean; + minimumTouchTime: number; }; export type InputInfo = {