1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-12 08:54:00 +02:00
joplin/packages/lib/services/spellChecker/SpellCheckerService.ts

203 lines
5.1 KiB
TypeScript
Raw Normal View History

2020-11-05 18:58:23 +02:00
import Setting from '../../models/Setting';
import CommandService from '../CommandService';
import SpellCheckerServiceDriverBase from './SpellCheckerServiceDriverBase';
import { _, countryDisplayName } from '../../locale';
import KvStore from '../KvStore';
2020-11-05 18:58:23 +02:00
export default class SpellCheckerService {
private driver_:SpellCheckerServiceDriverBase;
private latestSelectedLanguages_:string[] = [];
2020-11-05 18:58:23 +02:00
private static instance_:SpellCheckerService;
public static instance():SpellCheckerService {
if (this.instance_) return this.instance_;
this.instance_ = new SpellCheckerService();
return this.instance_;
}
public async initialize(driver:SpellCheckerServiceDriverBase) {
this.driver_ = driver;
this.latestSelectedLanguages_ = await this.loadLatestSelectedLanguages();
2020-11-05 18:58:23 +02:00
this.setupDefaultLanguage();
this.applyStateToDriver();
}
private get defaultLanguage():string {
return 'en-US';
}
private async loadLatestSelectedLanguages():Promise<string[]> {
const result = await KvStore.instance().value<string>('spellCheckerService.latestSelectedLanguages');
if (!result) return [];
return JSON.parse(result);
}
private async addLatestSelectedLanguage(language:string) {
const languages = this.latestSelectedLanguages_.slice();
if (languages.length > 5) languages.splice(0, 1);
if (languages.includes(language)) {
languages.splice(languages.indexOf(language), 1);
}
languages.splice(0, 0, language);
this.latestSelectedLanguages_ = languages;
await KvStore.instance().setValue('spellCheckerService.latestSelectedLanguages', JSON.stringify(this.latestSelectedLanguages_));
}
2020-11-05 18:58:23 +02:00
public setupDefaultLanguage() {
if (!Setting.value('spellChecker.language')) {
const l = this.driver_.language;
this.setLanguage(l ? l : this.defaultLanguage);
}
}
public get availableLanguages():string[] {
return this.driver_.availableLanguages;
}
private applyStateToDriver() {
this.driver_.setLanguage(this.enabled ? this.language : '');
}
public setLanguage(language:string) {
Setting.setValue('spellChecker.language', language);
this.applyStateToDriver();
this.addLatestSelectedLanguage(language);
2020-11-05 18:58:23 +02:00
}
public get language():string {
return Setting.value('spellChecker.language');
}
public get enabled():boolean {
return Setting.value('spellChecker.enabled');
}
public toggleEnabled() {
Setting.toggle('spellChecker.enabled');
this.applyStateToDriver();
}
private async addToDictionary(language:string, word:string) {
this.driver_.addWordToSpellCheckerDictionary(language, word);
}
public contextMenuItems(misspelledWord:string, dictionarySuggestions:string[]):any[] {
2020-11-05 18:58:23 +02:00
if (!misspelledWord) return [];
const output = [];
output.push({ type: 'separator' });
2020-11-05 18:58:23 +02:00
if (dictionarySuggestions.length) {
for (const suggestion of dictionarySuggestions) {
output.push({
2020-11-05 18:58:23 +02:00
label: suggestion,
click: () => {
CommandService.instance().execute('replaceSelection', suggestion);
},
});
2020-11-05 18:58:23 +02:00
}
} else {
output.push({
2020-11-05 18:58:23 +02:00
label: `(${_('No suggestions')})`,
enabled: false,
click: () => {},
});
2020-11-05 18:58:23 +02:00
}
output.push({ type: 'separator' });
2020-11-05 18:58:23 +02:00
output.push({
2020-11-05 18:58:23 +02:00
label: _('Add to dictionary'),
click: () => {
this.addToDictionary(this.language, misspelledWord);
},
});
2020-11-05 18:58:23 +02:00
return output;
}
private changeLanguageMenuItem(language:string, enabled:boolean, checked:boolean) {
return {
label: countryDisplayName(language),
type: 'radio',
checked: checked,
enabled: enabled,
click: () => {
this.setLanguage(language);
},
};
}
2020-11-05 18:58:23 +02:00
private changeLanguageMenuItems(selectedLanguage:string, enabled:boolean) {
const languageMenuItems = [];
for (const locale of this.driver_.availableLanguages) {
languageMenuItems.push(this.changeLanguageMenuItem(locale, enabled, locale === selectedLanguage));
2020-11-05 18:58:23 +02:00
}
languageMenuItems.sort((a:any, b:any) => {
return a.label < b.label ? -1 : +1;
});
return languageMenuItems;
}
public spellCheckerConfigMenuItems(selectedLanguage:string, useSpellChecker:boolean) {
const latestLanguageItems = this.latestSelectedLanguages_.map((language:string) => {
return this.changeLanguageMenuItem(language, true, language === selectedLanguage);
});
if (latestLanguageItems.length) latestLanguageItems.splice(0, 0, { type: 'separator' } as any);
latestLanguageItems.sort((a:any, b:any) => {
return a.label < b.label ? -1 : +1;
});
return [
{
label: _('Use spell checker'),
type: 'checkbox',
checked: useSpellChecker,
click: () => {
this.toggleEnabled();
},
},
...latestLanguageItems,
{
type: 'separator',
},
// Can be removed once it does work
{
label: '⚠ Spell checker doesn\'t work in Markdown editor ⚠',
enabled: false,
},
{
type: 'separator',
},
{
label: _('Change language'),
submenu: this.changeLanguageMenuItems(selectedLanguage, useSpellChecker),
},
];
2020-11-05 18:58:23 +02:00
}
public spellCheckerConfigMenuItem(selectedLanguage:string, useSpellChecker:boolean) {
return {
2020-11-05 18:58:23 +02:00
label: _('Spell checker'),
submenu: this.spellCheckerConfigMenuItems(selectedLanguage, useSpellChecker),
};
2020-11-05 18:58:23 +02:00
}
}