aboutsummaryrefslogtreecommitdiff
path: root/ext/mixed/js/api.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mixed/js/api.js')
-rw-r--r--ext/mixed/js/api.js196
1 files changed, 186 insertions, 10 deletions
diff --git a/ext/mixed/js/api.js b/ext/mixed/js/api.js
index 30c08347..0bc91759 100644
--- a/ext/mixed/js/api.js
+++ b/ext/mixed/js/api.js
@@ -28,10 +28,6 @@ function apiOptionsGetFull() {
return _apiInvoke('optionsGetFull');
}
-function apiOptionsSet(changedOptions, optionsContext, source) {
- return _apiInvoke('optionsSet', {changedOptions, optionsContext, source});
-}
-
function apiOptionsSave(source) {
return _apiInvoke('optionsSave', {source});
}
@@ -64,8 +60,8 @@ function apiTemplateRender(template, data) {
return _apiInvoke('templateRender', {data, template});
}
-function apiAudioGetUri(definition, source, optionsContext) {
- return _apiInvoke('audioGetUri', {definition, source, optionsContext});
+function apiAudioGetUri(definition, source, details) {
+ return _apiInvoke('audioGetUri', {definition, source, details});
}
function apiCommandExec(command, params) {
@@ -76,6 +72,10 @@ 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});
}
@@ -108,14 +108,176 @@ function apiGetZoom() {
return _apiInvoke('getZoom');
}
-function apiGetMessageToken() {
- return _apiInvoke('getMessageToken');
-}
-
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':
+ 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;
+ }
+ };
+
+ 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) => {
@@ -143,3 +305,17 @@ function _apiInvoke(action, params={}) {
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) {
+ // NOP
+ }
+ });
+}