2020-11-05 18:58:23 +02:00
|
|
|
// Provides spell checking feature via the native Electron built-in spell checker
|
|
|
|
|
2020-11-07 17:59:37 +02:00
|
|
|
import SpellCheckerServiceDriverBase from '@joplin/lib/services/spellChecker/SpellCheckerServiceDriverBase';
|
2020-11-05 18:58:23 +02:00
|
|
|
import bridge from '../bridge';
|
2023-07-27 17:05:56 +02:00
|
|
|
import Logger from '@joplin/utils/Logger';
|
2022-10-29 12:44:12 +02:00
|
|
|
import { languageCodeOnly, localesFromLanguageCode } from '@joplin/lib/locale';
|
2020-11-27 13:12:28 +02:00
|
|
|
|
|
|
|
const logger = Logger.create('SpellCheckerServiceDriverNative');
|
2020-11-05 18:58:23 +02:00
|
|
|
|
|
|
|
export default class SpellCheckerServiceDriverNative extends SpellCheckerServiceDriverBase {
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
private session(): any {
|
2020-11-05 18:58:23 +02:00
|
|
|
return bridge().window().webContents.session;
|
|
|
|
}
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
public get availableLanguages(): string[] {
|
2020-11-05 18:58:23 +02:00
|
|
|
return this.session().availableSpellCheckerLanguages;
|
|
|
|
}
|
|
|
|
|
2022-08-27 13:05:44 +02:00
|
|
|
// Language can be set to [] to disable spell-checking
|
|
|
|
public setLanguages(v: string[]) {
|
2022-10-29 12:44:12 +02:00
|
|
|
|
|
|
|
// Note that in order to validate the language we need ot set it on the
|
|
|
|
// session and check if Electron has thrown an exception or not. This is
|
|
|
|
// fine because the actual languages will be set below after the calls
|
|
|
|
// to this functions.
|
|
|
|
const validateLanguage = (v: string) => {
|
|
|
|
const languagesToTry = [
|
|
|
|
v,
|
|
|
|
languageCodeOnly(v),
|
|
|
|
].concat(localesFromLanguageCode(languageCodeOnly(v), this.availableLanguages));
|
|
|
|
|
|
|
|
for (const toTry of languagesToTry) {
|
|
|
|
try {
|
|
|
|
this.session().setSpellCheckerLanguages([toTry]);
|
|
|
|
return toTry;
|
|
|
|
} catch (error) {
|
|
|
|
logger.warn(`Failed to set language to "${toTry}". Will try the next one in this list: ${JSON.stringify(languagesToTry)}`);
|
|
|
|
logger.warn('Error was:', error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
const effectiveLanguages: string[] = [];
|
|
|
|
for (const language of v) {
|
|
|
|
const effectiveLanguage = validateLanguage(language);
|
|
|
|
if (effectiveLanguage) effectiveLanguages.push(effectiveLanguage);
|
|
|
|
}
|
|
|
|
|
2020-11-05 18:58:23 +02:00
|
|
|
// If we pass an empty array, it disables spell checking
|
|
|
|
// https://github.com/electron/electron/issues/25228
|
2022-10-29 12:44:12 +02:00
|
|
|
if (effectiveLanguages.length === 0) {
|
2020-11-27 20:15:22 +02:00
|
|
|
this.session().setSpellCheckerLanguages([]);
|
2020-11-27 13:12:28 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-29 12:44:12 +02:00
|
|
|
this.session().setSpellCheckerLanguages(effectiveLanguages);
|
|
|
|
logger.info(`Set effective languages to "${effectiveLanguages}"`);
|
2020-11-05 18:58:23 +02:00
|
|
|
}
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
public get language(): string {
|
2020-11-05 18:58:23 +02:00
|
|
|
const languages = this.session().getSpellCheckerLanguages();
|
|
|
|
return languages.length ? languages[0] : '';
|
|
|
|
}
|
|
|
|
|
2020-11-12 21:13:28 +02:00
|
|
|
public addWordToSpellCheckerDictionary(_language: string, word: string) {
|
2020-11-05 18:58:23 +02:00
|
|
|
// Actually on Electron all languages share the same dictionary, or
|
|
|
|
// perhaps it's added to the currently active language.
|
|
|
|
this.session().addWordToSpellCheckerDictionary(word);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|