diff options
| -rw-r--r-- | ext/js/pages/settings/audio-controller.js | 180 | 
1 files changed, 103 insertions, 77 deletions
| diff --git a/ext/js/pages/settings/audio-controller.js b/ext/js/pages/settings/audio-controller.js index dcc5428e..2581893c 100644 --- a/ext/js/pages/settings/audio-controller.js +++ b/ext/js/pages/settings/audio-controller.js @@ -30,6 +30,14 @@ class AudioController {          this._ttsVoiceTestTextInput = null;      } +    get settingsController() { +        return this._settingsController; +    } + +    get modalController() { +        return this._modalController; +    } +      async prepare() {          this._audioSystem.prepare(); @@ -51,18 +59,41 @@ class AudioController {          this._onOptionsChanged({options});      } +    async removeSource(entry) { +        const {index} = entry; +        this._audioSourceEntries.splice(index, 1); +        entry.cleanup(); +        for (let i = index, ii = this._audioSourceEntries.length; i < ii; ++i) { +            this._audioSourceEntries[i].index = i; +        } + +        await this._settingsController.modifyProfileSettings([{ +            action: 'splice', +            path: 'audio.sources', +            start: index, +            deleteCount: 1, +            items: [] +        }]); +    } +      // Private      _onOptionsChanged({options}) { -        for (let i = this._audioSourceEntries.length - 1; i >= 0; --i) { -            this._cleanupAudioSourceEntry(i); +        for (const entry of this._audioSourceEntries) { +            entry.cleanup();          } +        this._audioSourceEntries = []; -        for (const audioSource of options.audio.sources) { -            this._createAudioSourceEntry(audioSource); +        const {sources} = options.audio; +        for (let i = 0, ii = sources.length; i < ii; ++i) { +            this._createAudioSourceEntry(i, sources[i]);          }      } +    _onAddAudioSource() { +        this._addAudioSource(); +    } +      _onTestTextToSpeech() {          try {              const text = this._ttsVoiceTestTextInput.value || ''; @@ -132,103 +163,93 @@ class AudioController {          );      } -    _getUnusedAudioSource() { -        const audioSourcesAvailable = [ +    _createAudioSourceEntry(index, type) { +        const node = this._settingsController.instantiateTemplate('audio-source'); +        const entry = new AudioSourceEntry(this, index, type, node); +        this._audioSourceEntries.push(entry); +        this._audioSourceContainer.appendChild(node); +        entry.prepare(); +    } + +    _getUnusedAudioSourceType() { +        const typesAvailable = [              'jpod101',              'jpod101-alternate',              'jisho',              'custom'          ]; -        for (const source of audioSourcesAvailable) { -            if (!this._audioSourceEntries.some((metadata) => metadata.value === source)) { -                return source; +        for (const type of typesAvailable) { +            if (!this._audioSourceEntries.some((entry) => entry.type === type)) { +                return type;              }          } -        return audioSourcesAvailable[0]; -    } - -    _createAudioSourceEntry(value) { -        const eventListeners = new EventListenerCollection(); -        const container = this._settingsController.instantiateTemplate('audio-source'); -        const select = container.querySelector('.audio-source-select'); -        const removeButton = container.querySelector('.audio-source-remove'); -        const menuButton = container.querySelector('.audio-source-menu-button'); - -        select.value = value; - -        const entry = { -            container, -            eventListeners, -            value -        }; - -        eventListeners.addEventListener(select, 'change', this._onAudioSourceSelectChange.bind(this, entry), false); -        if (removeButton !== null) { -            eventListeners.addEventListener(removeButton, 'click', this._onAudioSourceRemoveClicked.bind(this, entry), false); -        } -        if (menuButton !== null) { -            eventListeners.addEventListener(menuButton, 'menuOpen', this._onMenuOpen.bind(this, entry), false); -            eventListeners.addEventListener(menuButton, 'menuClose', this._onMenuClose.bind(this, entry), false); -        } - -        this._audioSourceContainer.appendChild(container); -        this._audioSourceEntries.push(entry); +        return typesAvailable[0];      } -    async _removeAudioSourceEntry(entry) { -        const index = this._audioSourceEntries.indexOf(entry); -        if (index < 0) { return; } - -        this._cleanupAudioSourceEntry(index); +    async _addAudioSource() { +        const type = this._getUnusedAudioSourceType(); +        const index = this._audioSourceEntries.length; +        this._createAudioSourceEntry(index, type);          await this._settingsController.modifyProfileSettings([{              action: 'splice',              path: 'audio.sources',              start: index, -            deleteCount: 1, -            items: [] +            deleteCount: 0, +            items: [type]          }]);      } +} -    _cleanupAudioSourceEntry(index) { -        const {container, eventListeners} = this._audioSourceEntries[index]; -        if (container.parentNode !== null) { -            container.parentNode.removeChild(container); -        } -        eventListeners.removeAllEventListeners(); -        this._audioSourceEntries.splice(index, 1); +class AudioSourceEntry { +    constructor(parent, index, type, node) { +        this._parent = parent; +        this._index = index; +        this._type = type; +        this._node = node; +        this._eventListeners = new EventListenerCollection();      } -    async _onAddAudioSource() { -        const audioSource = this._getUnusedAudioSource(); -        const index = this._audioSourceEntries.length; -        this._createAudioSourceEntry(audioSource); -        await this._settingsController.modifyProfileSettings([{ -            action: 'splice', -            path: 'audio.sources', -            start: index, -            deleteCount: 0, -            items: [audioSource] -        }]); +    get index() { +        return this._index; +    } + +    set index(value) { +        this._index = value;      } -    async _onAudioSourceSelectChange(entry, event) { -        const index = this._audioSourceEntries.indexOf(entry); -        if (index < 0) { return; } +    get type() { +        return this._type; +    } + +    prepare() { +        const select = this._node.querySelector('.audio-source-select'); +        const menuButton = this._node.querySelector('.audio-source-menu-button'); + +        select.value = this._type; -        const value = event.currentTarget.value; -        entry.value = value; -        await this._settingsController.setProfileSetting(`audio.sources[${index}]`, value); +        this._eventListeners.addEventListener(select, 'change', this._onAudioSourceSelectChange.bind(this), false); +        this._eventListeners.addEventListener(menuButton, 'menuOpen', this._onMenuOpen.bind(this), false); +        this._eventListeners.addEventListener(menuButton, 'menuClose', this._onMenuClose.bind(this), false);      } -    _onAudioSourceRemoveClicked(entry) { -        this._removeAudioSourceEntry(entry); +    cleanup() { +        if (this._node.parentNode !== null) { +            this._node.parentNode.removeChild(this._node); +        } +        this._eventListeners.removeAllEventListeners();      } -    _onMenuOpen(entry, e) { +    // Private + +    _onAudioSourceSelectChange(event) { +        this._setType(event.currentTarget.value); +    } + +    _onMenuOpen(e) {          const {menu} = e.detail;          let hasHelp = false; -        switch (entry.value) { +        switch (this._type) {              case 'custom':              case 'custom-json':                  hasHelp = true; @@ -238,17 +259,22 @@ class AudioController {          menu.bodyNode.querySelector('.popup-menu-item[data-menu-action=help]').hidden = !hasHelp;      } -    _onMenuClose(entry, e) { +    _onMenuClose(e) {          switch (e.detail.action) {              case 'help': -                this._showHelp(entry.value); +                this._showHelp(this._type);                  break;              case 'remove': -                this._removeAudioSourceEntry(entry); +                this._parent.removeSource(this);                  break;          }      } +    async _setType(value) { +        this._type = value; +        await this._parent.settingsController.setProfileSetting(`audio.sources[${this._index}]`, value); +    } +      _showHelp(type) {          switch (type) {              case 'custom': @@ -261,6 +287,6 @@ class AudioController {      }      _showModal(name) { -        this._modalController.getModal(name).setVisible(true); +        this._parent.modalController.getModal(name).setVisible(true);      }  } |