summaryrefslogtreecommitdiff
path: root/ext/js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-04-10 23:55:11 -0400
committerGitHub <noreply@github.com>2021-04-10 23:55:11 -0400
commit20d60a2ba79c065586805806ea703a8057839f75 (patch)
tree3043090e118e03a8e276d2a7f1557e525ac23239 /ext/js
parentb23c4bff4bf319ea79eea0d025e21eb19e6dcd68 (diff)
Initial safari compatibility (#1609)
* Update environment info to return the 'safari' browser * Fix popup display on Safari * Update environment assignment * Add data-loading-stalled property when loading takes longer than expected * Add notification when loading has stalled * Allow getDictionaryInfo invocation on non-privileged contexts * Update _validatePrivilegedMessageSender * Don't listen to 'voiceschanged' event unless addEventListener is present Also expose an event
Diffstat (limited to 'ext/js')
-rw-r--r--ext/js/background/backend.js14
-rw-r--r--ext/js/background/environment.js14
-rw-r--r--ext/js/media/audio-system.js18
-rw-r--r--ext/js/pages/action-popup-main.js9
-rw-r--r--ext/js/pages/settings/audio-controller.js4
-rw-r--r--ext/js/pages/settings/settings-main.js27
6 files changed, 67 insertions, 19 deletions
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index a6b9c0dc..21b18e99 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -112,7 +112,7 @@ class Backend {
['getDisplayTemplatesHtml', {async: true, contentScript: true, handler: this._onApiGetDisplayTemplatesHtml.bind(this)}],
['getZoom', {async: true, contentScript: true, handler: this._onApiGetZoom.bind(this)}],
['getDefaultAnkiFieldTemplates', {async: false, contentScript: true, handler: this._onApiGetDefaultAnkiFieldTemplates.bind(this)}],
- ['getDictionaryInfo', {async: true, contentScript: false, handler: this._onApiGetDictionaryInfo.bind(this)}],
+ ['getDictionaryInfo', {async: true, contentScript: true, handler: this._onApiGetDictionaryInfo.bind(this)}],
['getDictionaryCounts', {async: true, contentScript: false, handler: this._onApiGetDictionaryCounts.bind(this)}],
['purgeDatabase', {async: true, contentScript: false, handler: this._onApiPurgeDatabase.bind(this)}],
['getMedia', {async: true, contentScript: true, handler: this._onApiGetMedia.bind(this)}],
@@ -1288,10 +1288,14 @@ class Backend {
}
_validatePrivilegedMessageSender(sender) {
- const url = sender.url;
- if (!(typeof url === 'string' && yomichan.isExtensionUrl(url))) {
- throw new Error('Invalid message sender');
- }
+ let {url} = sender;
+ if (typeof url === 'string' && yomichan.isExtensionUrl(url)) { return; }
+ const {tab} = url;
+ if (typeof tab === 'object' && tab !== null) {
+ ({url} = tab);
+ if (typeof url === 'string' && yomichan.isExtensionUrl(url)) { return; }
+ }
+ throw new Error('Invalid message sender');
}
_getBrowserIconTitle() {
diff --git a/ext/js/background/environment.js b/ext/js/background/environment.js
index 04099ca1..8111741f 100644
--- a/ext/js/background/environment.js
+++ b/ext/js/background/environment.js
@@ -83,9 +83,23 @@ class Environment {
} catch (e) {
// NOP
}
+ if (this._isSafari()) {
+ return 'safari';
+ }
return 'firefox';
} else {
return 'chrome';
}
}
+
+ _isSafari() {
+ const {vendor, userAgent} = navigator;
+ return (
+ typeof vendor === 'string' &&
+ typeof userAgent === 'string' &&
+ vendor.includes('Apple') &&
+ !userAgent.includes('CriOS') &&
+ !userAgent.includes('FxiOS')
+ );
+ }
}
diff --git a/ext/js/media/audio-system.js b/ext/js/media/audio-system.js
index cf63511f..cc2bcfc0 100644
--- a/ext/js/media/audio-system.js
+++ b/ext/js/media/audio-system.js
@@ -19,18 +19,20 @@
* TextToSpeechAudio
*/
-class AudioSystem {
+class AudioSystem extends EventDispatcher {
constructor() {
+ super();
this._fallbackAudio = null;
}
prepare() {
// speechSynthesis.getVoices() will not be populated unless some API call is made.
- if (typeof speechSynthesis === 'undefined') { return; }
-
- const eventListeners = new EventListenerCollection();
- const onVoicesChanged = () => { eventListeners.removeAllEventListeners(); };
- eventListeners.addEventListener(speechSynthesis, 'voiceschanged', onVoicesChanged, false);
+ if (
+ typeof speechSynthesis !== 'undefined' &&
+ typeof speechSynthesis.addEventListener === 'function'
+ ) {
+ speechSynthesis.addEventListener('voiceschanged', this._onVoicesChanged.bind(this), false);
+ }
}
getFallbackAudio() {
@@ -64,6 +66,10 @@ class AudioSystem {
// Private
+ _onVoicesChanged(e) {
+ this.trigger('voiceschanged', e);
+ }
+
_isAudioValid(audio, source) {
switch (source) {
case 'jpod101':
diff --git a/ext/js/pages/action-popup-main.js b/ext/js/pages/action-popup-main.js
index 2de986da..4934802b 100644
--- a/ext/js/pages/action-popup-main.js
+++ b/ext/js/pages/action-popup-main.js
@@ -103,6 +103,10 @@ class DisplayController {
let tab;
try {
tab = await this._getCurrentTab();
+ // Safari assigns a tab object to the popup, other browsers do not
+ if (tab && await this._isSafari()) {
+ tab = void 0;
+ }
} catch (e) {
// NOP
}
@@ -220,6 +224,11 @@ class DisplayController {
node.hidden = false;
}
}
+
+ async _isSafari() {
+ const {browser} = await yomichan.api.getEnvironmentInfo();
+ return browser === 'safari';
+ }
}
(async () => {
diff --git a/ext/js/pages/settings/audio-controller.js b/ext/js/pages/settings/audio-controller.js
index e62383a8..6b1ce0b5 100644
--- a/ext/js/pages/settings/audio-controller.js
+++ b/ext/js/pages/settings/audio-controller.js
@@ -39,9 +39,7 @@ class AudioController {
this._audioSourceAddButton.addEventListener('click', this._onAddAudioSource.bind(this), false);
- if (typeof speechSynthesis !== 'undefined') {
- speechSynthesis.addEventListener('voiceschanged', this._updateTextToSpeechVoices.bind(this), false);
- }
+ this._audioSystem.on('voiceschanged', this._updateTextToSpeechVoices.bind(this), false);
this._updateTextToSpeechVoices();
document.querySelector('#text-to-speech-voice-test').addEventListener('click', this._onTestTextToSpeech.bind(this), false);
diff --git a/ext/js/pages/settings/settings-main.js b/ext/js/pages/settings/settings-main.js
index 2560685c..6f3e2a58 100644
--- a/ext/js/pages/settings/settings-main.js
+++ b/ext/js/pages/settings/settings-main.js
@@ -24,6 +24,7 @@
* DictionaryController
* DictionaryImportController
* DocumentFocusController
+ * Environment
* ExtensionKeyboardShortcutController
* GenericSettingController
* KeyboardShortcutController
@@ -47,11 +48,16 @@
*/
async function setupEnvironmentInfo() {
+ const {dataset} = document.documentElement;
const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
- const {browser, platform} = await yomichan.api.getEnvironmentInfo();
- document.documentElement.dataset.browser = browser;
- document.documentElement.dataset.os = platform.os;
- document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
+ dataset.manifestVersion = `${manifestVersion}`;
+
+ const environment = new Environment();
+ await environment.prepare();
+ const {browser, platform} = environment.getInfo();
+
+ dataset.browser = browser;
+ dataset.os = platform.os;
}
async function setupGenericSettingsController(genericSettingController) {
@@ -67,9 +73,20 @@ async function setupGenericSettingsController(genericSettingController) {
const statusFooter = new StatusFooter(document.querySelector('.status-footer-container'));
statusFooter.prepare();
+ setupEnvironmentInfo();
+
+ let prepareTimer = setTimeout(() => {
+ prepareTimer = null;
+ document.documentElement.dataset.loadingStalled = 'true';
+ }, 1000);
+
await yomichan.prepare();
- setupEnvironmentInfo();
+ if (prepareTimer !== null) {
+ clearTimeout(prepareTimer);
+ prepareTimer = null;
+ }
+ delete document.documentElement.dataset.loadingStalled;
const optionsFull = await yomichan.api.optionsGetFull();