diff --git a/README.md b/README.md index 4949308f15..3b29a2278c 100644 --- a/README.md +++ b/README.md @@ -128,4 +128,4 @@ Yomitan uses several third-party libraries to function. ## Attribution -`button.mp3` is provided by [UNIVERSFIELD](https://pixabay.com/sound-effects/error-8-206492/) and licensed under the [Pixabay Content License](https://pixabay.com/service/license-summary/). +`fallback-bloop.mp3` is provided by [UNIVERSFIELD](https://pixabay.com/sound-effects/error-8-206492/) and licensed under the [Pixabay Content License](https://pixabay.com/service/license-summary/). diff --git a/dev/data/manifest-variants.json b/dev/data/manifest-variants.json index 0dd2a22f6b..5b7e1bdb80 100644 --- a/dev/data/manifest-variants.json +++ b/dev/data/manifest-variants.json @@ -33,6 +33,9 @@ "service_worker": "sw.js", "type": "module" }, + "omnibox": { + "keyword": "yomi" + }, "content_scripts": [ { "run_at": "document_idle", diff --git a/ext/data/audio/button.mp3 b/ext/data/audio/fallback-bloop.mp3 similarity index 100% rename from ext/data/audio/button.mp3 rename to ext/data/audio/fallback-bloop.mp3 diff --git a/ext/data/audio/fallback-click.mp3 b/ext/data/audio/fallback-click.mp3 new file mode 100644 index 0000000000..7a9728d1c8 Binary files /dev/null and b/ext/data/audio/fallback-click.mp3 differ diff --git a/ext/data/schemas/options-schema.json b/ext/data/schemas/options-schema.json index c47f7063fd..227bc945ec 100644 --- a/ext/data/schemas/options-schema.json +++ b/ext/data/schemas/options-schema.json @@ -391,7 +391,7 @@ "enabled", "volume", "autoPlay", - "playFallbackSound", + "fallbackSoundType", "sources" ], "properties": { @@ -409,9 +409,10 @@ "type": "boolean", "default": false }, - "playFallbackSound": { - "type": "boolean", - "default": true + "fallbackSoundType": { + "type": "string", + "enum": ["none", "click", "bloop"], + "default": "click" }, "sources": { "type": "array", diff --git a/ext/data/templates/anki-field-templates-upgrade-v60.handlebars b/ext/data/templates/anki-field-templates-upgrade-v61.handlebars similarity index 100% rename from ext/data/templates/anki-field-templates-upgrade-v60.handlebars rename to ext/data/templates/anki-field-templates-upgrade-v61.handlebars diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index a533805c52..a9dbbc3e54 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -1373,6 +1373,8 @@ export class Backend { this._setupContextMenu(options); + this._attachOmniboxListener(); + void this._accessibilityController.update(this._getOptionsFull(false)); this._sendMessageAllTabsIgnoreResponse({action: 'applicationOptionsUpdated', params: {source}}); @@ -1404,6 +1406,18 @@ export class Backend { } } + /** */ + _attachOmniboxListener() { + try { + chrome.omnibox.onInputEntered.addListener((text) => { + const newURL = 'search.html?query=' + encodeURIComponent(text); + void chrome.tabs.create({url: newURL}); + }); + } catch (e) { + log.error(e); + } + } + /** * @param {boolean} useSchema * @returns {import('settings').Options} diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index 1e37db64d3..50b94d2e04 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -572,6 +572,7 @@ export class OptionsUtil { this._updateVersion58, this._updateVersion59, this._updateVersion60, + this._updateVersion61, ]; /* eslint-enable @typescript-eslint/unbound-method */ if (typeof targetVersion === 'number' && targetVersion < result.length) { @@ -1596,11 +1597,22 @@ export class OptionsUtil { } /** - * - Added sentence-furigana-plain handlebar + * - Replaced audio.playFallbackSound with audio.fallbackSoundType * @type {import('options-util').UpdateFunction} */ async _updateVersion60(options) { - await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v60.handlebars'); + for (const profile of options.profiles) { + profile.options.audio.fallbackSoundType = profile.options.audio.playFallbackSound ? 'click' : 'none'; + delete profile.options.audio.playFallbackSound; + } + } + + /** + * - Added sentence-furigana-plain handlebar + * @type {import('options-util').UpdateFunction} + */ + async _updateVersion61(options) { + await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v61.handlebars'); } /** diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index ef035857ce..87f5691370 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -36,8 +36,8 @@ export class DisplayAudio { this._playbackVolume = 1; /** @type {boolean} */ this._autoPlay = false; - /** @type {boolean} */ - this._playFallbackSound = true; + /** @type {import('settings').FallbackSoundType} */ + this._fallbackSoundType = 'none'; /** @type {?import('core').Timeout} */ this._autoPlayAudioTimer = null; /** @type {number} */ @@ -170,10 +170,10 @@ export class DisplayAudio { _onOptionsUpdated({options}) { const { general: {language}, - audio: {enabled, autoPlay, playFallbackSound, volume, sources}, + audio: {enabled, autoPlay, fallbackSoundType, volume, sources}, } = options; this._autoPlay = enabled && autoPlay; - this._playFallbackSound = playFallbackSound; + this._fallbackSoundType = fallbackSoundType; this._playbackVolume = Number.isFinite(volume) ? Math.max(0, Math.min(1, volume / 100)) : 1; /** @type {Set} */ @@ -454,7 +454,7 @@ export class DisplayAudio { const sourceIndex = sources.indexOf(source); title = `From source ${1 + sourceIndex}: ${source.name}`; } else { - audio = this._audioSystem.getFallbackAudio(this._playFallbackSound); + audio = this._audioSystem.getFallbackAudio(this._fallbackSoundType); title = 'Could not find audio'; } diff --git a/ext/js/media/audio-system.js b/ext/js/media/audio-system.js index 7a7e40bebd..0dfa2d20f9 100644 --- a/ext/js/media/audio-system.js +++ b/ext/js/media/audio-system.js @@ -27,8 +27,8 @@ export class AudioSystem extends EventDispatcher { super(); /** @type {?HTMLAudioElement} */ this._fallbackAudio = null; - /** @type {?boolean} */ - this._playFallbackSound = null; + /** @type {?import('settings').FallbackSoundType} */ + this._fallbackSoundType = null; } /** @@ -45,14 +45,24 @@ export class AudioSystem extends EventDispatcher { } /** - * @param {boolean} playFallbackSound + * @param {import('settings').FallbackSoundType} fallbackSoundType * @returns {HTMLAudioElement} */ - getFallbackAudio(playFallbackSound) { - if (this._fallbackAudio === null || this._playFallbackSound !== playFallbackSound) { - // audio handler expects audio url to always be present, empty string must be used instead of `new Audio()` - this._fallbackAudio = playFallbackSound ? new Audio('/data/audio/button.mp3') : new Audio(''); - this._playFallbackSound = playFallbackSound; + getFallbackAudio(fallbackSoundType) { + if (this._fallbackAudio === null || this._fallbackSoundType !== fallbackSoundType) { + this._fallbackSoundType = fallbackSoundType; + switch (fallbackSoundType) { + case 'click': + this._fallbackAudio = new Audio('/data/audio/fallback-click.mp3'); + break; + case 'bloop': + this._fallbackAudio = new Audio('/data/audio/fallback-bloop.mp3'); + break; + case 'none': + // audio handler expects audio url to always be present, empty string must be used instead of `new Audio()` + this._fallbackAudio = new Audio(''); + break; + } } return this._fallbackAudio; } diff --git a/ext/settings.html b/ext/settings.html index 924c230fe5..b6b3101545 100644 --- a/ext/settings.html +++ b/ext/settings.html @@ -1461,15 +1461,23 @@

Yomitan Settings

-
-
-
Enable audio fallback sound
-
Play sound when Yomitan fails to fetch audio.
-
-
- +
+
+
+
Audio fallback sound
+
+ The sound to play when Yomitan fails to fetch audio. +
+
+
+ +
-
+
Audio volume
diff --git a/test/options-util.test.js b/test/options-util.test.js index 81bce9dceb..08230c3b7b 100644 --- a/test/options-util.test.js +++ b/test/options-util.test.js @@ -76,7 +76,7 @@ function createProfileOptionsTestData1() { sources: ['jpod101', 'text-to-speech', 'custom', 'jpod101-alternate'], volume: 100, autoPlay: false, - playFallbackSound: true, + fallbackSoundType: 'click', customSourceUrl: 'http://localhost/audio.mp3?term={expression}&reading={reading}', textToSpeechVoice: 'example-voice', }, @@ -337,7 +337,7 @@ function createProfileOptionsUpdatedTestData1() { ], volume: 100, autoPlay: false, - playFallbackSound: true, + fallbackSoundType: 'click', }, scanning: { selectText: true, @@ -680,7 +680,7 @@ function createOptionsUpdatedTestData1() { }, ], profileCurrent: 0, - version: 60, + version: 61, global: { database: { prefixWildcardsSupported: false, diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts index 5ca7e62c39..f5111e629b 100644 --- a/types/ext/settings.d.ts +++ b/types/ext/settings.d.ts @@ -167,10 +167,12 @@ export type AudioOptions = { enabled: boolean; volume: number; autoPlay: boolean; - playFallbackSound: boolean; + fallbackSoundType: FallbackSoundType; sources: AudioSourceOptions[]; }; +export type FallbackSoundType = 'none' | 'click' | 'bloop'; + export type AudioSourceOptions = { type: AudioSourceType; url: string;