aboutsummaryrefslogtreecommitdiffstats
path: root/src/webview/spellchecker.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/webview/spellchecker.js')
-rw-r--r--src/webview/spellchecker.js111
1 files changed, 70 insertions, 41 deletions
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index a504a4039..b0192b7ef 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -1,63 +1,92 @@
1import { SpellCheckHandler } from 'electron-spellchecker'; 1import { webFrame } from 'electron';
2import fs from 'fs';
3import path from 'path';
4import { SpellCheckerProvider } from 'electron-hunspell';
2 5
3import { isMac } from '../environment'; 6import { DICTIONARY_PATH } from '../config';
4 7
5export default class Spellchecker { 8const debug = require('debug')('Franz:spellchecker');
6 isInitialized = false;
7 handler = null;
8 initRetries = 0;
9 DOMCheckInterval = null;
10 9
11 get inputs() { 10let provider;
12 return document.querySelectorAll('input[type="text"], [contenteditable="true"], textarea'); 11let currentDict;
13 } 12let _isEnabled = false;
14 13
15 initialize() { 14async function loadDictionaries() {
16 this.handler = new SpellCheckHandler(); 15 const rawList = fs.readdirSync(DICTIONARY_PATH);
17 16
18 if (!isMac) { 17 const dicts = rawList.filter(item => !item.startsWith('.') && fs.lstatSync(path.join(DICTIONARY_PATH, item)).isDirectory());
19 this.attach(); 18
20 } else { 19 debug('Found dictionaries', dicts);
21 this.isInitialized = true; 20
22 } 21 for (let i = 0; i < dicts.length; i += 1) {
22 const fileLocation = `${DICTIONARY_PATH}/${dicts[i]}/${dicts[i]}`;
23 debug('Trying to load', fileLocation);
24 // eslint-disable-next-line
25 await provider.loadDictionary(dicts[i], `${fileLocation}.dic`, `${fileLocation}.aff`);
23 } 26 }
27}
28
29export async function switchDict(locale) {
30 try {
31 debug('Trying to load dictionary', locale);
24 32
25 attach() { 33 if (!provider.availableDictionaries.includes(locale)) {
26 let initFailed = false; 34 console.warn('Dict not available', locale);
27 35
28 if (this.initRetries > 3) {
29 console.error('Could not initialize spellchecker');
30 return; 36 return;
31 } 37 }
32 38
33 try { 39 if (!provider) {
34 this.handler.attachToInput(); 40 console.warn('SpellcheckProvider not initialized');
35 this.handler.switchLanguage(navigator.language); 41
36 } catch (err) { 42 return;
37 initFailed = true;
38 this.initRetries = +1;
39 setTimeout(() => { this.attach(); console.warn('Spellchecker init failed, trying again in 5s'); }, 5000);
40 } 43 }
41 44
42 if (!initFailed) { 45 if (locale === currentDict) {
43 this.isInitialized = true; 46 console.warn('Dictionary is already used', currentDict);
47
48 return;
44 } 49 }
45 }
46 50
47 toggleSpellchecker(enable = false) { 51 provider.switchDictionary(locale);
48 this.inputs.forEach((input) => {
49 input.setAttribute('spellcheck', enable);
50 });
51 52
52 this.intervalHandler(enable); 53 debug('Switched dictionary to', locale);
54
55 currentDict = locale;
56 _isEnabled = true;
57 } catch (err) {
58 console.error(err);
53 } 59 }
60}
54 61
55 intervalHandler(enable) { 62export default async function initialize(languageCode = 'en-us') {
56 clearInterval(this.DOMCheckInterval); 63 try {
64 provider = new SpellCheckerProvider();
65 const locale = languageCode.toLowerCase();
57 66
58 if (enable) { 67 debug('Init spellchecker');
59 this.DOMCheckInterval = setInterval(() => this.toggleSpellchecker(enable), 30000); 68 await provider.initialize();
60 } 69 await loadDictionaries();
70
71 debug('Available spellchecker dictionaries', provider.availableDictionaries);
72
73 switchDict(locale);
74
75 return provider;
76 } catch (err) {
77 console.error(err);
78 return false;
61 } 79 }
62} 80}
63 81
82export function isEnabled() {
83 return _isEnabled;
84}
85
86export function disable() {
87 if (isEnabled()) {
88 webFrame.setSpellCheckProvider(currentDict, true, { spellCheck: () => true });
89 _isEnabled = false;
90 currentDict = null;
91 }
92}