diff options
Diffstat (limited to 'ext')
25 files changed, 399 insertions, 427 deletions
diff --git a/ext/bg/js/context-main.js b/ext/bg/js/context-main.js index dbba0272..e90e7e2e 100644 --- a/ext/bg/js/context-main.js +++ b/ext/bg/js/context-main.js @@ -16,11 +16,7 @@ */ /* global - * apiCommandExec - * apiForwardLogsToBackend - * apiGetEnvironmentInfo - * apiLogIndicatorClear - * apiOptionsGet + * api */ function showExtensionInfo() { @@ -36,12 +32,12 @@ function setupButtonEvents(selector, command, url) { for (const node of nodes) { node.addEventListener('click', (e) => { if (e.button !== 0) { return; } - apiCommandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'}); + api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'}); e.preventDefault(); }, false); node.addEventListener('auxclick', (e) => { if (e.button !== 1) { return; } - apiCommandExec(command, {mode: 'newTab'}); + api.commandExec(command, {mode: 'newTab'}); e.preventDefault(); }, false); @@ -54,14 +50,14 @@ function setupButtonEvents(selector, command, url) { } async function mainInner() { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); await yomichan.prepare(); - await apiLogIndicatorClear(); + await api.logIndicatorClear(); showExtensionInfo(); - apiGetEnvironmentInfo().then(({browser}) => { + api.getEnvironmentInfo().then(({browser}) => { // Firefox mobile opens this page as a full webpage. document.documentElement.dataset.mode = (browser === 'firefox-mobile' ? 'full' : 'mini'); }); @@ -76,14 +72,14 @@ async function mainInner() { depth: 0, url: window.location.href }; - apiOptionsGet(optionsContext).then((options) => { + api.optionsGet(optionsContext).then((options) => { const toggle = document.querySelector('#enable-search'); toggle.checked = options.general.enable; - toggle.addEventListener('change', () => apiCommandExec('toggle'), false); + toggle.addEventListener('change', () => api.commandExec('toggle'), false); const toggle2 = document.querySelector('#enable-search2'); toggle2.checked = options.general.enable; - toggle2.addEventListener('change', () => apiCommandExec('toggle'), false); + toggle2.addEventListener('change', () => api.commandExec('toggle'), false); setTimeout(() => { for (const n of document.querySelectorAll('.toggle-group')) { diff --git a/ext/bg/js/search-main.js b/ext/bg/js/search-main.js index 54fa549d..3e089594 100644 --- a/ext/bg/js/search-main.js +++ b/ext/bg/js/search-main.js @@ -17,8 +17,7 @@ /* global * DisplaySearch - * apiForwardLogsToBackend - * apiOptionsGet + * api * dynamicLoader */ @@ -35,7 +34,7 @@ async function injectSearchFrontend() { } (async () => { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); await yomichan.prepare(); const displaySearch = new DisplaySearch(); @@ -45,7 +44,7 @@ async function injectSearchFrontend() { const applyOptions = async () => { const optionsContext = {depth: 0, url: window.location.href}; - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); if (!options.scanning.enableOnSearchPage || optionsApplied) { return; } optionsApplied = true; diff --git a/ext/bg/js/search-query-parser-generator.js b/ext/bg/js/search-query-parser-generator.js index 9e7ff8aa..6989e157 100644 --- a/ext/bg/js/search-query-parser-generator.js +++ b/ext/bg/js/search-query-parser-generator.js @@ -17,7 +17,7 @@ /* global * TemplateHandler - * apiGetQueryParserTemplatesHtml + * api */ class QueryParserGenerator { @@ -26,7 +26,7 @@ class QueryParserGenerator { } async prepare() { - const html = await apiGetQueryParserTemplatesHtml(); + const html = await api.getQueryParserTemplatesHtml(); this._templateHandler = new TemplateHandler(html); } diff --git a/ext/bg/js/search-query-parser.js b/ext/bg/js/search-query-parser.js index e1e37d1c..addfc686 100644 --- a/ext/bg/js/search-query-parser.js +++ b/ext/bg/js/search-query-parser.js @@ -18,9 +18,7 @@ /* global * QueryParserGenerator * TextScanner - * apiModifySettings - * apiTermsFind - * apiTextParse + * api * docSentenceExtract */ @@ -59,7 +57,7 @@ class QueryParser { this._setPreview(text); - this._parseResults = await apiTextParse(text, this._getOptionsContext()); + this._parseResults = await api.textParse(text, this._getOptionsContext()); this._refreshSelectedParser(); this._renderParserSelect(); @@ -80,7 +78,7 @@ class QueryParser { const searchText = this._textScanner.getTextSourceContent(textSource, this._options.scanning.length); if (searchText.length === 0) { return null; } - const {definitions, length} = await apiTermsFind(searchText, {}, this._getOptionsContext()); + const {definitions, length} = await api.termsFind(searchText, {}, this._getOptionsContext()); if (definitions.length === 0) { return null; } const sentence = docSentenceExtract(textSource, this._options.anki.sentenceExt); @@ -99,7 +97,7 @@ class QueryParser { _onParserChange(e) { const value = e.target.value; - apiModifySettings([{ + api.modifySettings([{ action: 'set', path: 'parsing.selectedParser', value, @@ -112,7 +110,7 @@ class QueryParser { if (this._parseResults.length > 0) { if (!this._getParseResult()) { const value = this._parseResults[0].id; - apiModifySettings([{ + api.modifySettings([{ action: 'set', path: 'parsing.selectedParser', value, diff --git a/ext/bg/js/search.js b/ext/bg/js/search.js index 96e8a70b..75707e6c 100644 --- a/ext/bg/js/search.js +++ b/ext/bg/js/search.js @@ -20,9 +20,7 @@ * DOM * Display * QueryParser - * apiClipboardGet - * apiModifySettings - * apiTermsFind + * api * wanakana */ @@ -52,7 +50,7 @@ class DisplaySearch extends Display { this.introVisible = true; this.introAnimationTimer = null; - this.clipboardMonitor = new ClipboardMonitor({getClipboard: apiClipboardGet}); + this.clipboardMonitor = new ClipboardMonitor({getClipboard: api.clipboardGet.bind(api)}); this._onKeyDownIgnoreKeys = new Map([ ['ANY_MOD', new Set([ @@ -234,7 +232,7 @@ class DisplaySearch extends Display { this.setIntroVisible(!valid, animate); this.updateSearchButton(); if (valid) { - const {definitions} = await apiTermsFind(query, details, this.getOptionsContext()); + const {definitions} = await api.termsFind(query, details, this.getOptionsContext()); this.setContent('terms', {definitions, context: { focus: false, disableHistory: true, @@ -258,7 +256,7 @@ class DisplaySearch extends Display { } else { wanakana.unbind(this.query); } - apiModifySettings([{ + api.modifySettings([{ action: 'set', path: 'general.enableWanakana', value, @@ -274,7 +272,7 @@ class DisplaySearch extends Display { (granted) => { if (granted) { this.clipboardMonitor.start(); - apiModifySettings([{ + api.modifySettings([{ action: 'set', path: 'general.enableClipboardMonitor', value: true, @@ -288,7 +286,7 @@ class DisplaySearch extends Display { ); } else { this.clipboardMonitor.stop(); - apiModifySettings([{ + api.modifySettings([{ action: 'set', path: 'general.enableClipboardMonitor', value: false, diff --git a/ext/bg/js/settings/anki-templates.js b/ext/bg/js/settings/anki-templates.js index d5b6e677..0dadb433 100644 --- a/ext/bg/js/settings/anki-templates.js +++ b/ext/bg/js/settings/anki-templates.js @@ -19,10 +19,7 @@ * AnkiNoteBuilder * ankiGetFieldMarkers * ankiGetFieldMarkersHtml - * apiGetDefaultAnkiFieldTemplates - * apiOptionsGet - * apiTemplateRender - * apiTermsFind + * api * getOptionsContext * getOptionsMutable * settingsSaveOptions @@ -38,7 +35,7 @@ async function onAnkiFieldTemplatesResetConfirm(e) { $('#field-template-reset-modal').modal('hide'); - const value = await apiGetDefaultAnkiFieldTemplates(); + const value = await api.getDefaultAnkiFieldTemplates(); const element = document.querySelector('#field-templates'); element.value = value; @@ -65,9 +62,9 @@ function ankiTemplatesInitialize() { async function ankiTemplatesUpdateValue() { const optionsContext = getOptionsContext(); - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); let templates = options.anki.fieldTemplates; - if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); } + if (typeof templates !== 'string') { templates = await api.getDefaultAnkiFieldTemplates(); } $('#field-templates').val(templates); onAnkiTemplatesValidateCompile(); @@ -79,7 +76,7 @@ const ankiTemplatesValidateGetDefinition = (() => { return async (text, optionsContext) => { if (cachedText !== text) { - const {definitions} = await apiTermsFind(text, {}, optionsContext); + const {definitions} = await api.termsFind(text, {}, optionsContext); if (definitions.length === 0) { return null; } cachedValue = definitions[0]; @@ -97,15 +94,15 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i const optionsContext = getOptionsContext(); const definition = await ankiTemplatesValidateGetDefinition(text, optionsContext); if (definition !== null) { - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); const context = { document: { title: document.title } }; let templates = options.anki.fieldTemplates; - if (typeof templates !== 'string') { templates = await apiGetDefaultAnkiFieldTemplates(); } - const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: apiTemplateRender}); + if (typeof templates !== 'string') { templates = await api.getDefaultAnkiFieldTemplates(); } + const ankiNoteBuilder = new AnkiNoteBuilder({renderTemplate: api.templateRender.bind(api)}); result = await ankiNoteBuilder.formatField(field, definition, mode, context, options, templates, exceptions); } } catch (e) { @@ -125,7 +122,7 @@ async function ankiTemplatesValidate(infoNode, field, mode, showSuccessResult, i async function onAnkiFieldTemplatesChanged(e) { // Get value let templates = e.currentTarget.value; - if (templates === await apiGetDefaultAnkiFieldTemplates()) { + if (templates === await api.getDefaultAnkiFieldTemplates()) { // Default templates = null; } diff --git a/ext/bg/js/settings/anki.js b/ext/bg/js/settings/anki.js index ff1277ed..ba83f994 100644 --- a/ext/bg/js/settings/anki.js +++ b/ext/bg/js/settings/anki.js @@ -16,9 +16,7 @@ */ /* global - * apiGetAnkiDeckNames - * apiGetAnkiModelFieldNames - * apiGetAnkiModelNames + * api * getOptionsContext * getOptionsMutable * onFormOptionsChanged @@ -107,7 +105,7 @@ async function _ankiDeckAndModelPopulate(options) { const kanjiModel = {value: options.anki.kanji.model, selector: '#anki-kanji-model'}; try { _ankiSpinnerShow(true); - const [deckNames, modelNames] = await Promise.all([apiGetAnkiDeckNames(), apiGetAnkiModelNames()]); + const [deckNames, modelNames] = await Promise.all([api.getAnkiDeckNames(), api.getAnkiModelNames()]); deckNames.sort(); modelNames.sort(); termsDeck.values = deckNames; @@ -180,7 +178,7 @@ async function _onAnkiModelChanged(e) { let fieldNames; try { const modelName = node.value; - fieldNames = await apiGetAnkiModelFieldNames(modelName); + fieldNames = await api.getAnkiModelFieldNames(modelName); _ankiSetError(null); } catch (error) { _ankiSetError(error); diff --git a/ext/bg/js/settings/backup.js b/ext/bg/js/settings/backup.js index faf4e592..5eb55502 100644 --- a/ext/bg/js/settings/backup.js +++ b/ext/bg/js/settings/backup.js @@ -16,9 +16,7 @@ */ /* global - * apiGetDefaultAnkiFieldTemplates - * apiGetEnvironmentInfo - * apiOptionsGetFull + * api * optionsGetDefault * optionsUpdateVersion * utilBackend @@ -51,9 +49,9 @@ function _getSettingsExportDateString(date, dateSeparator, dateTimeSeparator, ti } async function _getSettingsExportData(date) { - const optionsFull = await apiOptionsGetFull(); - const environment = await apiGetEnvironmentInfo(); - const fieldTemplatesDefault = await apiGetDefaultAnkiFieldTemplates(); + const optionsFull = await api.optionsGetFull(); + const environment = await api.getEnvironmentInfo(); + const fieldTemplatesDefault = await api.getDefaultAnkiFieldTemplates(); // Format options for (const {options} of optionsFull.profiles) { diff --git a/ext/bg/js/settings/dictionaries.js b/ext/bg/js/settings/dictionaries.js index 632c01ea..4d307f0f 100644 --- a/ext/bg/js/settings/dictionaries.js +++ b/ext/bg/js/settings/dictionaries.js @@ -17,13 +17,7 @@ /* global * PageExitPrevention - * apiDeleteDictionary - * apiGetDictionaryCounts - * apiGetDictionaryInfo - * apiImportDictionaryArchive - * apiOptionsGet - * apiOptionsGetFull - * apiPurgeDatabase + * api * getOptionsContext * getOptionsFullMutable * getOptionsMutable @@ -312,7 +306,7 @@ class SettingsDictionaryEntryUI { progressBar.style.width = `${percent}%`; }; - await apiDeleteDictionary(this.dictionaryInfo.title, onProgress); + await api.deleteDictionary(this.dictionaryInfo.title, onProgress); } catch (e) { dictionaryErrorsShow([e]); } finally { @@ -423,7 +417,7 @@ async function onDictionaryOptionsChanged() { dictionaryUI.setOptionsDictionaries(options.dictionaries); - const optionsFull = await apiOptionsGetFull(); + const optionsFull = await api.optionsGetFull(); document.querySelector('#database-enable-prefix-wildcard-searches').checked = optionsFull.global.database.prefixWildcardsSupported; await updateMainDictionarySelectValue(); @@ -431,7 +425,7 @@ async function onDictionaryOptionsChanged() { async function onDatabaseUpdated() { try { - const dictionaries = await apiGetDictionaryInfo(); + const dictionaries = await api.getDictionaryInfo(); dictionaryUI.setDictionaries(dictionaries); document.querySelector('#dict-warning').hidden = (dictionaries.length > 0); @@ -439,7 +433,7 @@ async function onDatabaseUpdated() { updateMainDictionarySelectOptions(dictionaries); await updateMainDictionarySelectValue(); - const {counts, total} = await apiGetDictionaryCounts(dictionaries.map((v) => v.title), true); + const {counts, total} = await api.getDictionaryCounts(dictionaries.map((v) => v.title), true); dictionaryUI.setCounts(counts, total); } catch (e) { dictionaryErrorsShow([e]); @@ -468,7 +462,7 @@ function updateMainDictionarySelectOptions(dictionaries) { async function updateMainDictionarySelectValue() { const optionsContext = getOptionsContext(); - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); const value = options.general.mainDictionary; @@ -618,7 +612,7 @@ async function onDictionaryPurge(e) { dictionaryErrorsShow(null); dictionarySpinnerShow(true); - await apiPurgeDatabase(); + await api.purgeDatabase(); for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { options.dictionaries = utilBackgroundIsolate({}); options.general.mainDictionary = ''; @@ -666,7 +660,7 @@ async function onDictionaryImport(e) { } }; - const optionsFull = await apiOptionsGetFull(); + const optionsFull = await api.optionsGetFull(); const importDetails = { prefixWildcardsSupported: optionsFull.global.database.prefixWildcardsSupported @@ -680,7 +674,7 @@ async function onDictionaryImport(e) { } const archiveContent = await dictReadFile(files[i]); - const {result, errors} = await apiImportDictionaryArchive(archiveContent, importDetails, updateProgress); + const {result, errors} = await api.importDictionaryArchive(archiveContent, importDetails, updateProgress); for (const {options} of toIterable((await getOptionsFullMutable()).profiles)) { const dictionaryOptions = SettingsDictionaryListUI.createDictionaryOptions(); dictionaryOptions.enabled = true; diff --git a/ext/bg/js/settings/main.js b/ext/bg/js/settings/main.js index 61395b1c..94f7f8f5 100644 --- a/ext/bg/js/settings/main.js +++ b/ext/bg/js/settings/main.js @@ -21,9 +21,7 @@ * ankiInitialize * ankiTemplatesInitialize * ankiTemplatesUpdateValue - * apiForwardLogsToBackend - * apiGetEnvironmentInfo - * apiOptionsSave + * api * appearanceInitialize * audioSettingsInitialize * backupInitialize @@ -265,7 +263,7 @@ function settingsGetSource() { async function settingsSaveOptions() { const source = await settingsGetSource(); - await apiOptionsSave(source); + await api.optionsSave(source); } async function onOptionsUpdated({source}) { @@ -290,7 +288,7 @@ async function settingsPopulateModifierKeys() { const scanModifierKeySelect = document.querySelector('#scan-modifier-key'); scanModifierKeySelect.textContent = ''; - const environment = await apiGetEnvironmentInfo(); + const environment = await api.getEnvironmentInfo(); const modifierKeys = [ {value: 'none', name: 'None'}, ...environment.modifiers.keys @@ -305,7 +303,7 @@ async function settingsPopulateModifierKeys() { async function onReady() { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); await yomichan.prepare(); showExtensionInformation(); diff --git a/ext/bg/js/settings/popup-preview-frame-main.js b/ext/bg/js/settings/popup-preview-frame-main.js index 8228125f..a362efa5 100644 --- a/ext/bg/js/settings/popup-preview-frame-main.js +++ b/ext/bg/js/settings/popup-preview-frame-main.js @@ -17,10 +17,10 @@ /* global * SettingsPopupPreview - * apiForwardLogsToBackend + * api */ (() => { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); new SettingsPopupPreview(); })(); diff --git a/ext/bg/js/settings/popup-preview-frame.js b/ext/bg/js/settings/popup-preview-frame.js index 8901a0c4..bd9357e9 100644 --- a/ext/bg/js/settings/popup-preview-frame.js +++ b/ext/bg/js/settings/popup-preview-frame.js @@ -20,14 +20,13 @@ * Popup * PopupFactory * TextSourceRange - * apiFrameInformationGet - * apiOptionsGet + * api */ class SettingsPopupPreview { constructor() { this.frontend = null; - this.apiOptionsGetOld = apiOptionsGet; + this.apiOptionsGetOld = api.optionsGet.bind(api); this.popup = null; this.popupSetCustomOuterCssOld = null; this.popupShown = false; @@ -54,10 +53,10 @@ class SettingsPopupPreview { document.querySelector('#theme-dark-checkbox').addEventListener('change', this.onThemeDarkCheckboxChanged.bind(this), false); // Overwrite API functions - window.apiOptionsGet = this.apiOptionsGet.bind(this); + api.optionsGet = this.apiOptionsGet.bind(this); // Overwrite frontend - const {frameId} = await apiFrameInformationGet(); + const {frameId} = await api.frameInformationGet(); const popupFactory = new PopupFactory(frameId); await popupFactory.prepare(); diff --git a/ext/bg/js/settings/profiles.js b/ext/bg/js/settings/profiles.js index bdf5a13d..e32d5525 100644 --- a/ext/bg/js/settings/profiles.js +++ b/ext/bg/js/settings/profiles.js @@ -17,7 +17,7 @@ /* global * ConditionsUI - * apiOptionsGetFull + * api * conditionsClearCaches * formWrite * getOptionsFullMutable @@ -215,7 +215,7 @@ async function onProfileRemove(e) { return await onProfileRemoveConfirm(); } - const optionsFull = await apiOptionsGetFull(); + const optionsFull = await api.optionsGetFull(); if (optionsFull.profiles.length <= 1) { return; } @@ -278,7 +278,7 @@ async function onProfileMove(offset) { } async function onProfileCopy() { - const optionsFull = await apiOptionsGetFull(); + const optionsFull = await api.optionsGetFull(); if (optionsFull.profiles.length <= 1) { return; } diff --git a/ext/bg/js/settings/storage.js b/ext/bg/js/settings/storage.js index d754a109..73c93fa1 100644 --- a/ext/bg/js/settings/storage.js +++ b/ext/bg/js/settings/storage.js @@ -16,7 +16,7 @@ */ /* global - * apiGetEnvironmentInfo + * api */ function storageBytesToLabeledString(size) { @@ -52,7 +52,7 @@ async function isStoragePeristent() { async function storageInfoInitialize() { storagePersistInitialize(); - const {browser, platform} = await apiGetEnvironmentInfo(); + const {browser, platform} = await api.getEnvironmentInfo(); document.documentElement.dataset.browser = browser; document.documentElement.dataset.operatingSystem = platform.os; diff --git a/ext/fg/js/content-script-main.js b/ext/fg/js/content-script-main.js index 57386b85..b057ae3d 100644 --- a/ext/fg/js/content-script-main.js +++ b/ext/fg/js/content-script-main.js @@ -21,10 +21,7 @@ * Frontend * PopupFactory * PopupProxy - * apiBroadcastTab - * apiForwardLogsToBackend - * apiFrameInformationGet - * apiOptionsGet + * api */ async function createIframePopupProxy(frameOffsetForwarder, setDisabled) { @@ -36,7 +33,7 @@ async function createIframePopupProxy(frameOffsetForwarder, setDisabled) { } } ); - apiBroadcastTab('rootPopupRequestInformationBroadcast'); + api.broadcastTab('rootPopupRequestInformationBroadcast'); const {popupId, frameId: parentFrameId} = await rootPopupInformationPromise; const getFrameOffset = frameOffsetForwarder.getOffset.bind(frameOffsetForwarder); @@ -48,7 +45,7 @@ async function createIframePopupProxy(frameOffsetForwarder, setDisabled) { } async function getOrCreatePopup(depth) { - const {frameId} = await apiFrameInformationGet(); + const {frameId} = await api.frameInformationGet(); if (typeof frameId !== 'number') { const error = new Error('Failed to get frameId'); yomichan.logError(error); @@ -71,7 +68,7 @@ async function createPopupProxy(depth, id, parentFrameId) { } (async () => { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); await yomichan.prepare(); const data = window.frontendInitializationData || {}; @@ -112,7 +109,7 @@ async function createPopupProxy(depth, id, parentFrameId) { depth: isSearchPage ? 0 : depth, url: proxy ? await getPopupProxyUrl() : window.location.href }; - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); if (!proxy && frameOffsetForwarder === null) { frameOffsetForwarder = new FrameOffsetForwarder(); diff --git a/ext/fg/js/float-main.js b/ext/fg/js/float-main.js index 20771910..249b4dbe 100644 --- a/ext/fg/js/float-main.js +++ b/ext/fg/js/float-main.js @@ -17,8 +17,7 @@ /* global * DisplayFloat - * apiForwardLogsToBackend - * apiOptionsGet + * api * dynamicLoader */ @@ -38,7 +37,7 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) { const applyOptions = async () => { const optionsContext = {depth, url}; - const options = await apiOptionsGet(optionsContext); + const options = await api.optionsGet(optionsContext); const maxPopupDepthExceeded = !(typeof depth === 'number' && depth < options.scanning.popupNestingMaxDepth); if (maxPopupDepthExceeded || optionsApplied) { return; } @@ -55,7 +54,7 @@ async function popupNestedInitialize(id, depth, parentFrameId, url) { } (async () => { - apiForwardLogsToBackend(); + api.forwardLogsToBackend(); const display = new DisplayFloat(); await display.prepare(); })(); diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 845bf7f6..12d27a9f 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -17,8 +17,7 @@ /* global * Display - * apiBroadcastTab - * apiSendMessageToFrame + * api * popupNestedInitialize */ @@ -61,7 +60,7 @@ class DisplayFloat extends Display { yomichan.on('orphaned', this.onOrphaned.bind(this)); window.addEventListener('message', this.onMessage.bind(this), false); - apiBroadcastTab('popupPrepared', {secret: this._secret}); + api.broadcastTab('popupPrepared', {secret: this._secret}); } onError(error) { @@ -153,7 +152,7 @@ class DisplayFloat extends Display { }, 2000 ); - apiBroadcastTab('requestDocumentInformationBroadcast', {uniqueId}); + api.broadcastTab('requestDocumentInformationBroadcast', {uniqueId}); const {title} = await promise; return title; @@ -176,7 +175,7 @@ class DisplayFloat extends Display { const {token, frameId} = params; this._token = token; - apiSendMessageToFrame(frameId, 'popupInitialized', {secret, token}); + api.sendMessageToFrame(frameId, 'popupInitialized', {secret, token}); } async _configure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) { @@ -192,7 +191,7 @@ class DisplayFloat extends Display { this.setContentScale(scale); - apiSendMessageToFrame(frameId, 'popupConfigured', {messageId}); + api.sendMessageToFrame(frameId, 'popupConfigured', {messageId}); } _isMessageAuthenticated(message) { diff --git a/ext/fg/js/frame-offset-forwarder.js b/ext/fg/js/frame-offset-forwarder.js index 9b68d34e..10e3b5be 100644 --- a/ext/fg/js/frame-offset-forwarder.js +++ b/ext/fg/js/frame-offset-forwarder.js @@ -16,7 +16,7 @@ */ /* global - * apiBroadcastTab + * api */ class FrameOffsetForwarder { @@ -161,6 +161,6 @@ class FrameOffsetForwarder { } _forwardFrameOffsetOrigin(offset, uniqueId) { - apiBroadcastTab('frameOffset', {offset, uniqueId}); + api.broadcastTab('frameOffset', {offset, uniqueId}); } } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 575dc413..a263f3e6 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -17,11 +17,7 @@ /* global * TextScanner - * apiBroadcastTab - * apiGetZoom - * apiKanjiFind - * apiOptionsGet - * apiTermsFind + * api * docSentenceExtract */ @@ -69,7 +65,7 @@ class Frontend { async prepare() { try { await this.updateOptions(); - const {zoomFactor} = await apiGetZoom(); + const {zoomFactor} = await api.getZoom(); this._pageZoomFactor = zoomFactor; window.addEventListener('resize', this._onResize.bind(this), false); @@ -120,7 +116,7 @@ class Frontend { async updateOptions() { const optionsContext = await this.getOptionsContext(); - this._options = await apiOptionsGet(optionsContext); + this._options = await api.optionsGet(optionsContext); this._textScanner.setOptions(this._options); this._updateTextScannerEnabled(); @@ -261,7 +257,7 @@ class Frontend { const searchText = this._textScanner.getTextSourceContent(textSource, this._options.scanning.length); if (searchText.length === 0) { return null; } - const {definitions, length} = await apiTermsFind(searchText, {}, optionsContext); + const {definitions, length} = await api.termsFind(searchText, {}, optionsContext); if (definitions.length === 0) { return null; } textSource.setEndOffset(length); @@ -273,7 +269,7 @@ class Frontend { const searchText = this._textScanner.getTextSourceContent(textSource, 1); if (searchText.length === 0) { return null; } - const definitions = await apiKanjiFind(searchText, optionsContext); + const definitions = await api.kanjiFind(searchText, optionsContext); if (definitions.length === 0) { return null; } textSource.setEndOffset(1); @@ -351,12 +347,12 @@ class Frontend { _broadcastRootPopupInformation() { if (!this._popup.isProxy() && this._popup.depth === 0 && this._popup.frameId === 0) { - apiBroadcastTab('rootPopupInformation', {popupId: this._popup.id, frameId: this._popup.frameId}); + api.broadcastTab('rootPopupInformation', {popupId: this._popup.id, frameId: this._popup.frameId}); } } _broadcastDocumentInformation(uniqueId) { - apiBroadcastTab('documentInformationBroadcast', { + api.broadcastTab('documentInformationBroadcast', { uniqueId, frameId: this._popup.frameId, title: document.title diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index b7d4b57e..a8188143 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -17,7 +17,7 @@ /* global * DOM - * apiOptionsGet + * api * dynamicLoader */ @@ -89,7 +89,7 @@ class Popup { this._optionsContext = optionsContext; this._previousOptionsContextSource = source; - this._options = await apiOptionsGet(optionsContext); + this._options = await api.optionsGet(optionsContext); this.updateTheme(); this._invokeApi('setOptionsContext', {optionsContext}); diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js index 0bc91759..e09a0db6 100644 --- a/ext/mixed/js/api.js +++ b/ext/mixed/js/api.js @@ -15,307 +15,321 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ +const api = (() => { + class API { + constructor() { + this._forwardLogsToBackendEnabled = false; + } + + forwardLogsToBackend() { + if (this._forwardLogsToBackendEnabled) { return; } + this._forwardLogsToBackendEnabled = true; + + yomichan.on('log', async ({error, level, context}) => { + try { + await this.log(errorToJson(error), level, context); + } catch (e) { + // NOP + } + }); + } + + // Invoke functions + + optionsSchemaGet() { + return this._invoke('optionsSchemaGet'); + } + + optionsGet(optionsContext) { + return this._invoke('optionsGet', {optionsContext}); + } + + optionsGetFull() { + return this._invoke('optionsGetFull'); + } + + optionsSave(source) { + return this._invoke('optionsSave', {source}); + } + + termsFind(text, details, optionsContext) { + return this._invoke('termsFind', {text, details, optionsContext}); + } + + textParse(text, optionsContext) { + return this._invoke('textParse', {text, optionsContext}); + } + + kanjiFind(text, optionsContext) { + return this._invoke('kanjiFind', {text, optionsContext}); + } + + definitionAdd(definition, mode, context, details, optionsContext) { + return this._invoke('definitionAdd', {definition, mode, context, details, optionsContext}); + } + + definitionsAddable(definitions, modes, context, optionsContext) { + return this._invoke('definitionsAddable', {definitions, modes, context, optionsContext}); + } + + noteView(noteId) { + return this._invoke('noteView', {noteId}); + } + + templateRender(template, data) { + return this._invoke('templateRender', {data, template}); + } + + audioGetUri(definition, source, details) { + return this._invoke('audioGetUri', {definition, source, details}); + } + + commandExec(command, params) { + return this._invoke('commandExec', {command, params}); + } + + screenshotGet(options) { + return this._invoke('screenshotGet', {options}); + } + + sendMessageToFrame(frameId, action, params) { + return this._invoke('sendMessageToFrame', {frameId, action, params}); + } + + broadcastTab(action, params) { + return this._invoke('broadcastTab', {action, params}); + } -function apiOptionsSchemaGet() { - return _apiInvoke('optionsSchemaGet'); -} + frameInformationGet() { + return this._invoke('frameInformationGet'); + } -function apiOptionsGet(optionsContext) { - return _apiInvoke('optionsGet', {optionsContext}); -} + injectStylesheet(type, value) { + return this._invoke('injectStylesheet', {type, value}); + } -function apiOptionsGetFull() { - return _apiInvoke('optionsGetFull'); -} + getEnvironmentInfo() { + return this._invoke('getEnvironmentInfo'); + } -function apiOptionsSave(source) { - return _apiInvoke('optionsSave', {source}); -} + clipboardGet() { + return this._invoke('clipboardGet'); + } -function apiTermsFind(text, details, optionsContext) { - return _apiInvoke('termsFind', {text, details, optionsContext}); -} + getDisplayTemplatesHtml() { + return this._invoke('getDisplayTemplatesHtml'); + } -function apiTextParse(text, optionsContext) { - return _apiInvoke('textParse', {text, optionsContext}); -} + getQueryParserTemplatesHtml() { + return this._invoke('getQueryParserTemplatesHtml'); + } -function apiKanjiFind(text, optionsContext) { - return _apiInvoke('kanjiFind', {text, optionsContext}); -} + getZoom() { + return this._invoke('getZoom'); + } -function apiDefinitionAdd(definition, mode, context, details, optionsContext) { - return _apiInvoke('definitionAdd', {definition, mode, context, details, optionsContext}); -} + getDefaultAnkiFieldTemplates() { + return this._invoke('getDefaultAnkiFieldTemplates'); + } -function apiDefinitionsAddable(definitions, modes, context, optionsContext) { - return _apiInvoke('definitionsAddable', {definitions, modes, context, optionsContext}); -} + getAnkiDeckNames() { + return this._invoke('getAnkiDeckNames'); + } -function apiNoteView(noteId) { - return _apiInvoke('noteView', {noteId}); -} + getAnkiModelNames() { + return this._invoke('getAnkiModelNames'); + } -function apiTemplateRender(template, data) { - return _apiInvoke('templateRender', {data, template}); -} + getAnkiModelFieldNames(modelName) { + return this._invoke('getAnkiModelFieldNames', {modelName}); + } -function apiAudioGetUri(definition, source, details) { - return _apiInvoke('audioGetUri', {definition, source, details}); -} + getDictionaryInfo() { + return this._invoke('getDictionaryInfo'); + } -function apiCommandExec(command, params) { - return _apiInvoke('commandExec', {command, params}); -} - -function apiScreenshotGet(options) { - return _apiInvoke('screenshotGet', {options}); -} - -function apiSendMessageToFrame(frameId, action, params) { - return _apiInvoke('sendMessageToFrame', {frameId, action, params}); -} - -function apiBroadcastTab(action, params) { - return _apiInvoke('broadcastTab', {action, params}); -} - -function apiFrameInformationGet() { - return _apiInvoke('frameInformationGet'); -} - -function apiInjectStylesheet(type, value) { - return _apiInvoke('injectStylesheet', {type, value}); -} - -function apiGetEnvironmentInfo() { - return _apiInvoke('getEnvironmentInfo'); -} - -function apiClipboardGet() { - return _apiInvoke('clipboardGet'); -} - -function apiGetDisplayTemplatesHtml() { - return _apiInvoke('getDisplayTemplatesHtml'); -} - -function apiGetQueryParserTemplatesHtml() { - return _apiInvoke('getQueryParserTemplatesHtml'); -} - -function apiGetZoom() { - return _apiInvoke('getZoom'); -} - -function apiGetDefaultAnkiFieldTemplates() { - return _apiInvoke('getDefaultAnkiFieldTemplates'); -} - -function apiGetAnkiDeckNames() { - return _apiInvoke('getAnkiDeckNames'); -} - -function apiGetAnkiModelNames() { - return _apiInvoke('getAnkiModelNames'); -} - -function apiGetAnkiModelFieldNames(modelName) { - return _apiInvoke('getAnkiModelFieldNames', {modelName}); -} - -function apiGetDictionaryInfo() { - return _apiInvoke('getDictionaryInfo'); -} - -function apiGetDictionaryCounts(dictionaryNames, getTotal) { - return _apiInvoke('getDictionaryCounts', {dictionaryNames, getTotal}); -} - -function apiPurgeDatabase() { - return _apiInvoke('purgeDatabase'); -} - -function apiGetMedia(targets) { - return _apiInvoke('getMedia', {targets}); -} - -function apiLog(error, level, context) { - return _apiInvoke('log', {error, level, context}); -} - -function apiLogIndicatorClear() { - return _apiInvoke('logIndicatorClear'); -} - -function apiImportDictionaryArchive(archiveContent, details, onProgress) { - return _apiInvokeWithProgress('importDictionaryArchive', {archiveContent, details}, onProgress); -} - -function apiDeleteDictionary(dictionaryName, onProgress) { - return _apiInvokeWithProgress('deleteDictionary', {dictionaryName}, onProgress); -} - -function apiModifySettings(targets, source) { - return _apiInvoke('modifySettings', {targets, source}); -} - -function _apiCreateActionPort(timeout=5000) { - return new Promise((resolve, reject) => { - let timer = null; - let portNameResolve; - let portNameReject; - const portNamePromise = new Promise((resolve2, reject2) => { - portNameResolve = resolve2; - portNameReject = reject2; - }); - - const onConnect = async (port) => { - try { - const portName = await portNamePromise; - if (port.name !== portName || timer === null) { return; } - } catch (e) { - return; - } - - clearTimeout(timer); - timer = null; - - chrome.runtime.onConnect.removeListener(onConnect); - resolve(port); - }; - - const onError = (e) => { - if (timer !== null) { - clearTimeout(timer); - timer = null; - } - chrome.runtime.onConnect.removeListener(onConnect); - portNameReject(e); - reject(e); - }; - - timer = setTimeout(() => onError(new Error('Timeout')), timeout); - - chrome.runtime.onConnect.addListener(onConnect); - _apiInvoke('createActionPort').then(portNameResolve, onError); - }); -} - -function _apiInvokeWithProgress(action, params, onProgress, timeout=5000) { - return new Promise((resolve, reject) => { - let timer = null; - let port = null; - - if (typeof onProgress !== 'function') { - onProgress = () => {}; - } - - const onMessage = (message) => { - switch (message.type) { - case 'ack': + getDictionaryCounts(dictionaryNames, getTotal) { + return this._invoke('getDictionaryCounts', {dictionaryNames, getTotal}); + } + + purgeDatabase() { + return this._invoke('purgeDatabase'); + } + + getMedia(targets) { + return this._invoke('getMedia', {targets}); + } + + log(error, level, context) { + return this._invoke('log', {error, level, context}); + } + + logIndicatorClear() { + return this._invoke('logIndicatorClear'); + } + + modifySettings(targets, source) { + return this._invoke('modifySettings', {targets, source}); + } + + // Invoke functions with progress + + importDictionaryArchive(archiveContent, details, onProgress) { + return this._invokeWithProgress('importDictionaryArchive', {archiveContent, details}, onProgress); + } + + deleteDictionary(dictionaryName, onProgress) { + return this._invokeWithProgress('deleteDictionary', {dictionaryName}, onProgress); + } + + // Utilities + + _createActionPort(timeout=5000) { + return new Promise((resolve, reject) => { + let timer = null; + let portNameResolve; + let portNameReject; + const portNamePromise = new Promise((resolve2, reject2) => { + portNameResolve = resolve2; + portNameReject = reject2; + }); + + const onConnect = async (port) => { + try { + const portName = await portNamePromise; + if (port.name !== portName || timer === null) { return; } + } catch (e) { + return; + } + + clearTimeout(timer); + timer = null; + + chrome.runtime.onConnect.removeListener(onConnect); + resolve(port); + }; + + const onError = (e) => { if (timer !== null) { clearTimeout(timer); timer = null; } - break; - case 'progress': - try { - onProgress(...message.data); - } catch (e) { - // NOP + chrome.runtime.onConnect.removeListener(onConnect); + portNameReject(e); + reject(e); + }; + + timer = setTimeout(() => onError(new Error('Timeout')), timeout); + + chrome.runtime.onConnect.addListener(onConnect); + this._invoke('createActionPort').then(portNameResolve, onError); + }); + } + + _invokeWithProgress(action, params, onProgress, timeout=5000) { + return new Promise((resolve, reject) => { + let timer = null; + let port = null; + + if (typeof onProgress !== 'function') { + onProgress = () => {}; + } + + const onMessage = (message) => { + switch (message.type) { + case 'ack': + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + break; + case 'progress': + try { + onProgress(...message.data); + } catch (e) { + // NOP + } + break; + case 'complete': + cleanup(); + resolve(message.data); + break; + case 'error': + cleanup(); + reject(jsonToError(message.data)); + break; } - break; - case 'complete': + }; + + const onDisconnect = () => { cleanup(); - resolve(message.data); - break; - case 'error': + reject(new Error('Disconnected')); + }; + + const cleanup = () => { + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + if (port !== null) { + port.onMessage.removeListener(onMessage); + port.onDisconnect.removeListener(onDisconnect); + port.disconnect(); + port = null; + } + onProgress = null; + }; + + timer = setTimeout(() => { cleanup(); - reject(jsonToError(message.data)); - break; - } - }; - - const onDisconnect = () => { - cleanup(); - reject(new Error('Disconnected')); - }; - - const cleanup = () => { - if (timer !== null) { - clearTimeout(timer); - timer = null; - } - if (port !== null) { - port.onMessage.removeListener(onMessage); - port.onDisconnect.removeListener(onDisconnect); - port.disconnect(); - port = null; - } - onProgress = null; - }; - - timer = setTimeout(() => { - cleanup(); - reject(new Error('Timeout')); - }, timeout); - - (async () => { - try { - port = await _apiCreateActionPort(timeout); - port.onMessage.addListener(onMessage); - port.onDisconnect.addListener(onDisconnect); - port.postMessage({action, params}); - } catch (e) { - cleanup(); - reject(e); - } finally { - action = null; - params = null; - } - })(); - }); -} - -function _apiInvoke(action, params={}) { - const data = {action, params}; - return new Promise((resolve, reject) => { - try { - chrome.runtime.sendMessage(data, (response) => { - _apiCheckLastError(chrome.runtime.lastError); - if (response !== null && typeof response === 'object') { - if (typeof response.error !== 'undefined') { - reject(jsonToError(response.error)); - } else { - resolve(response.result); + reject(new Error('Timeout')); + }, timeout); + + (async () => { + try { + port = await this._createActionPort(timeout); + port.onMessage.addListener(onMessage); + port.onDisconnect.addListener(onDisconnect); + port.postMessage({action, params}); + } catch (e) { + cleanup(); + reject(e); + } finally { + action = null; + params = null; } - } else { - const message = response === null ? 'Unexpected null response' : `Unexpected response of type ${typeof response}`; - reject(new Error(`${message} (${JSON.stringify(data)})`)); + })(); + }); + } + + _invoke(action, params={}) { + const data = {action, params}; + return new Promise((resolve, reject) => { + try { + chrome.runtime.sendMessage(data, (response) => { + this._checkLastError(chrome.runtime.lastError); + if (response !== null && typeof response === 'object') { + if (typeof response.error !== 'undefined') { + reject(jsonToError(response.error)); + } else { + resolve(response.result); + } + } else { + const message = response === null ? 'Unexpected null response' : `Unexpected response of type ${typeof response}`; + reject(new Error(`${message} (${JSON.stringify(data)})`)); + } + }); + } catch (e) { + reject(e); + yomichan.triggerOrphaned(e); } }); - } catch (e) { - reject(e); - yomichan.triggerOrphaned(e); - } - }); -} - -function _apiCheckLastError() { - // NOP -} - -let _apiForwardLogsToBackendEnabled = false; -function apiForwardLogsToBackend() { - if (_apiForwardLogsToBackendEnabled) { return; } - _apiForwardLogsToBackendEnabled = true; - - yomichan.on('log', async ({error, level, context}) => { - try { - await apiLog(errorToJson(error), level, context); - } catch (e) { + } + + _checkLastError() { // NOP } - }); -} + } + + return new API(); +})(); diff --git a/ext/mixed/js/display-generator.js b/ext/mixed/js/display-generator.js index a2b2b139..3f3a155e 100644 --- a/ext/mixed/js/display-generator.js +++ b/ext/mixed/js/display-generator.js @@ -17,7 +17,7 @@ /* global * TemplateHandler - * apiGetDisplayTemplatesHtml + * api * jp */ @@ -29,7 +29,7 @@ class DisplayGenerator { } async prepare() { - const html = await apiGetDisplayTemplatesHtml(); + const html = await api.getDisplayTemplatesHtml(); this._templateHandler = new TemplateHandler(html); } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 2e59b4ff..380134ad 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -22,15 +22,7 @@ * DisplayGenerator * MediaLoader * WindowScroll - * apiAudioGetUri - * apiBroadcastTab - * apiDefinitionAdd - * apiDefinitionsAddable - * apiKanjiFind - * apiNoteView - * apiOptionsGet - * apiScreenshotGet - * apiTermsFind + * api * docRangeFromPoint * docSentenceExtract */ @@ -49,7 +41,7 @@ class Display { this.audioSystem = new AudioSystem({ audioUriBuilder: { getUri: async (definition, source, details) => { - return await apiAudioGetUri(definition, source, details); + return await api.audioGetUri(definition, source, details); } }, useCache: true @@ -212,7 +204,7 @@ class Display { url: this.context.get('url') }; - const definitions = await apiKanjiFind(link.textContent, this.getOptionsContext()); + const definitions = await api.kanjiFind(link.textContent, this.getOptionsContext()); this.setContent('kanji', {definitions, context}); } catch (error) { this.onError(error); @@ -290,7 +282,7 @@ class Display { try { textSource.setEndOffset(this.options.scanning.length); - ({definitions, length} = await apiTermsFind(textSource.text(), {}, this.getOptionsContext())); + ({definitions, length} = await api.termsFind(textSource.text(), {}, this.getOptionsContext())); if (definitions.length === 0) { return false; } @@ -334,7 +326,7 @@ class Display { onNoteView(e) { e.preventDefault(); const link = e.currentTarget; - apiNoteView(link.dataset.noteId); + api.noteView(link.dataset.noteId); } onKeyDown(e) { @@ -379,7 +371,7 @@ class Display { } async updateOptions() { - this.options = await apiOptionsGet(this.getOptionsContext()); + this.options = await api.optionsGet(this.getOptionsContext()); this.updateDocumentOptions(this.options); this.updateTheme(this.options.general.popupTheme); this.setCustomCss(this.options.general.customPopupCss); @@ -746,7 +738,7 @@ class Display { noteTryView() { const button = this.viewerButtonFind(this.index); if (button !== null && !button.classList.contains('disabled')) { - apiNoteView(button.dataset.noteId); + api.noteView(button.dataset.noteId); } } @@ -763,7 +755,7 @@ class Display { } const context = await this._getNoteContext(); - const noteId = await apiDefinitionAdd(definition, mode, context, details, this.getOptionsContext()); + const noteId = await api.definitionAdd(definition, mode, context, details, this.getOptionsContext()); if (noteId) { const index = this.definitions.indexOf(definition); const adderButton = this.adderButtonFind(index, mode); @@ -857,7 +849,7 @@ class Display { await promiseTimeout(1); // Wait for popup to be hidden. const {format, quality} = this.options.anki.screenshot; - const dataUrl = await apiScreenshotGet({format, quality}); + const dataUrl = await api.screenshotGet({format, quality}); if (!dataUrl || dataUrl.error) { return; } return {dataUrl, format}; @@ -871,7 +863,7 @@ class Display { } setPopupVisibleOverride(visible) { - return apiBroadcastTab('popupSetVisibleOverride', {visible}); + return api.broadcastTab('popupSetVisibleOverride', {visible}); } setSpinnerVisible(visible) { @@ -933,7 +925,7 @@ class Display { async getDefinitionsAddable(definitions, modes) { try { const context = await this._getNoteContext(); - return await apiDefinitionsAddable(definitions, modes, context, this.getOptionsContext()); + return await api.definitionsAddable(definitions, modes, context, this.getOptionsContext()); } catch (e) { return []; } diff --git a/ext/mixed/js/dynamic-loader.js b/ext/mixed/js/dynamic-loader.js index ce946109..37f85112 100644 --- a/ext/mixed/js/dynamic-loader.js +++ b/ext/mixed/js/dynamic-loader.js @@ -16,7 +16,7 @@ */ /* global - * apiInjectStylesheet + * api */ const dynamicLoader = (() => { @@ -45,7 +45,7 @@ const dynamicLoader = (() => { } injectedStylesheets.set(id, null); - await apiInjectStylesheet(type, value); + await api.injectStylesheet(type, value); return null; } diff --git a/ext/mixed/js/media-loader.js b/ext/mixed/js/media-loader.js index 64ccd715..fc6e93d1 100644 --- a/ext/mixed/js/media-loader.js +++ b/ext/mixed/js/media-loader.js @@ -16,7 +16,7 @@ */ /* global - * apiGetMedia + * api */ class MediaLoader { @@ -84,7 +84,7 @@ class MediaLoader { async _getMediaData(path, dictionaryName, cachedData) { const token = this._token; - const data = (await apiGetMedia([{path, dictionaryName}]))[0]; + const data = (await api.getMedia([{path, dictionaryName}]))[0]; if (token === this._token && data !== null) { const contentArrayBuffer = this._base64ToArrayBuffer(data.content); const blob = new Blob([contentArrayBuffer], {type: data.mediaType}); |