diff options
Diffstat (limited to 'ext/js/settings/profile-controller.js')
| -rw-r--r-- | ext/js/settings/profile-controller.js | 697 | 
1 files changed, 0 insertions, 697 deletions
| diff --git a/ext/js/settings/profile-controller.js b/ext/js/settings/profile-controller.js deleted file mode 100644 index 3883e80a..00000000 --- a/ext/js/settings/profile-controller.js +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (C) 2020-2021  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 - * ProfileConditionsUI - */ - -class ProfileController { -    constructor(settingsController, modalController) { -        this._settingsController = settingsController; -        this._modalController = modalController; -        this._profileConditionsUI = new ProfileConditionsUI(settingsController); -        this._profileConditionsIndex = null; -        this._profileActiveSelect = null; -        this._profileTargetSelect = null; -        this._profileCopySourceSelect = null; -        this._profileNameInput = null; -        this._removeProfileNameElement = null; -        this._profileAddButton = null; -        this._profileRemoveButton = null; -        this._profileRemoveConfirmButton = null; -        this._profileCopyButton = null; -        this._profileCopyConfirmButton = null; -        this._profileMoveUpButton = null; -        this._profileMoveDownButton = null; -        this._profileEntryListContainer = null; -        this._profileConditionsProfileName = null; -        this._profileRemoveModal = null; -        this._profileCopyModal = null; -        this._profileConditionsModal = null; -        this._profileEntriesSupported = false; -        this._profileEntryList = []; -        this._profiles = []; -        this._profileCurrent = 0; -    } - -    get profileCount() { -        return this._profiles.length; -    } - -    get profileCurrentIndex() { -        return this._profileCurrent; -    } - -    async prepare() { -        const {platform: {os}} = await yomichan.api.getEnvironmentInfo(); -        this._profileConditionsUI.os = os; - -        this._profileActiveSelect = document.querySelector('#profile-active-select'); -        this._profileTargetSelect = document.querySelector('#profile-target-select'); -        this._profileCopySourceSelect = document.querySelector('#profile-copy-source-select'); -        this._profileNameInput = document.querySelector('#profile-name-input'); -        this._removeProfileNameElement = document.querySelector('#profile-remove-name'); -        this._profileAddButton = document.querySelector('#profile-add-button'); -        this._profileRemoveButton = document.querySelector('#profile-remove-button'); -        this._profileRemoveConfirmButton = document.querySelector('#profile-remove-confirm-button'); -        this._profileCopyButton = document.querySelector('#profile-copy-button'); -        this._profileCopyConfirmButton = document.querySelector('#profile-copy-confirm-button'); -        this._profileMoveUpButton = document.querySelector('#profile-move-up-button'); -        this._profileMoveDownButton = document.querySelector('#profile-move-down-button'); -        this._profileEntryListContainer = document.querySelector('#profile-entry-list'); -        this._profileConditionsProfileName = document.querySelector('#profile-conditions-profile-name'); -        this._profileRemoveModal = this._modalController.getModal('profile-remove'); -        this._profileCopyModal = this._modalController.getModal('profile-copy'); -        this._profileConditionsModal = this._modalController.getModal('profile-conditions'); - -        this._profileEntriesSupported = (this._profileEntryListContainer !== null); - -        if (this._profileActiveSelect !== null) { this._profileActiveSelect.addEventListener('change', this._onProfileActiveChange.bind(this), false); } -        if (this._profileTargetSelect !== null) { this._profileTargetSelect.addEventListener('change', this._onProfileTargetChange.bind(this), false); } -        if (this._profileNameInput !== null) { this._profileNameInput.addEventListener('change', this._onNameChanged.bind(this), false); } -        if (this._profileAddButton !== null) { this._profileAddButton.addEventListener('click', this._onAdd.bind(this), false); } -        if (this._profileRemoveButton !== null) { this._profileRemoveButton.addEventListener('click', this._onDelete.bind(this), false); } -        if (this._profileRemoveConfirmButton !== null) { this._profileRemoveConfirmButton.addEventListener('click', this._onDeleteConfirm.bind(this), false); } -        if (this._profileCopyButton !== null) { this._profileCopyButton.addEventListener('click', this._onCopy.bind(this), false); } -        if (this._profileCopyConfirmButton !== null) { this._profileCopyConfirmButton.addEventListener('click', this._onCopyConfirm.bind(this), false); } -        if (this._profileMoveUpButton !== null) { this._profileMoveUpButton.addEventListener('click', this._onMove.bind(this, -1), false); } -        if (this._profileMoveDownButton !== null) { this._profileMoveDownButton.addEventListener('click', this._onMove.bind(this, 1), false); } - -        this._profileConditionsUI.on('conditionGroupCountChanged', this._onConditionGroupCountChanged.bind(this)); -        this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this)); -        this._onOptionsChanged(); -    } - -    async moveProfile(profileIndex, offset) { -        if (this._getProfile(profileIndex) === null) { return; } - -        const profileIndexNew = Math.max(0, Math.min(this._profiles.length - 1, profileIndex + offset)); -        if (profileIndex === profileIndexNew) { return; } - -        await this.swapProfiles(profileIndex, profileIndexNew); -    } - -    async setProfileName(profileIndex, value) { -        const profile = this._getProfile(profileIndex); -        if (profile === null) { return; } - -        profile.name = value; -        this._updateSelectName(profileIndex, value); - -        const profileEntry = this._getProfileEntry(profileIndex); -        if (profileEntry !== null) { profileEntry.setName(value); } - -        await this._settingsController.setGlobalSetting(`profiles[${profileIndex}].name`, value); -    } - -    async setDefaultProfile(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (profile === null) { return; } - -        this._profileActiveSelect.value = `${profileIndex}`; -        this._profileCurrent = profileIndex; - -        const profileEntry = this._getProfileEntry(profileIndex); -        if (profileEntry !== null) { profileEntry.setIsDefault(true); } - -        await this._settingsController.setGlobalSetting('profileCurrent', profileIndex); -    } - -    async copyProfile(sourceProfileIndex, destinationProfileIndex) { -        const sourceProfile = this._getProfile(sourceProfileIndex); -        if (sourceProfile === null || !this._getProfile(destinationProfileIndex)) { return; } - -        const options = clone(sourceProfile.options); -        this._profiles[destinationProfileIndex].options = options; - -        this._updateProfileSelectOptions(); - -        const destinationProfileEntry = this._getProfileEntry(destinationProfileIndex); -        if (destinationProfileEntry !== null) { -            destinationProfileEntry.updateState(); -        } - -        await this._settingsController.modifyGlobalSettings([{ -            action: 'set', -            path: `profiles[${destinationProfileIndex}].options`, -            value: options -        }]); - -        await this._settingsController.refresh(); -    } - -    async duplicateProfile(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (this.profile === null) { return; } - -        // Create new profile -        const newProfile = clone(profile); -        newProfile.name = this._createCopyName(profile.name, this._profiles, 100); - -        // Update state -        const index = this._profiles.length; -        this._profiles.push(newProfile); -        if (this._profileEntriesSupported) { -            this._addProfileEntry(index); -        } -        this._updateProfileSelectOptions(); - -        // Modify settings -        await this._settingsController.modifyGlobalSettings([{ -            action: 'splice', -            path: 'profiles', -            start: index, -            deleteCount: 0, -            items: [newProfile] -        }]); - -        // Update profile index -        this._settingsController.profileIndex = index; -    } - -    async deleteProfile(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (profile === null || this.profileCount <= 1) { return; } - -        // Get indices -        let profileCurrentNew = this._profileCurrent; -        const settingsProfileIndex = this._settingsController.profileIndex; - -        // Construct settings modifications -        const modifications = [{ -            action: 'splice', -            path: 'profiles', -            start: profileIndex, -            deleteCount: 1, -            items: [] -        }]; -        if (profileCurrentNew >= profileIndex) { -            profileCurrentNew = Math.min(profileCurrentNew - 1, this._profiles.length - 1); -            modifications.push({ -                action: 'set', -                path: 'profileCurrent', -                value: profileCurrentNew -            }); -        } - -        // Update state -        this._profileCurrent = profileCurrentNew; - -        this._profiles.splice(profileIndex, 1); - -        if (profileIndex < this._profileEntryList.length) { -            const profileEntry = this._profileEntryList[profileIndex]; -            profileEntry.cleanup(); -            this._profileEntryList.splice(profileIndex, 1); - -            for (let i = profileIndex, ii = this._profileEntryList.length; i < ii; ++i) { -                this._profileEntryList[i].index = i; -            } -        } - -        const profileEntry2 = this._getProfileEntry(profileCurrentNew); -        if (profileEntry2 !== null) { -            profileEntry2.setIsDefault(true); -        } - -        this._updateProfileSelectOptions(); - -        // Modify settings -        await this._settingsController.modifyGlobalSettings(modifications); - -        // Update profile index -        if (settingsProfileIndex === profileIndex) { -            this._settingsController.profileIndex = profileCurrentNew; -        } -    } - -    async swapProfiles(index1, index2) { -        const profile1 = this._getProfile(index1); -        const profile2 = this._getProfile(index2); -        if (profile1 === null || profile2 === null || index1 === index2) { return; } - -        // Get swapped indices -        const profileCurrent = this._profileCurrent; -        const profileCurrentNew = this._getSwappedValue(profileCurrent, index1, index2); - -        const settingsProfileIndex = this._settingsController.profileIndex; -        const settingsProfileIndexNew = this._getSwappedValue(settingsProfileIndex, index1, index2); - -        // Construct settings modifications -        const modifications = [{ -            action: 'swap', -            path1: `profiles[${index1}]`, -            path2: `profiles[${index2}]` -        }]; -        if (profileCurrentNew !== profileCurrent) { -            modifications.push({ -                action: 'set', -                path: 'profileCurrent', -                value: profileCurrentNew -            }); -        } - -        // Update state -        this._profileCurrent = profileCurrentNew; - -        this._profiles[index1] = profile2; -        this._profiles[index2] = profile1; - -        const entry1 = this._getProfileEntry(index1); -        const entry2 = this._getProfileEntry(index2); -        if (entry1 !== null && entry2 !== null) { -            entry1.index = index2; -            entry2.index = index1; -            this._swapDomNodes(entry1.node, entry2.node); -            this._profileEntryList[index1] = entry2; -            this._profileEntryList[index2] = entry1; -        } - -        this._updateProfileSelectOptions(); - -        // Modify settings -        await this._settingsController.modifyGlobalSettings(modifications); - -        // Update profile index -        if (settingsProfileIndex !== settingsProfileIndexNew) { -            this._settingsController.profileIndex = settingsProfileIndexNew; -        } -    } - -    openDeleteProfileModal(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (profile === null || this.profileCount <= 1) { return; } - -        this._removeProfileNameElement.textContent = profile.name; -        this._profileRemoveModal.node.dataset.profileIndex = `${profileIndex}`; -        this._profileRemoveModal.setVisible(true); -    } - -    openCopyProfileModal(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (profile === null || this.profileCount <= 1) { return; } - -        let copyFromIndex = this._profileCurrent; -        if (copyFromIndex === profileIndex) { -            if (profileIndex !== 0) { -                copyFromIndex = 0; -            } else if (this.profileCount > 1) { -                copyFromIndex = 1; -            } -        } - -        const profileIndexString = `${profileIndex}`; -        for (const option of this._profileCopySourceSelect.querySelectorAll('option')) { -            const {value} = option; -            option.disabled = (value === profileIndexString); -        } -        this._profileCopySourceSelect.value = `${copyFromIndex}`; - -        this._profileCopyModal.node.dataset.profileIndex = `${profileIndex}`; -        this._profileCopyModal.setVisible(true); -    } - -    openProfileConditionsModal(profileIndex) { -        const profile = this._getProfile(profileIndex); -        if (profile === null) { return; } - -        if (this._profileConditionsModal === null) { return; } -        this._profileConditionsModal.setVisible(true); - -        this._profileConditionsUI.cleanup(); -        this._profileConditionsIndex = profileIndex; -        this._profileConditionsUI.prepare(profileIndex); -        if (this._profileConditionsProfileName !== null) { -            this._profileConditionsProfileName.textContent = profile.name; -        } -    } - -    // Private - -    async _onOptionsChanged() { -        // Update state -        const {profiles, profileCurrent} = await this._settingsController.getOptionsFull(); -        this._profiles = profiles; -        this._profileCurrent = profileCurrent; - -        const settingsProfileIndex = this._settingsController.profileIndex; -        const settingsProfile = this._getProfile(settingsProfileIndex); - -        // Udpate UI -        this._updateProfileSelectOptions(); - -        this._profileActiveSelect.value = `${profileCurrent}`; -        this._profileTargetSelect.value = `${settingsProfileIndex}`; - -        if (this._profileRemoveButton !== null) { this._profileRemoveButton.disabled = (profiles.length <= 1); } -        if (this._profileCopyButton !== null) { this._profileCopyButton.disabled = (profiles.length <= 1); } -        if (this._profileMoveUpButton !== null) { this._profileMoveUpButton.disabled = (settingsProfileIndex <= 0); } -        if (this._profileMoveDownButton !== null) { this._profileMoveDownButton.disabled = (settingsProfileIndex >= profiles.length - 1); } - -        if (this._profileNameInput !== null && settingsProfile !== null) { this._profileNameInput.value = settingsProfile.name; } - -        // Update profile conditions -        this._profileConditionsUI.cleanup(); -        const conditionsProfile = this._getProfile(this._profileConditionsIndex !== null ? this._profileConditionsIndex : settingsProfileIndex); -        if (conditionsProfile !== null) { -            this._profileConditionsUI.prepare(settingsProfileIndex); -        } - -        // Udpate profile entries -        for (const entry of this._profileEntryList) { -            entry.cleanup(); -        } -        this._profileEntryList = []; -        if (this._profileEntriesSupported) { -            for (let i = 0, ii = profiles.length; i < ii; ++i) { -                this._addProfileEntry(i); -            } -        } -    } - -    _onProfileActiveChange(e) { -        const value = this._tryGetValidProfileIndex(e.currentTarget.value); -        if (value === null) { return; } -        this.setDefaultProfile(value); -    } - -    _onProfileTargetChange(e) { -        const value = this._tryGetValidProfileIndex(e.currentTarget.value); -        if (value === null) { return; } -        this._settingsController.profileIndex = value; -    } - -    _onNameChanged(e) { -        this.setProfileName(this._settingsController.profileIndex, e.currentTarget.value); -    } - -    _onAdd() { -        this.duplicateProfile(this._settingsController.profileIndex); -    } - -    _onDelete(e) { -        const profileIndex = this._settingsController.profileIndex; -        if (e.shiftKey) { -            this.deleteProfile(profileIndex); -        } else { -            this.openDeleteProfileModal(profileIndex); -        } -    } - -    _onDeleteConfirm() { -        const modal = this._profileRemoveModal; -        modal.setVisible(false); -        const {node} = modal; -        let profileIndex = node.dataset.profileIndex; -        delete node.dataset.profileIndex; - -        profileIndex = this._tryGetValidProfileIndex(profileIndex); -        if (profileIndex === null) { return; } - -        this.deleteProfile(profileIndex); -    } - -    _onCopy() { -        this.openCopyProfileModal(this._settingsController.profileIndex); -    } - -    _onCopyConfirm() { -        const modal = this._profileCopyModal; -        modal.setVisible(false); -        const {node} = modal; -        let destinationProfileIndex = node.dataset.profileIndex; -        delete node.dataset.profileIndex; - -        destinationProfileIndex = this._tryGetValidProfileIndex(destinationProfileIndex); -        if (destinationProfileIndex === null) { return; } - -        const sourceProfileIndex = this._tryGetValidProfileIndex(this._profileCopySourceSelect.value); -        if (sourceProfileIndex === null) { return; } - -        this.copyProfile(sourceProfileIndex, destinationProfileIndex); -    } - -    _onMove(offset) { -        this.moveProfile(this._settingsController.profileIndex, offset); -    } - -    _onConditionGroupCountChanged({count, profileIndex}) { -        if (profileIndex >= 0 && profileIndex < this._profileEntryList.length) { -            const profileEntry = this._profileEntryList[profileIndex]; -            profileEntry.setConditionGroupsCount(count); -        } -    } - -    _addProfileEntry(profileIndex) { -        const profile = this._profiles[profileIndex]; -        const node = this._settingsController.instantiateTemplate('profile-entry'); -        const entry = new ProfileEntry(this, node); -        this._profileEntryList.push(entry); -        entry.prepare(profile, profileIndex); -        this._profileEntryListContainer.appendChild(node); -    } - -    _updateProfileSelectOptions() { -        for (const select of this._getAllProfileSelects()) { -            const fragment = document.createDocumentFragment(); -            for (let i = 0; i < this._profiles.length; ++i) { -                const profile = this._profiles[i]; -                const option = document.createElement('option'); -                option.value = `${i}`; -                option.textContent = profile.name; -                fragment.appendChild(option); -            } -            select.textContent = ''; -            select.appendChild(fragment); -        } -    } - -    _updateSelectName(index, name) { -        const optionValue = `${index}`; -        for (const select of this._getAllProfileSelects()) { -            for (const option of select.querySelectorAll('option')) { -                if (option.value === optionValue) { -                    option.textContent = name; -                } -            } -        } -    } - -    _getAllProfileSelects() { -        return [ -            this._profileActiveSelect, -            this._profileTargetSelect, -            this._profileCopySourceSelect -        ]; -    } - -    _tryGetValidProfileIndex(stringValue) { -        if (typeof stringValue !== 'string') { return null; } -        const intValue = parseInt(stringValue, 10); -        return ( -            Number.isFinite(intValue) && -            intValue >= 0 && -            intValue < this.profileCount ? -            intValue : null -        ); -    } - -    _createCopyName(name, profiles, maxUniqueAttempts) { -        let space, index, prefix, suffix; -        const match = /^([\w\W]*\(Copy)((\s+)(\d+))?(\)\s*)$/.exec(name); -        if (match === null) { -            prefix = `${name} (Copy`; -            space = ''; -            index = ''; -            suffix = ')'; -        } else { -            prefix = match[1]; -            suffix = match[5]; -            if (typeof match[2] === 'string') { -                space = match[3]; -                index = parseInt(match[4], 10) + 1; -            } else { -                space = ' '; -                index = 2; -            } -        } - -        let i = 0; -        while (true) { -            const newName = `${prefix}${space}${index}${suffix}`; -            if (i++ >= maxUniqueAttempts || profiles.findIndex((profile) => profile.name === newName) < 0) { -                return newName; -            } -            if (typeof index !== 'number') { -                index = 2; -                space = ' '; -            } else { -                ++index; -            } -        } -    } - -    _getSwappedValue(currentValue, value1, value2) { -        if (currentValue === value1) { return value2; } -        if (currentValue === value2) { return value1; } -        return currentValue; -    } - -    _getProfile(profileIndex) { -        return (profileIndex >= 0 && profileIndex < this._profiles.length ? this._profiles[profileIndex] : null); -    } - -    _getProfileEntry(profileIndex) { -        return (profileIndex >= 0 && profileIndex < this._profileEntryList.length ? this._profileEntryList[profileIndex] : null); -    } - -    _swapDomNodes(node1, node2) { -        const parent1 = node1.parentNode; -        const parent2 = node2.parentNode; -        const next1 = node1.nextSibling; -        const next2 = node2.nextSibling; -        if (node2 !== next1) { parent1.insertBefore(node2, next1); } -        if (node1 !== next2) { parent2.insertBefore(node1, next2); } -    } -} - -class ProfileEntry { -    constructor(profileController, node) { -        this._profileController = profileController; -        this._node = node; -        this._profile = null; -        this._index = 0; -        this._isDefaultRadio = null; -        this._nameInput = null; -        this._countLink = null; -        this._countText = null; -        this._menuButton = null; -        this._eventListeners = new EventListenerCollection(); -    } - -    get index() { -        return this._index; -    } - -    set index(value) { -        this._index = value; -    } - -    get node() { -        return this._node; -    } - -    prepare(profile, index) { -        this._profile = profile; -        this._index = index; - -        const node = this._node; -        this._isDefaultRadio = node.querySelector('.profile-entry-is-default-radio'); -        this._nameInput = node.querySelector('.profile-entry-name-input'); -        this._countLink = node.querySelector('.profile-entry-condition-count-link'); -        this._countText = node.querySelector('.profile-entry-condition-count'); -        this._menuButton = node.querySelector('.profile-entry-menu-button'); - -        this.updateState(); - -        this._eventListeners.addEventListener(this._isDefaultRadio, 'change', this._onIsDefaultRadioChange.bind(this), false); -        this._eventListeners.addEventListener(this._nameInput, 'input', this._onNameInputInput.bind(this), false); -        this._eventListeners.addEventListener(this._countLink, 'click', this._onConditionsCountLinkClick.bind(this), false); -        this._eventListeners.addEventListener(this._menuButton, 'menuOpen', this._onMenuOpen.bind(this), false); -        this._eventListeners.addEventListener(this._menuButton, 'menuClose', this._onMenuClose.bind(this), false); -    } - -    cleanup() { -        this._eventListeners.removeAllEventListeners(); -        if (this._node.parentNode !== null) { -            this._node.parentNode.removeChild(this._node); -        } -    } - -    setName(value) { -        if (this._nameInput.value === value) { return; } -        this._nameInput.value = value; -    } - -    setIsDefault(value) { -        this._isDefaultRadio.checked = value; -    } - -    updateState() { -        this._nameInput.value = this._profile.name; -        this._countText.textContent = `${this._profile.conditionGroups.length}`; -        this._isDefaultRadio.checked = (this._index === this._profileController.profileCurrentIndex); -    } - -    setConditionGroupsCount(count) { -        this._countText.textContent = `${count}`; -    } - -    // Private - -    _onIsDefaultRadioChange(e) { -        if (!e.currentTarget.checked) { return; } -        this._profileController.setDefaultProfile(this._index); -    } - -    _onNameInputInput(e) { -        const name = e.currentTarget.value; -        this._profileController.setProfileName(this._index, name); -    } - -    _onConditionsCountLinkClick() { -        this._profileController.openProfileConditionsModal(this._index); -    } - -    _onMenuOpen(e) { -        const bodyNode = e.detail.menu.bodyNode; -        const count = this._profileController.profileCount; -        this._setMenuActionEnabled(bodyNode, 'moveUp', this._index > 0); -        this._setMenuActionEnabled(bodyNode, 'moveDown', this._index < count - 1); -        this._setMenuActionEnabled(bodyNode, 'copyFrom', count > 1); -        this._setMenuActionEnabled(bodyNode, 'delete', count > 1); -    } - -    _onMenuClose(e) { -        switch (e.detail.action) { -            case 'moveUp': -                this._profileController.moveProfile(this._index, -1); -                break; -            case 'moveDown': -                this._profileController.moveProfile(this._index, 1); -                break; -            case 'copyFrom': -                this._profileController.openCopyProfileModal(this._index); -                break; -            case 'editConditions': -                this._profileController.openProfileConditionsModal(this._index); -                break; -            case 'duplicate': -                this._profileController.duplicateProfile(this._index); -                break; -            case 'delete': -                this._profileController.openDeleteProfileModal(this._index); -                break; -        } -    } - -    _setMenuActionEnabled(menu, action, enabled) { -        const element = menu.querySelector(`[data-menu-action="${action}"]`); -        if (element === null) { return; } -        element.disabled = !enabled; -    } -} |