diff options
author | 2018-11-30 14:32:45 +0100 | |
---|---|---|
committer | 2018-11-30 14:32:45 +0100 | |
commit | 3d87c0e45cead95ddb6c11fc6540b82e375bdcf5 (patch) | |
tree | c91f425a39cb585242d6df5b4070de4a2141b3b4 /src/webview/spellchecker.js | |
parent | Merge branch 'update/monetization' into develop (diff) | |
download | ferdium-app-3d87c0e45cead95ddb6c11fc6540b82e375bdcf5.tar.gz ferdium-app-3d87c0e45cead95ddb6c11fc6540b82e375bdcf5.tar.zst ferdium-app-3d87c0e45cead95ddb6c11fc6540b82e375bdcf5.zip |
feat(App): Improved spell checker & context menu
Diffstat (limited to 'src/webview/spellchecker.js')
-rw-r--r-- | src/webview/spellchecker.js | 111 |
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 @@ | |||
1 | import { SpellCheckHandler } from 'electron-spellchecker'; | 1 | import { webFrame } from 'electron'; |
2 | import fs from 'fs'; | ||
3 | import path from 'path'; | ||
4 | import { SpellCheckerProvider } from 'electron-hunspell'; | ||
2 | 5 | ||
3 | import { isMac } from '../environment'; | 6 | import { DICTIONARY_PATH } from '../config'; |
4 | 7 | ||
5 | export default class Spellchecker { | 8 | const debug = require('debug')('Franz:spellchecker'); |
6 | isInitialized = false; | ||
7 | handler = null; | ||
8 | initRetries = 0; | ||
9 | DOMCheckInterval = null; | ||
10 | 9 | ||
11 | get inputs() { | 10 | let provider; |
12 | return document.querySelectorAll('input[type="text"], [contenteditable="true"], textarea'); | 11 | let currentDict; |
13 | } | 12 | let _isEnabled = false; |
14 | 13 | ||
15 | initialize() { | 14 | async 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 | |||
29 | export 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) { | 62 | export 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 | ||
82 | export function isEnabled() { | ||
83 | return _isEnabled; | ||
84 | } | ||
85 | |||
86 | export function disable() { | ||
87 | if (isEnabled()) { | ||
88 | webFrame.setSpellCheckProvider(currentDict, true, { spellCheck: () => true }); | ||
89 | _isEnabled = false; | ||
90 | currentDict = null; | ||
91 | } | ||
92 | } | ||