diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2020-09-09 16:59:03 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-09-09 16:59:03 -0400 | 
| commit | 0d00f7e1cf8a0fa1e2b1aa2732bceaae39f4e23c (patch) | |
| tree | 92b0a2e72ef2cecb31e8cc70da354ee43b87e2b4 /ext/bg/js | |
| parent | acb7ad32f39c40b879400c9daa4bc8cd25585ba7 (diff) | |
Scanning input generalization (#789)
* Add inputs to options.scanning
* Update CSS for mouse buttons
* Update list counters
* Set up HTML/CSS
* Add input controller
* Use new inputs
* Include mouse buttons
* Update how button inputs are detected
* Add index/empty fields to the input details object
* Update none check for scanning modifier
* Remove old settings
* Remove unused global
Diffstat (limited to 'ext/bg/js')
| -rw-r--r-- | ext/bg/js/options.js | 19 | ||||
| -rw-r--r-- | ext/bg/js/settings/keyboard-mouse-input-field.js | 2 | ||||
| -rw-r--r-- | ext/bg/js/settings/main.js | 23 | ||||
| -rw-r--r-- | ext/bg/js/settings/profile-conditions-ui.js | 2 | ||||
| -rw-r--r-- | ext/bg/js/settings/scan-inputs-controller.js | 178 | 
5 files changed, 203 insertions, 21 deletions
| diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 398fb95c..ab32bb11 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -474,6 +474,7 @@ class OptionsUtil {          //  Added usePopupWindow.          //  Updated handlebars templates to include "clipboard-image" definition.          //  Added hideDelay. +        //  Added inputs to profileOptions.scanning.          for (const {conditionGroups} of options.profiles) {              for (const {conditions} of conditionGroups) {                  for (const condition of conditions) { @@ -489,6 +490,24 @@ class OptionsUtil {          for (const {options: profileOptions} of options.profiles) {              profileOptions.general.usePopupWindow = false;              profileOptions.scanning.hideDelay = 0; + +            const {modifier, middleMouse} = profileOptions.scanning; +            const scanningInputs = []; +            switch (modifier) { +                case 'alt': +                case 'ctrl': +                case 'shift': +                case 'meta': +                    scanningInputs.push(modifier); +                    break; +                case 'none': +                    scanningInputs.push(''); +                    break; +            } +            if (middleMouse) { +                scanningInputs.push('mouse2'); +            } +            profileOptions.scanning.inputs = scanningInputs;          }          await this._addFieldTemplatesToOptions(options, '/bg/data/anki-field-templates-upgrade-v4.handlebars');          return options; diff --git a/ext/bg/js/settings/keyboard-mouse-input-field.js b/ext/bg/js/settings/keyboard-mouse-input-field.js index b1530c1b..4ba0d3ed 100644 --- a/ext/bg/js/settings/keyboard-mouse-input-field.js +++ b/ext/bg/js/settings/keyboard-mouse-input-field.js @@ -172,7 +172,7 @@ class KeyboardMouseInputField extends EventDispatcher {      _onMouseButtonMouseDown(e) {          e.preventDefault(); -        this._addInputs([`mouse${e.button}`]); +        this._addInputs(DocumentUtil.getActiveButtons(e));      }      _onMouseButtonMouseUp(e) { diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js index 7fa8e502..4932586b 100644 --- a/ext/bg/js/settings/main.js +++ b/ext/bg/js/settings/main.js @@ -22,10 +22,10 @@   * ClipboardPopupsController   * DictionaryController   * DictionaryImportController - * DocumentUtil   * GenericSettingController   * PopupPreviewController   * ProfileController + * ScanInputsController   * SettingsBackup   * SettingsController   * StorageController @@ -40,23 +40,6 @@ function showExtensionInformation() {      node.textContent = `${manifest.name} v${manifest.version}`;  } -async function settingsPopulateModifierKeys() { -    const scanModifierKeySelect = document.querySelector('#scan-modifier-key'); -    scanModifierKeySelect.textContent = ''; - -    const {platform: {os}} = await api.getEnvironmentInfo(); -    const modifierKeys = [ -        ['none', 'None'], -        ...DocumentUtil.getModifierKeys(os) -    ]; -    for (const [value, name] of modifierKeys) { -        const option = document.createElement('option'); -        option.value = value; -        option.textContent = name; -        scanModifierKeySelect.appendChild(option); -    } -} -  async function setupEnvironmentInfo() {      const {browser, platform} = await api.getEnvironmentInfo();      document.documentElement.dataset.browser = browser; @@ -71,7 +54,6 @@ async function setupEnvironmentInfo() {          setupEnvironmentInfo();          showExtensionInformation(); -        settingsPopulateModifierKeys();          const optionsFull = await api.optionsGetFull(); @@ -111,6 +93,9 @@ async function setupEnvironmentInfo() {          const settingsBackup = new SettingsBackup(settingsController);          settingsBackup.prepare(); +        const scanInputsController = new ScanInputsController(settingsController); +        scanInputsController.prepare(); +          yomichan.ready();      } catch (e) {          yomichan.logError(e); diff --git a/ext/bg/js/settings/profile-conditions-ui.js b/ext/bg/js/settings/profile-conditions-ui.js index d88f932b..419c35b3 100644 --- a/ext/bg/js/settings/profile-conditions-ui.js +++ b/ext/bg/js/settings/profile-conditions-ui.js @@ -441,7 +441,7 @@ class ProfileConditionUI {          this._operatorOptionContainer = this._operatorInput.querySelector('optgroup');          this._valueInput = this._node.querySelector('.condition-input-inner');          this._removeButton = this._node.querySelector('.condition-remove'); -        this._mouseButton = this._node.querySelector('.condition-mouse-button'); +        this._mouseButton = this._node.querySelector('.mouse-button');          const operatorDetails = this._getOperatorDetails(type, operator);          this._updateTypes(type); diff --git a/ext/bg/js/settings/scan-inputs-controller.js b/ext/bg/js/settings/scan-inputs-controller.js new file mode 100644 index 00000000..3b3945ff --- /dev/null +++ b/ext/bg/js/settings/scan-inputs-controller.js @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2020  Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +/* global + * KeyboardMouseInputField + * api + */ + +class ScanInputsController { +    constructor(settingsController) { +        this._settingsController = settingsController; +        this._os = null; +        this._container = null; +        this._addButton = null; +        this._entries = []; +    } + +    async prepare() { +        const {platform: {os}} = await api.getEnvironmentInfo(); +        this._os = os; + +        this._container = document.querySelector('#scan-input-list'); +        this._addButton = document.querySelector('#scan-input-add'); + +        this._addButton.addEventListener('click', this._onAddButtonClick.bind(this), false); +        this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this)); + +        const options = await this._settingsController.getOptions(); +        this._onOptionsChanged({options}); +    } + +    removeInput(index) { +        if (index < 0 || index >= this._entries.length) { return false; } +        const input = this._entries[index]; +        input.cleanup(); +        this._entries.splice(index, 1); +        for (let i = index, ii = this._entries.length; i < ii; ++i) { +            this._entries[i].index = i; +        } +        this._settingsController.modifyProfileSettings([{ +            action: 'splice', +            path: 'scanning.inputs', +            start: index, +            deleteCount: 1, +            items: [] +        }]); +    } + +    setProperty(index, property, value) { +        const path = `scanning.inputs[${index}].${property}`; +        this._settingsController.setProfileSetting(path, value); +    } + +    // Private + +    _onOptionsChanged({options}) { +        const {inputs} = options.scanning; + +        for (let i = this._entries.length - 1; i >= 0; --i) { +            this._entries[i].cleanup(); +        } +        this._entries.length = 0; + +        for (let i = 0, ii = inputs.length; i < ii; ++i) { +            const {include, exclude} = inputs[i]; +            this._addOption(i, include, exclude); +        } +    } + +    _onAddButtonClick(e) { +        e.preventDefault(); + +        const index = this._entries.length; +        const include = ''; +        const exclude = ''; +        this._addOption(index, include, exclude); +        this._settingsController.modifyProfileSettings([{ +            action: 'splice', +            path: 'scanning.inputs', +            start: index, +            deleteCount: 0, +            items: [{include, exclude}] +        }]); +    } + +    _addOption(index, include, exclude) { +        const field = new ScanInputField(this, index, this._os); +        this._entries.push(field); +        field.prepare(this._container, include, exclude); +    } +} + +class ScanInputField { +    constructor(parent, index, os) { +        this._parent = parent; +        this._index = index; +        this._os = os; +        this._node = null; +        this._includeInputField = null; +        this._excludeInputField = null; +        this._eventListeners = new EventListenerCollection(); +    } + +    get index() { +        return this._index; +    } + +    set index(value) { +        this._index = value; +    } + +    prepare(container, include, exclude) { +        const node = this._instantiateTemplate('#scan-input-template'); +        const includeInputNode = node.querySelector('.scan-input-include .scan-input-field'); +        const includeMouseButton = node.querySelector('.scan-input-include .mouse-button'); +        const excludeInputNode = node.querySelector('.scan-input-exclude .scan-input-field'); +        const excludeMouseButton = node.querySelector('.scan-input-exclude .mouse-button'); +        const removeButton = node.querySelector('.scan-input-remove'); + +        this._node = node; +        container.appendChild(node); + +        this._includeInputField = new KeyboardMouseInputField(includeInputNode, includeMouseButton, this._os); +        this._excludeInputField = new KeyboardMouseInputField(excludeInputNode, excludeMouseButton, this._os); +        this._includeInputField.prepare(include, 'modifierInputs'); +        this._excludeInputField.prepare(exclude, 'modifierInputs'); + +        this._eventListeners.on(this._includeInputField, 'change', this._onIncludeValueChange.bind(this)); +        this._eventListeners.on(this._excludeInputField, 'change', this._onExcludeValueChange.bind(this)); +        this._eventListeners.addEventListener(removeButton, 'click', this._onRemoveClick.bind(this)); +    } + +    cleanup() { +        this._eventListeners.removeAllEventListeners(); +        if (this._includeInputField !== null) { +            this._includeInputField.cleanup(); +            this._includeInputField = null; +        } +        if (this._node !== null) { +            const parent = this._node.parentNode; +            if (parent !== null) { parent.removeChild(this._node); } +            this._node = null; +        } +    } + +    _onIncludeValueChange({value}) { +        this._parent.setProperty(this._index, 'include', value); +    } + +    _onExcludeValueChange({value}) { +        this._parent.setProperty(this._index, 'exclude', value); +    } + +    _onRemoveClick(e) { +        e.preventDefault(); +        this._parent.removeInput(this._index); +    } + +    _instantiateTemplate(templateSelector) { +        const template = document.querySelector(templateSelector); +        const content = document.importNode(template.content, true); +        return content.firstChild; +    } +} |