aboutsummaryrefslogtreecommitdiffstats
path: root/src/webview
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-02-12 20:42:21 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2019-02-12 20:42:21 +0100
commit2d5a303b1cc559339c3ecc7a176e9d8bd66755ef (patch)
tree2a97c1db68a72b8e208bd177af7faad5df2c9f48 /src/webview
parentfeat(Windows): Add option to quit Franz from Taskbar icon (diff)
parentfeat(Spell checking): Add option to automatically detect language (diff)
downloadferdium-app-2d5a303b1cc559339c3ecc7a176e9d8bd66755ef.tar.gz
ferdium-app-2d5a303b1cc559339c3ecc7a176e9d8bd66755ef.tar.zst
ferdium-app-2d5a303b1cc559339c3ecc7a176e9d8bd66755ef.zip
Merge branch 'feature/spellcheck-autodetect' into develop
Diffstat (limited to 'src/webview')
-rw-r--r--src/webview/contextMenu.js12
-rw-r--r--src/webview/recipe.js56
-rw-r--r--src/webview/spellchecker.js11
3 files changed, 75 insertions, 4 deletions
diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js
index a76c03e5a..afb1d8912 100644
--- a/src/webview/contextMenu.js
+++ b/src/webview/contextMenu.js
@@ -207,8 +207,6 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
207 }); 207 });
208 }); 208 });
209 209
210 console.log('isSpellcheckEnabled', isSpellcheckEnabled);
211
212 menuTpl.push({ 210 menuTpl.push({
213 type: 'separator', 211 type: 'separator',
214 }, { 212 }, {
@@ -234,6 +232,16 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
234 }, 232 },
235 }, 233 },
236 { 234 {
235 id: 'automaticDetection',
236 label: 'Automatic language detection',
237 type: 'radio',
238 checked: spellcheckerLanguage === 'automatic',
239 click() {
240 debug('Detect language automatically');
241 ipcRenderer.sendToHost('set-service-spellchecker-language', 'automatic');
242 },
243 },
244 {
237 type: 'separator', 245 type: 'separator',
238 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage, 246 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage,
239 }, 247 },
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index c718b348e..1e5d74b1f 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -1,10 +1,12 @@
1import { ipcRenderer } from 'electron'; 1import { ipcRenderer } from 'electron';
2import path from 'path'; 2import path from 'path';
3import { autorun, computed, observable } from 'mobx'; 3import { autorun, computed, observable } from 'mobx';
4import { loadModule } from 'cld3-asm';
5import { debounce } from 'lodash';
4 6
5import RecipeWebview from './lib/RecipeWebview'; 7import RecipeWebview from './lib/RecipeWebview';
6 8
7import spellchecker, { switchDict, disable as disableSpellchecker } from './spellchecker'; 9import spellchecker, { switchDict, disable as disableSpellchecker, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker';
8import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; 10import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode';
9import contextMenu from './contextMenu'; 11import contextMenu from './contextMenu';
10import './notifications'; 12import './notifications';
@@ -40,6 +42,8 @@ class RecipeController {
40 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage; 42 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage;
41 } 43 }
42 44
45 cldIdentifier = null;
46
43 async initialize() { 47 async initialize() {
44 Object.keys(this.ipcEvents).forEach((channel) => { 48 Object.keys(this.ipcEvents).forEach((channel) => {
45 ipcRenderer.on(channel, (...args) => { 49 ipcRenderer.on(channel, (...args) => {
@@ -87,10 +91,22 @@ class RecipeController {
87 91
88 if (this.settings.app.enableSpellchecking) { 92 if (this.settings.app.enableSpellchecking) {
89 debug('Setting spellchecker language to', this.spellcheckerLanguage); 93 debug('Setting spellchecker language to', this.spellcheckerLanguage);
90 switchDict(this.spellcheckerLanguage); 94 let { spellcheckerLanguage } = this;
95 if (spellcheckerLanguage === 'automatic') {
96 this.automaticLanguageDetection();
97 debug('Found `automatic` locale, falling back to user locale until detected', this.settings.app.locale);
98 spellcheckerLanguage = this.settings.app.locale;
99 } else if (this.cldIdentifier) {
100 this.cldIdentifier.destroy();
101 }
102 switchDict(spellcheckerLanguage);
91 } else { 103 } else {
92 debug('Disable spellchecker'); 104 debug('Disable spellchecker');
93 disableSpellchecker(); 105 disableSpellchecker();
106
107 if (this.cldIdentifier) {
108 this.cldIdentifier.destroy();
109 }
94 } 110 }
95 111
96 if (this.settings.service.isDarkModeEnabled) { 112 if (this.settings.service.isDarkModeEnabled) {
@@ -113,6 +129,42 @@ class RecipeController {
113 serviceIdEcho(event) { 129 serviceIdEcho(event) {
114 event.sender.send('service-id', this.settings.service.id); 130 event.sender.send('service-id', this.settings.service.id);
115 } 131 }
132
133 async automaticLanguageDetection() {
134 const cldFactory = await loadModule();
135 this.cldIdentifier = cldFactory.create(0, 1000);
136
137 window.addEventListener('keyup', debounce((e) => {
138 const element = e.target;
139
140 console.log(element);
141
142 if (!element) return;
143
144 let value = '';
145 if (element.isContentEditable) {
146 value = element.textContent;
147 } else if (element.value) {
148 value = element.value;
149 }
150
151 // Force a minimum length to get better detection results
152 if (value.length < 30) return;
153
154 debug('Detecting language for', value);
155 const findResult = this.cldIdentifier.findLanguage(value);
156
157 debug('Language detection result', findResult);
158
159 if (findResult.is_reliable) {
160 const spellcheckerLocale = getSpellcheckerLocaleByFuzzyIdentifier(findResult.language);
161 debug('Language detected reliably, setting spellchecker language to', spellcheckerLocale);
162 if (spellcheckerLocale) {
163 switchDict(spellcheckerLocale);
164 }
165 }
166 }, 225));
167 }
116} 168}
117 169
118/* eslint-disable no-new */ 170/* eslint-disable no-new */
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index becaed449..9158b3b94 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -3,6 +3,7 @@ import { SpellCheckerProvider } from 'electron-hunspell';
3import path from 'path'; 3import path from 'path';
4 4
5import { DICTIONARY_PATH } from '../config'; 5import { DICTIONARY_PATH } from '../config';
6import { SPELLCHECKER_LOCALES } from '../i18n/languages';
6 7
7const debug = require('debug')('Franz:spellchecker'); 8const debug = require('debug')('Franz:spellchecker');
8 9
@@ -82,3 +83,13 @@ export function disable() {
82 currentDict = null; 83 currentDict = null;
83 } 84 }
84} 85}
86
87export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) {
88 const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase());
89
90 if (locales.length >= 1) {
91 return locales[0];
92 }
93
94 return null;
95}