diff options
Diffstat (limited to 'ext/js/pages/settings/settings-controller.js')
-rw-r--r-- | ext/js/pages/settings/settings-controller.js | 172 |
1 files changed, 148 insertions, 24 deletions
diff --git a/ext/js/pages/settings/settings-controller.js b/ext/js/pages/settings/settings-controller.js index 83ccdb39..1b46c745 100644 --- a/ext/js/pages/settings/settings-controller.js +++ b/ext/js/pages/settings/settings-controller.js @@ -22,21 +22,33 @@ import {PermissionsUtil} from '../../data/permissions-util.js'; import {HtmlTemplateCollection} from '../../dom/html-template-collection.js'; import {yomitan} from '../../yomitan.js'; +/** + * @augments EventDispatcher<import('settings-controller').EventType> + */ export class SettingsController extends EventDispatcher { constructor() { super(); + /** @type {number} */ this._profileIndex = 0; + /** @type {string} */ this._source = generateId(16); + /** @type {Set<import('settings-controller').PageExitPrevention>} */ this._pageExitPreventions = new Set(); + /** @type {EventListenerCollection} */ this._pageExitPreventionEventListeners = new EventListenerCollection(); - this._templates = new HtmlTemplateCollection(document); + /** @type {HtmlTemplateCollection} */ + this._templates = new HtmlTemplateCollection(); + this._templates.load(document); + /** @type {PermissionsUtil} */ this._permissionsUtil = new PermissionsUtil(); } + /** @type {string} */ get source() { return this._source; } + /** @type {number} */ get profileIndex() { return this._profileIndex; } @@ -46,10 +58,12 @@ export class SettingsController extends EventDispatcher { this._setProfileIndex(value, true); } + /** @type {PermissionsUtil} */ get permissionsUtil() { return this._permissionsUtil; } + /** */ async prepare() { yomitan.on('optionsUpdated', this._onOptionsUpdated.bind(this)); if (this._canObservePermissionsChanges()) { @@ -63,67 +77,121 @@ export class SettingsController extends EventDispatcher { } } + /** */ async refresh() { await this._onOptionsUpdatedInternal(true); } + /** + * @returns {Promise<import('settings').ProfileOptions>} + */ async getOptions() { const optionsContext = this.getOptionsContext(); return await yomitan.api.optionsGet(optionsContext); } + /** + * @returns {Promise<import('settings').Options>} + */ async getOptionsFull() { return await yomitan.api.optionsGetFull(); } + /** + * @param {import('settings').Options} value + */ async setAllSettings(value) { const profileIndex = value.profileCurrent; await yomitan.api.setAllSettings(value, this._source); this._setProfileIndex(profileIndex, true); } + /** + * @param {import('settings-modifications').ScopedRead[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async getSettings(targets) { - return await this._getSettings(targets, {}); + return await this._getSettings(targets, null); } + /** + * @param {import('settings-modifications').Read[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async getGlobalSettings(targets) { - return await this._getSettings(targets, {scope: 'global'}); + return await this._getSettings(targets, {scope: 'global', optionsContext: null}); } + /** + * @param {import('settings-modifications').Read[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async getProfileSettings(targets) { - return await this._getSettings(targets, {scope: 'profile'}); + return await this._getSettings(targets, {scope: 'profile', optionsContext: null}); } + /** + * @param {import('settings-modifications').ScopedModification[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async modifySettings(targets) { - return await this._modifySettings(targets, {}); + return await this._modifySettings(targets, null); } + /** + * @param {import('settings-modifications').Modification[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async modifyGlobalSettings(targets) { - return await this._modifySettings(targets, {scope: 'global'}); + return await this._modifySettings(targets, {scope: 'global', optionsContext: null}); } + /** + * @param {import('settings-modifications').Modification[]} targets + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async modifyProfileSettings(targets) { - return await this._modifySettings(targets, {scope: 'profile'}); + return await this._modifySettings(targets, {scope: 'profile', optionsContext: null}); } + /** + * @param {string} path + * @param {unknown} value + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async setGlobalSetting(path, value) { return await this.modifyGlobalSettings([{action: 'set', path, value}]); } + /** + * @param {string} path + * @param {unknown} value + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async setProfileSetting(path, value) { return await this.modifyProfileSettings([{action: 'set', path, value}]); } + /** + * @returns {Promise<import('dictionary-importer').Summary[]>} + */ async getDictionaryInfo() { return await yomitan.api.getDictionaryInfo(); } + /** + * @returns {import('settings').OptionsContext} + */ getOptionsContext() { return {index: this._profileIndex}; } + /** + * @returns {import('settings-controller').PageExitPrevention} + */ preventPageExit() { - const obj = {end: null}; + /** @type {import('settings-controller').PageExitPrevention} */ + const obj = {}; obj.end = this._endPreventPageExit.bind(this, obj); if (this._pageExitPreventionEventListeners.size === 0) { this._pageExitPreventionEventListeners.addEventListener(window, 'beforeunload', this._onBeforeUnload.bind(this), false); @@ -132,14 +200,25 @@ export class SettingsController extends EventDispatcher { return obj; } + /** + * @param {string} name + * @returns {Element} + */ instantiateTemplate(name) { return this._templates.instantiate(name); } + /** + * @param {string} name + * @returns {DocumentFragment} + */ instantiateTemplateFragment(name) { return this._templates.instantiateFragment(name); } + /** + * @returns {Promise<import('settings').Options>} + */ async getDefaultOptions() { const optionsUtil = new OptionsUtil(); await optionsUtil.prepare(); @@ -149,22 +228,34 @@ export class SettingsController extends EventDispatcher { // Private + /** + * @param {number} value + * @param {boolean} canUpdateProfileIndex + */ _setProfileIndex(value, canUpdateProfileIndex) { this._profileIndex = value; this.trigger('optionsContextChanged'); this._onOptionsUpdatedInternal(canUpdateProfileIndex); } + /** + * @param {{source: string}} details + */ _onOptionsUpdated({source}) { if (source === this._source) { return; } this._onOptionsUpdatedInternal(true); } + /** + * @param {boolean} canUpdateProfileIndex + */ async _onOptionsUpdatedInternal(canUpdateProfileIndex) { const optionsContext = this.getOptionsContext(); try { const options = await this.getOptions(); - this.trigger('optionsChanged', {options, optionsContext}); + /** @type {import('settings-controller').OptionsChangedEvent} */ + const event = {options, optionsContext}; + this.trigger('optionsChanged', event); } catch (e) { if (canUpdateProfileIndex) { this._setProfileIndex(0, false); @@ -174,26 +265,49 @@ export class SettingsController extends EventDispatcher { } } - _setupTargets(targets, extraFields) { - return targets.map((target) => { - target = Object.assign({}, extraFields, target); - if (target.scope === 'profile') { - target.optionsContext = this.getOptionsContext(); - } - return target; - }); + /** + * @param {import('settings-modifications').OptionsScope} target + */ + _modifyOptionsScope(target) { + if (target.scope === 'profile') { + target.optionsContext = this.getOptionsContext(); + } } + /** + * @template {boolean} THasScope + * @param {import('settings-controller').SettingsRead<THasScope>[]} targets + * @param {import('settings-controller').SettingsExtraFields<THasScope>} extraFields + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async _getSettings(targets, extraFields) { - targets = this._setupTargets(targets, extraFields); - return await yomitan.api.getSettings(targets); + const targets2 = targets.map((target) => { + const target2 = /** @type {import('settings-controller').SettingsRead<true>} */ (Object.assign({}, extraFields, target)); + this._modifyOptionsScope(target2); + return target2; + }); + return await yomitan.api.getSettings(targets2); } + /** + * @template {boolean} THasScope + * @param {import('settings-controller').SettingsModification<THasScope>[]} targets + * @param {import('settings-controller').SettingsExtraFields<THasScope>} extraFields + * @returns {Promise<import('settings-controller').ModifyResult[]>} + */ async _modifySettings(targets, extraFields) { - targets = this._setupTargets(targets, extraFields); - return await yomitan.api.modifySettings(targets, this._source); + const targets2 = targets.map((target) => { + const target2 = /** @type {import('settings-controller').SettingsModification<true>} */ (Object.assign({}, extraFields, target)); + this._modifyOptionsScope(target2); + return target2; + }); + return await yomitan.api.modifySettings(targets2, this._source); } + /** + * @param {BeforeUnloadEvent} e + * @returns {string|undefined} + */ _onBeforeUnload(e) { if (this._pageExitPreventions.size === 0) { return; @@ -204,6 +318,9 @@ export class SettingsController extends EventDispatcher { return ''; } + /** + * @param {import('settings-controller').PageExitPrevention} obj + */ _endPreventPageExit(obj) { this._pageExitPreventions.delete(obj); if (this._pageExitPreventions.size === 0) { @@ -211,18 +328,25 @@ export class SettingsController extends EventDispatcher { } } + /** */ _onPermissionsChanged() { this._triggerPermissionsChanged(); } + /** */ async _triggerPermissionsChanged() { - const event = 'permissionsChanged'; - if (!this.hasListeners(event)) { return; } + const eventName = 'permissionsChanged'; + if (!this.hasListeners(eventName)) { return; } const permissions = await this._permissionsUtil.getAllPermissions(); - this.trigger(event, {permissions}); + /** @type {import('settings-controller').PermissionsChangedEvent} */ + const event = {permissions}; + this.trigger(eventName, event); } + /** + * @returns {boolean} + */ _canObservePermissionsChanges() { return isObject(chrome.permissions) && isObject(chrome.permissions.onAdded) && isObject(chrome.permissions.onRemoved); } |