diff --git a/CHANGELOG.md b/CHANGELOG.md
index e134741..5d37aa2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
## Changelog
+### Version 1.3.3
+ * Tell Anki to download Audio when playing Audio (#14)
+
### Version 1.3.2
* Adding a Clear Page button in the VN Hook Page
diff --git a/manifest.json b/manifest.json
index 91da381..f70935b 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,7 +2,7 @@
"manifest_version": 2,
"author": "Gareth Parker",
"name": "RikaiRebuilt",
- "version": "1.3.2",
+ "version": "1.3.3",
"applications": {
"gecko": {
diff --git a/options/options.html b/options/options.html
index 53d9802..1243396 100644
--- a/options/options.html
+++ b/options/options.html
@@ -372,6 +372,11 @@
Keymap
+
Version 1.3.3
+
+ - Have Anki Auto-Download Audio when Playing Audio
+
+
Version 1.3.2
- Adding a "Clear Page" button in the VN Hook section
diff --git a/package.json b/package.json
index 3416d06..c9e8891 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"@types/jquery": "^3.5.0",
"isomorphic-fetch": "^2.2.1",
"mocha": "^5.1.1",
+ "prettier": "^2.0.5",
"typescript": "^3.2.2",
"web-ext-types": "^3.1.0"
},
diff --git a/src/AnkiImport.ts b/src/AnkiImport.ts
index 15f721d..625cc82 100644
--- a/src/AnkiImport.ts
+++ b/src/AnkiImport.ts
@@ -1,190 +1,225 @@
-import AudioPlayer from './AudioPlayer';
+import AudioPlayer from "./AudioPlayer";
import {isDictionaryResult, SearchResults} from "./interfaces/SearchResults";
import {Config} from "./defaultConfig";
import {AnkiFields} from "./interfaces/AnkiFields";
import {RikaiController} from "./background";
export default class AnkiImport {
- private ankiUrl: string = 'http://127.0.0.1:49601';
-
- async makeCall(action, params) {
- return fetch(this.ankiUrl, {
- method: 'POST',
- body: JSON.stringify({action, params})
- });
+ private ankiUrl: string = "http://127.0.0.1:49601";
+ private MOCK_CALL = false;
+
+ async makeCall(action, params) {
+ if (this.MOCK_CALL) {
+ console.log(`POST ${this.ankiUrl}`);
+ console.log({ action, params });
+ return;
}
- async addNote(entryFormat: AnkiFields, entry: SearchResults, config: Config) {
- const promises = [];
- let audio = false;
- const isNoAudio = await AudioPlayer.isNoAudio(entry);
-
- const fields = {};
- for (const key in config.ankiFields) {
- let values = config.ankiFields[key].split(' ');
- let newValues = [];
-
- for (const valueKey in values) {
- let newValue = null;
- switch (values[valueKey]) {
- case 'audio':
- if (isNoAudio && !config.importEmptyAudio) {
- newValue = null;
- } else {
- audio = true;
- newValue = `[sound:${entryFormat.audioFile}]`;
- }
- break;
- case 'dictionaryFormat':
- newValue = entryFormat.dictionaryForm;
- break;
- case 'word':
- newValue = entryFormat.word;
- break;
- case 'reading':
- newValue = entryFormat.reading;
- break;
- case 'saveNotes':
- newValue = entryFormat.saveNotes;
- break;
- case 'sentence':
- newValue = entryFormat.sentence;
- break;
- case 'sentenceWithBlank':
- newValue = entryFormat.sentenceWithBlank;
- break;
- case 'sourceUrl':
- newValue = entryFormat.sourceUrl;
- break;
- case 'pageTitle':
- newValue = entryFormat.pageTitle;
- break;
- case 'definition':
- newValue = entryFormat.definition;
- break;
- case 'frequency':
- newValue = entryFormat.frequency;
- break;
- case 'pitch':
- newValue = entryFormat.pitch;
- break;
- }
-
- if (newValue !== null) {
- newValues.push(newValue);
- }
- }
-
- newValues = newValues.filter(value => value !== null);
- if (newValues.length) {
- fields[key] = newValues.join(' ');
+ return fetch(this.ankiUrl, {
+ method: "POST",
+ body: JSON.stringify({ action, params }),
+ });
+ }
+
+ async addNote(entryFormat: AnkiFields, entry: SearchResults, config: Config) {
+ const promises = [];
+ let audio = false;
+ const isNoAudio = await AudioPlayer.isNoAudio(entry);
+
+ const fields = {};
+ for (const key in config.ankiFields) {
+ let values = config.ankiFields[key].split(" ");
+ let newValues = [];
+
+ for (const valueKey in values) {
+ let newValue = null;
+ switch (values[valueKey]) {
+ case "audio":
+ if (isNoAudio && !config.importEmptyAudio) {
+ newValue = null;
+ } else {
+ audio = true;
+ newValue = `[sound:${entryFormat.audioFile}]`;
}
+ break;
+ case "dictionaryFormat":
+ newValue = entryFormat.dictionaryForm;
+ break;
+ case "word":
+ newValue = entryFormat.word;
+ break;
+ case "reading":
+ newValue = entryFormat.reading;
+ break;
+ case "saveNotes":
+ newValue = entryFormat.saveNotes;
+ break;
+ case "sentence":
+ newValue = entryFormat.sentence;
+ break;
+ case "sentenceWithBlank":
+ newValue = entryFormat.sentenceWithBlank;
+ break;
+ case "sourceUrl":
+ newValue = entryFormat.sourceUrl;
+ break;
+ case "pageTitle":
+ newValue = entryFormat.pageTitle;
+ break;
+ case "definition":
+ newValue = entryFormat.definition;
+ break;
+ case "frequency":
+ newValue = entryFormat.frequency;
+ break;
+ case "pitch":
+ newValue = entryFormat.pitch;
+ break;
}
- const tags = config.ankiTags;
- promises.push(this.makeCall('addNote', {fields, tags}));
-
- // If Audio
- if (audio && !isNoAudio) {
- promises.push(this.makeCall('downloadAudio', {filename: entryFormat.audioFile, url: entryFormat.audioUrl}));
+ if (newValue !== null) {
+ newValues.push(newValue);
}
+ }
- return Promise.all(promises);
+ newValues = newValues.filter((value) => value !== null);
+ if (newValues.length) {
+ fields[key] = newValues.join(" ");
+ }
}
+ const tags = config.ankiTags;
+ promises.push(this.makeCall("addNote", { fields, tags }));
+
+ // If Audio
+ if (audio && !isNoAudio) {
+ promises.push(
+ this.makeCall("downloadAudio", {
+ filename: entryFormat.audioFile,
+ url: entryFormat.audioUrl,
+ })
+ );
+ }
- // entry = Contains the work lookup info (kana, kanji, def)
- // word = Highlighted Word
- // sentence = The sentence containing the highlighted word
- // sentenceWBlank = Like sentence except the highlighted word is replaced with blanks
- // saveKana = Replace kanji with kana (that is, $d=$r)
- // saveFormat = Token-based save format
- static async makeTextOptions(
- entry: SearchResults,
- word: string,
- sentence: string,
- sentenceWithBlank: string,
- pageTitle: string,
- sourceUrl: string,
- saveKana: boolean,
- saveFormat,
- config: Config,
- rebuilt: RikaiController,
- ): Promise {
- if (!isDictionaryResult(entry)) return;
-
- let entryData;
-
- if ((entry == null) || (entry.data == null)) {
- return null;
- }
-
- // Example of what entry.data[0][0] looks like (linebreak added by me):
- // 乃 [の] /(prt,uk) indicates possessive/verb and adjective nominalizer (nominaliser)/substituting
- // for "ga" in subordinate phrases/indicates a confident conclusion/emotional emphasis (sentence end) (fem)/(P)/
+ return Promise.all(promises);
+ }
+
+ async downloadAudio(entry: SearchResults) {
+ if (!isDictionaryResult(entry)) return;
+ if (!entry?.data) return;
+ if (await AudioPlayer.isNoAudio(entry)) return;
+
+ const audioUrl = AudioPlayer.getAudioUrl(entry);
+
+ let [, dictionaryForm, reading] = entry.data[0][0].match(
+ /^(.+?)\s+(?:\[(.*?)\])?\s*\/(.+)\//
+ );
+
+ const audioFile = `${reading} - ${dictionaryForm}.mp3`;
+
+ return this.makeCall("downloadAudio", {
+ filename: audioFile,
+ url: audioUrl,
+ });
+ }
+
+ // entry = Contains the work lookup info (kana, kanji, def)
+ // word = Highlighted Word
+ // sentence = The sentence containing the highlighted word
+ // sentenceWBlank = Like sentence except the highlighted word is replaced with blanks
+ // saveKana = Replace kanji with kana (that is, $d=$r)
+ // saveFormat = Token-based save format
+ static async makeTextOptions(
+ entry: SearchResults,
+ word: string,
+ sentence: string,
+ sentenceWithBlank: string,
+ pageTitle: string,
+ sourceUrl: string,
+ saveKana: boolean,
+ saveFormat,
+ config: Config,
+ rebuilt: RikaiController
+ ): Promise {
+ if (!isDictionaryResult(entry)) return;
+
+ let entryData;
+
+ if (entry == null || entry.data == null) {
+ return null;
+ }
- // Extract needed data from the hilited entry
- // entryData[0] = kanji/kana + kana + definition
- // entryData[1] = kanji (or kana if no kanji)
- // entryData[2] = kana (null if no kanji)
- // entryData[3] = definition
+ // Example of what entry.data[0][0] looks like (linebreak added by me):
+ // 乃 [の] /(prt,uk) indicates possessive/verb and adjective nominalizer (nominaliser)/substituting
+ // for "ga" in subordinate phrases/indicates a confident conclusion/emotional emphasis (sentence end) (fem)/(P)/
- entryData = entry.data[0][0].match(/^(.+?)\s+(?:\[(.*?)\])?\s*\/(.+)\//);
- let [_, dictionaryForm, reading, definition] = entryData;
+ // Extract needed data from the hilited entry
+ // entryData[0] = kanji/kana + kana + definition
+ // entryData[1] = kanji (or kana if no kanji)
+ // entryData[2] = kana (null if no kanji)
+ // entryData[3] = definition
- // Does the user want to use the reading in place of kanji for the $d token?
- if (reading && saveKana) {
- dictionaryForm = reading;
- }
+ entryData = entry.data[0][0].match(/^(.+?)\s+(?:\[(.*?)\])?\s*\/(.+)\//);
+ let [_, dictionaryForm, reading, definition] = entryData;
- // Ensure that reading is never blank
- if (!reading) {
- reading = dictionaryForm;
- }
+ // Does the user want to use the reading in place of kanji for the $d token?
+ if (reading && saveKana) {
+ dictionaryForm = reading;
+ }
- const audioFile = reading + ' - ' + entryData[1] + '.mp3';
+ // Ensure that reading is never blank
+ if (!reading) {
+ reading = dictionaryForm;
+ }
- if (!config.epwingMode) {
- definition = entryData[3].replace(/\//g, "; ");
+ const audioFile = reading + " - " + entryData[1] + ".mp3";
- // Remove word type indicators? [example: (v1,n)]
- if (!config.showWordTypeIndicator) {
- definition = definition.replace(/^\([^)]+\)\s*/, '');
- }
+ if (!config.epwingMode) {
+ definition = entryData[3].replace(/\//g, "; ");
- // Remove popular indicator? [example: (P)]
- if (!config.showPopularWordIndicator) {
- definition = definition.replace('; (P)', '');
- }
- }
+ // Remove word type indicators? [example: (v1,n)]
+ if (!config.showWordTypeIndicator) {
+ definition = definition.replace(/^\([^)]+\)\s*/, "");
+ }
- // Get the page title
- pageTitle = pageTitle.replace(/ \- Mozilla Firefox$/, '');
-
- // Frequency
- // const frequency = rcxMain.getFreq(dictionaryForm, reading, true);
- const frequency = await rebuilt.getFrequency(dictionaryForm, reading, true, word);
-
- // Pitch accent
- // const pitch = rcxMain.getPitchAccent(dictionaryForm, reading);
- const pitch = await rebuilt.getPitch(dictionaryForm, reading);
-
- const saveNotes = null;
- const audioUrl = AudioPlayer.getAudioUrl(entry);
- return {
- audioFile,
- audioUrl,
- dictionaryForm,
- word,
- reading,
- saveNotes,
- sentence,
- sentenceWithBlank,
- sourceUrl,
- pageTitle,
- definition,
- frequency,
- pitch
- };
+ // Remove popular indicator? [example: (P)]
+ if (!config.showPopularWordIndicator) {
+ definition = definition.replace("; (P)", "");
+ }
}
+
+ // Get the page title
+ pageTitle = pageTitle.replace(/ \- Mozilla Firefox$/, "");
+
+ // Frequency
+ // const frequency = rcxMain.getFreq(dictionaryForm, reading, true);
+ const frequency = await rebuilt.getFrequency(
+ dictionaryForm,
+ reading,
+ true,
+ word
+ );
+
+ // Pitch accent
+ // const pitch = rcxMain.getPitchAccent(dictionaryForm, reading);
+ const pitch = await rebuilt.getPitch(dictionaryForm, reading);
+
+ const saveNotes = null;
+ const audioUrl = AudioPlayer.getAudioUrl(entry);
+ return {
+ audioFile,
+ audioUrl,
+ dictionaryForm,
+ word,
+ reading,
+ saveNotes,
+ sentence,
+ sentenceWithBlank,
+ sourceUrl,
+ pageTitle,
+ definition,
+ frequency,
+ pitch,
+ };
+ }
}
diff --git a/src/background.ts b/src/background.ts
index d78645c..e835a1e 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -1,11 +1,11 @@
-import defaultConfig, {Config} from './defaultConfig'
-import autobind from '../lib/autobind'
-import AnkiImport from './AnkiImport';
-import FrequencyDb from './database/FrequencyDb'
-import PitchDb from './database/PitchDb';
-import IndexedDictionary from './database/IndexedDictionary';
-import DictionaryLookup from './DictionaryLookup';
-import AudioPlayer from './AudioPlayer';
+import defaultConfig, {Config} from "./defaultConfig";
+import autobind from "../lib/autobind";
+import AnkiImport from "./AnkiImport";
+import FrequencyDb from "./database/FrequencyDb";
+import PitchDb from "./database/PitchDb";
+import IndexedDictionary from "./database/IndexedDictionary";
+import DictionaryLookup from "./DictionaryLookup";
+import AudioPlayer from "./AudioPlayer";
import {DictionaryDefinition} from "./interfaces/DictionaryDefinition";
import Utils from "./Utils";
import {installFrequencyDb, installPitchDb} from "./initializers";
@@ -15,210 +15,246 @@ let installedDictionaries: DictionaryDefinition[] = [];
let optionsPort;
export class RikaiController {
- private enabled: boolean = false;
- private isSetUp: boolean = false;
- private DictionaryLookup: DictionaryLookup;
- private config: Config;
+ private enabled: boolean = false;
+ private isSetUp: boolean = false;
+ private DictionaryLookup: DictionaryLookup;
+ private config: Config;
- constructor() {
- autobind(this);
+ constructor() {
+ autobind(this);
- this.config = defaultConfig;
- }
-
- setup() {
- if (this.isSetUp) return;
+ this.config = defaultConfig;
+ }
- this.isSetUp = true;
- this.DictionaryLookup = new DictionaryLookup(this.config);
- }
+ setup() {
+ if (this.isSetUp) return;
- async enable() {
- this.setup();
-
- if (this.enabled === true) {
- return this.disable();
- }
+ this.isSetUp = true;
+ this.DictionaryLookup = new DictionaryLookup(this.config);
+ }
- browser.storage.local.set({enabled: true});
- browser.storage.sync.get('config').then((storage: Storage & { config: Config }) => {
- if (!storage.config) return;
- const config: Config = storage.config;
+ async enable() {
+ this.setup();
- this.updateConfig(config);
+ if (this.enabled === true) {
+ return this.disable();
+ }
- if (typeof config.startWithSanseido !== 'undefined') {
- browser.storage.local.set({sanseidoMode: config.startWithSanseido});
- }
+ browser.storage.local.set({ enabled: true });
+ browser.storage.sync
+ .get("config")
+ .then((storage: Storage & { config: Config }) => {
+ if (!storage.config) return;
+ const config: Config = storage.config;
- if (typeof config.startWithEpwing !== 'undefined') {
- browser.storage.local.set({epwingMode: config.startWithEpwing});
- }
- });
+ this.updateConfig(config);
- browser.storage.local.get('installedDictionaries').then(config => {
- if (config.installedDictionaries) this.updateDictionaries(config.installedDictionaries);
- });
-
- browser.browserAction.setIcon({
- path: {
- 48: 'icons/smile_star.png'
- }
- });
+ if (typeof config.startWithSanseido !== "undefined") {
+ browser.storage.local.set({ sanseidoMode: config.startWithSanseido });
+ }
- this.enabled = true;
- }
+ if (typeof config.startWithEpwing !== "undefined") {
+ browser.storage.local.set({ epwingMode: config.startWithEpwing });
+ }
+ });
- async disable() {
- browser.storage.local.set({enabled: false});
+ browser.storage.local.get("installedDictionaries").then((config) => {
+ if (config.installedDictionaries)
+ this.updateDictionaries(config.installedDictionaries);
+ });
- browser.browserAction.setIcon({
- path: {
- 48: 'icons/smile.png'
- }
- });
+ browser.browserAction.setIcon({
+ path: {
+ 48: "icons/smile_star.png",
+ },
+ });
- this.enabled = false;
- }
+ this.enabled = true;
+ }
- getDictionaryLookup() {
- this.setup();
+ async disable() {
+ browser.storage.local.set({ enabled: false });
- return this.DictionaryLookup;
- }
+ browser.browserAction.setIcon({
+ path: {
+ 48: "icons/smile.png",
+ },
+ });
- async wordSearch(text) {
- return this.getDictionaryLookup().search(text);
- }
+ this.enabled = false;
+ }
- async getReadingCount(reading) {
- return this.getDictionaryLookup().getReadingCount(reading);
- }
+ getDictionaryLookup() {
+ this.setup();
- updateConfig(config) {
- if (this.config.epwingMode !== undefined) {
- config.epwingMode = this.config.epwingMode;
- }
- this.config = config || defaultConfig;
- this.getDictionaryLookup().updateConfig(config);
- }
+ return this.DictionaryLookup;
+ }
- updateDictionaries(dictionaries) {
- this.getDictionaryLookup().updateDictionaries(dictionaries);
- }
+ async wordSearch(text) {
+ return this.getDictionaryLookup().search(text);
+ }
- setEpwingMode(epwingMode) {
- this.config.epwingMode = epwingMode;
- }
+ async getReadingCount(reading) {
+ return this.getDictionaryLookup().getReadingCount(reading);
+ }
- async sendToAnki(content) {
- const {entry, word, sentence, sentenceWithBlank, pageTitle, sourceUrl} = content;
- const entryFormat = await AnkiImport.makeTextOptions(entry, word, sentence, sentenceWithBlank, pageTitle, sourceUrl, false, false, this.config, this);
- ankiImport.addNote(entryFormat, entry, this.config);
- playAudio([entry]);
+ updateConfig(config) {
+ if (this.config.epwingMode !== undefined) {
+ config.epwingMode = this.config.epwingMode;
}
+ this.config = config || defaultConfig;
+ this.getDictionaryLookup().updateConfig(config);
+ }
+
+ updateDictionaries(dictionaries) {
+ this.getDictionaryLookup().updateDictionaries(dictionaries);
+ }
+
+ setEpwingMode(epwingMode) {
+ this.config.epwingMode = epwingMode;
+ }
+
+ async sendToAnki(content) {
+ const {
+ entry,
+ word,
+ sentence,
+ sentenceWithBlank,
+ pageTitle,
+ sourceUrl,
+ } = content;
+ const entryFormat = await AnkiImport.makeTextOptions(
+ entry,
+ word,
+ sentence,
+ sentenceWithBlank,
+ pageTitle,
+ sourceUrl,
+ false,
+ false,
+ this.config,
+ this
+ );
+ ankiImport.addNote(entryFormat, entry, this.config);
+ playAudio([entry]);
+ }
+
+ async getFrequencyNumber(content) {
+ return frequencyDb.findFrequencyForExpression(content).then((results) => {
+ return results[0];
+ });
+ }
- async getFrequencyNumber(content) {
- return frequencyDb.findFrequencyForExpression(content).then(results => {
- return results[0];
- });
- }
+ async getPitch(expression, reading) {
+ return pitchDb
+ .getPitchAccent(expression, reading)
+ .then((results) => results[0]);
+ }
- async getPitch(expression, reading) {
- return pitchDb.getPitchAccent(expression, reading).then(results => results[0]);
+ async getEpwingDefinition(expression) {
+ if (!this.config.epwingDictionaries.length) {
+ return "No dictionaries found";
}
- async getEpwingDefinition(expression) {
- if (!this.config.epwingDictionaries.length) {
- return 'No dictionaries found';
+ const message = {
+ book_path: this.config.epwingDictionaries[0].path,
+ options: {
+ // 'gaiji': true,
+ "hit-num": true,
+ "html-sub": true,
+ "html-sup": true,
+ // 'no-header': true,
+ },
+ input: expression,
+ };
+
+ return browser.runtime.sendNativeMessage("eplkup", message).then(
+ (result: { output: any; error?: string }) => {
+ if (result.error) {
+ return `A problem occurred: ${result.error}`;
}
- const message = {
- 'book_path': this.config.epwingDictionaries[0].path,
- 'options': {
- // 'gaiji': true,
- 'hit-num': true,
- 'html-sub': true,
- 'html-sup': true,
- // 'no-header': true,
- },
- 'input': expression,
- };
-
- return browser.runtime.sendNativeMessage('eplkup', message).then((result: { output: any, error?: string }) => {
- if (result.error) {
- return `A problem occurred: ${result.error}`;
- }
-
- return result.output;
- }, f => { return `A problem has occurred. Have you set up the Epwing program? ${f}`; });
- }
-
- async getFrequency(inExpression, inReading, useHighlightedWord, highlightedWord) {
- const expression = inExpression;
- const reading = inReading;
-
- let freqNum = "";
- let freqStr = "";
- let freqBasedOnReading = false;
-
- try {
- const readingFreqNum = await this.getFrequencyNumber(reading);
- let readingSameAsExpression = (expression === reading);
- let expressionFreqNum = readingFreqNum;
-
- // Don't waste time looking up the expression freq if expression is same as the reading
- if (!readingSameAsExpression) {
- expressionFreqNum = await this.getFrequencyNumber(expression);
- }
-
- // If frequency was found for either frequency or reading
- if ((expressionFreqNum.length > 0) || (readingFreqNum.length > 0)) {
- // If the highlighted word does not contain kanji, and the reading is unique,
- // use the reading frequency
- if (useHighlightedWord
- && !readingSameAsExpression
- && !Utils.containsKanji(highlightedWord)
- && (readingFreqNum.length > 0)
- && (await this.getReadingCount(reading) === 1)) {
- freqNum = readingFreqNum;
- freqBasedOnReading = true;
- }
-
- // If expression and reading are the same, use the reading frequency
- if ((freqNum.length == 0)
- && readingSameAsExpression
- && (readingFreqNum.length > 0)) {
- freqNum = readingFreqNum;
- }
-
- // If the expression is in the freq db, use the expression frequency
- if ((freqNum.length == 0) && (expressionFreqNum.length > 0)) {
- freqNum = expressionFreqNum;
- }
-
- // If the reading is in the freq db, use the the reading frequency
- if ((freqNum.length == 0) && (readingFreqNum.length > 0)) {
- freqNum = readingFreqNum;
- freqBasedOnReading = true;
- }
- }
-
- freqStr = freqNum;
+ return result.output;
+ },
+ (f) => {
+ return `A problem has occurred. Have you set up the Epwing program? ${f}`;
+ }
+ );
+ }
+
+ async getFrequency(
+ inExpression,
+ inReading,
+ useHighlightedWord,
+ highlightedWord
+ ) {
+ const expression = inExpression;
+ const reading = inReading;
+
+ let freqNum = "";
+ let freqStr = "";
+ let freqBasedOnReading = false;
+
+ try {
+ const readingFreqNum = await this.getFrequencyNumber(reading);
+ let readingSameAsExpression = expression === reading;
+ let expressionFreqNum = readingFreqNum;
+
+ // Don't waste time looking up the expression freq if expression is same as the reading
+ if (!readingSameAsExpression) {
+ expressionFreqNum = await this.getFrequencyNumber(expression);
+ }
+
+ // If frequency was found for either frequency or reading
+ if (expressionFreqNum.length > 0 || readingFreqNum.length > 0) {
+ // If the highlighted word does not contain kanji, and the reading is unique,
+ // use the reading frequency
+ if (
+ useHighlightedWord &&
+ !readingSameAsExpression &&
+ !Utils.containsKanji(highlightedWord) &&
+ readingFreqNum.length > 0 &&
+ (await this.getReadingCount(reading)) === 1
+ ) {
+ freqNum = readingFreqNum;
+ freqBasedOnReading = true;
+ }
- // Indicate that frequency was based on the reading
- if (freqBasedOnReading) {
- freqStr += "_r";
- }
+ // If expression and reading are the same, use the reading frequency
+ if (
+ freqNum.length == 0 &&
+ readingSameAsExpression &&
+ readingFreqNum.length > 0
+ ) {
+ freqNum = readingFreqNum;
}
- catch (ex) {
- //@TODO: Throw an error here?
- // Components.utils.reportError("getFreq() Exception: " + ex);
- freqStr = "";
+
+ // If the expression is in the freq db, use the expression frequency
+ if (freqNum.length == 0 && expressionFreqNum.length > 0) {
+ freqNum = expressionFreqNum;
}
- return freqStr;
+ // If the reading is in the freq db, use the the reading frequency
+ if (freqNum.length == 0 && readingFreqNum.length > 0) {
+ freqNum = readingFreqNum;
+ freqBasedOnReading = true;
+ }
+ }
+
+ freqStr = freqNum;
+
+ // Indicate that frequency was based on the reading
+ if (freqBasedOnReading) {
+ freqStr += "_r";
+ }
+ } catch (ex) {
+ //@TODO: Throw an error here?
+ // Components.utils.reportError("getFreq() Exception: " + ex);
+ freqStr = "";
}
+
+ return freqStr;
+ }
}
const ankiImport = new AnkiImport();
@@ -230,181 +266,221 @@ pitchDb.open();
const controller = new RikaiController();
function playAudio(entry) {
- if (!entry) return;
+ if (!entry) return;
- AudioPlayer.play(entry, config);
+ AudioPlayer.play(entry, config);
}
browser.runtime.onMessage.addListener(async (message) => {
- const {type, content} = message;
+ const { type, content } = message;
+
+ switch (type) {
+ case "wordSearch":
+ return controller.wordSearch(content).then(
+ (response) => {
+ return { response };
+ },
+ (f) => console.log(f)
+ );
+ case "getEpwingDefinition":
+ return controller.getEpwingDefinition(content).then(
+ (response) => {
+ return { response };
+ },
+ (f) => {
+ console.log(f);
+ }
+ );
+ case "getPitch":
+ return controller
+ .getPitch(content.expression, content.reading)
+ .then((response) => {
+ return { response };
+ });
+ case "getFrequency":
+ return controller
+ .getFrequency(
+ content.inExpression,
+ content.inReading,
+ content.useHighlightedWord,
+ content.highlightedWord
+ )
+ .then((response) => {
+ return { response };
+ });
+ case "getReadingCount":
+ return controller.getReadingCount(content).then((response) => {
+ return { response };
+ });
+ case "playAudio":
+ playAudio(content);
+ await ankiImport.downloadAudio(content);
+ return { response: "" };
+ case "sendToAnki":
+ controller.sendToAnki(content);
+ return 0;
+ case "selectNextDictionary":
+ controller.getDictionaryLookup().selectNextDictionary();
+ return { response: null };
+ }
+});
+
+browser.runtime.onConnect.addListener((port) => {
+ optionsPort = port;
+
+ optionsPort.onMessage.addListener((message) => {
+ const { type, content } = message;
switch (type) {
- case "wordSearch":
- return controller.wordSearch(content).then(response => {
- return {response};
- }, f => console.log(f));
- case "getEpwingDefinition":
- return controller.getEpwingDefinition(content).then(response => {
- return {response};
- }, f => { console.log(f) });
- case "getPitch":
- return controller.getPitch(content.expression, content.reading).then(response => {
- return {response}
- });
- case "getFrequency":
- return controller.getFrequency(content.inExpression, content.inReading, content.useHighlightedWord, content.highlightedWord)
- .then(response => {
- return {response}
- });
- case "getReadingCount":
- return controller.getReadingCount(content).then(response => {
- return {response};
+ case "deleteDictionary":
+ const dictionary = new IndexedDictionary(content.id);
+ dictionary.open().then(async () => {
+ dictionary.deleteDatabase();
+ });
+ break;
+
+ case "importDictionary":
+ const { name, id, url } = content;
+ const testDb = new IndexedDictionary(id);
+ let hasType, isNameDictionary, isKanjiDictionary;
+
+ testDb.open().then(async () => {
+ let startTime;
+ let lastPercent = 0;
+ const progressCallback = (item, total) => {
+ let percentage = Math.floor((item / total) * 100);
+ if (percentage > lastPercent) {
+ optionsPort.postMessage({
+ type: "DICTIONARY_IMPORT_UPDATE",
+ content: { id, item, total },
+ });
+ }
+
+ lastPercent = percentage;
+ };
+
+ return fetch(url)
+ .then((response) => response.json())
+ .then((json) => {
+ hasType = json.hasType;
+ isKanjiDictionary = json.isKanjiDictionary;
+ isNameDictionary = json.isNameDictionary;
+
+ startTime = new Date().getTime();
+ return testDb.import(json.entries, progressCallback);
+ })
+ .then(() => {
+ const endTime = new Date().getTime();
+ console.log(
+ `Download took ${(endTime - startTime) / 1000} seconds`
+ );
+
+ installedDictionaries.push({
+ id,
+ name,
+ hasType,
+ isNameDictionary,
+ isKanjiDictionary,
+ });
+ // @ts-ignore
+ browser.storage.local.set({ installedDictionaries });
});
- case "playAudio":
- playAudio(content);
- return {response: ''};
- case "sendToAnki":
- controller.sendToAnki(content);
- return 0;
- case 'selectNextDictionary':
- controller.getDictionaryLookup().selectNextDictionary();
- return {response: null};
+ });
}
-});
-
-browser.runtime.onConnect.addListener(port => {
- optionsPort = port;
-
- optionsPort.onMessage.addListener(message => {
- const {type, content} = message;
-
- switch (type) {
- case "deleteDictionary":
- const dictionary = new IndexedDictionary(content.id);
- dictionary.open().then(async () => {
- dictionary.deleteDatabase();
- });
- break;
-
- case "importDictionary":
- const {name, id, url} = content;
- const testDb = new IndexedDictionary(id);
- let hasType, isNameDictionary, isKanjiDictionary;
-
- testDb.open().then(async () => {
- let startTime;
- let lastPercent = 0;
- const progressCallback = (item, total) => {
- let percentage = Math.floor((item / total) * 100);
- if (percentage > lastPercent) {
- optionsPort.postMessage({
- type: 'DICTIONARY_IMPORT_UPDATE',
- content: {id, item, total}
- });
- }
-
- lastPercent = percentage;
- };
-
- return fetch(url).then(response => response.json())
- .then(json => {
- hasType = json.hasType;
- isKanjiDictionary = json.isKanjiDictionary;
- isNameDictionary = json.isNameDictionary;
-
- startTime = new Date().getTime();
- return testDb.import(json.entries, progressCallback)
- })
- .then(() => {
- const endTime = new Date().getTime();
- console.log(`Download took ${(endTime - startTime) / 1000} seconds`);
-
- installedDictionaries.push({id, name, hasType, isNameDictionary, isKanjiDictionary});
- // @ts-ignore
- browser.storage.local.set({installedDictionaries})
- })
- });
- }
- });
+ });
});
browser.browserAction.onClicked.addListener(controller.enable);
browser.storage.onChanged.addListener((changes, areaName) => {
- if (areaName !== 'sync' && areaName !== 'local') return;
-
- if (changes.config) {
- config = changes.config.newValue;
-
- controller.updateConfig(config);
- } else if (changes.installedDictionaries) {
- installedDictionaries = changes.installedDictionaries.newValue;
- controller.updateDictionaries(installedDictionaries);
- } else if (changes.epwingMode) {
- controller.setEpwingMode(changes.epwingMode.newValue);
- }
+ if (areaName !== "sync" && areaName !== "local") return;
+
+ if (changes.config) {
+ config = changes.config.newValue;
+
+ controller.updateConfig(config);
+ } else if (changes.installedDictionaries) {
+ installedDictionaries = changes.installedDictionaries.newValue;
+ controller.updateDictionaries(installedDictionaries);
+ } else if (changes.epwingMode) {
+ controller.setEpwingMode(changes.epwingMode.newValue);
+ }
});
browser.browserAction.setIcon({
- path: {
- 48: 'icons/smile.png'
- }
+ path: {
+ 48: "icons/smile.png",
+ },
});
-browser.storage.local.set({enabled: false});
-browser.storage.local.get('installedDictionaries').then((config: Storage & { installedDictionaries?: DictionaryDefinition[] }) => {
- if (config.installedDictionaries) {
+browser.storage.local.set({ enabled: false });
+browser.storage.local
+ .get("installedDictionaries")
+ .then(
+ (config: Storage & { installedDictionaries?: DictionaryDefinition[] }) => {
+ if (config.installedDictionaries) {
installedDictionaries = config.installedDictionaries;
+ }
}
-});
+ );
-browser.runtime.onInstalled.addListener(async ({id, previousVersion, reason}) => {
+browser.runtime.onInstalled.addListener(
+ async ({ id, previousVersion, reason }) => {
//Frequency Information
installFrequencyDb(frequencyDb);
//Import pitch DB on first install
installPitchDb(pitchDb);
- browser.storage.sync.get('config').then(({config}: Storage & {config: Config}) => {
+ browser.storage.sync
+ .get("config")
+ .then(({ config }: Storage & { config: Config }) => {
if (!config) return;
if (config.openChangelogOnUpdate) {
- const optionsPageUrl = browser.extension.getURL('options/options.html');
+ const optionsPageUrl = browser.extension.getURL(
+ "options/options.html"
+ );
- if (reason === 'update') {
- browser.tabs.create({url: `${optionsPageUrl}#changelog`});
- }
+ if (reason === "update") {
+ browser.tabs.create({ url: `${optionsPageUrl}#changelog` });
+ }
}
let newConfigs = false;
for (const key in defaultConfig) {
- if(typeof config[key] === 'undefined') {
- newConfigs = true;
- config[key] = defaultConfig[key];
- }
+ if (typeof config[key] === "undefined") {
+ newConfigs = true;
+ config[key] = defaultConfig[key];
+ }
}
if (newConfigs) {
- // @ts-ignore
- browser.storage.sync.set({ config });
+ // @ts-ignore
+ browser.storage.sync.set({ config });
}
- });
-});
+ });
+ }
+);
// @ts-ignore
browser.contextMenus.removeAll();
// @ts-ignore
browser.contextMenus.create({
- title: "Options",
- contexts: ["browser_action"],
- onclick: () => {
- browser.tabs.create({url: browser.extension.getURL('options/options.html')});
- }
+ title: "Options",
+ contexts: ["browser_action"],
+ onclick: () => {
+ browser.tabs.create({
+ url: browser.extension.getURL("options/options.html"),
+ });
+ },
});
// @ts-ignore
browser.contextMenus.create({
- title: "Visual Novel Hook",
- contexts: ["browser_action"],
- onclick: () => {
- browser.tabs.create({url: browser.extension.getURL('vn-hook/index.html')});
- }
+ title: "Visual Novel Hook",
+ contexts: ["browser_action"],
+ onclick: () => {
+ browser.tabs.create({
+ url: browser.extension.getURL("vn-hook/index.html"),
+ });
+ },
});