diff options
-rw-r--r-- | gulpfile.babel.js | 6 | ||||
-rw-r--r-- | src/api/server/LocalApi.js | 4 | ||||
-rw-r--r-- | src/components/settings/settings/EditSettingsForm.js | 5 | ||||
-rw-r--r-- | src/models/Settings.js | 6 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 2 | ||||
-rw-r--r-- | src/stores/SettingsStore.js | 2 | ||||
-rw-r--r-- | src/webview/plugin.js | 28 | ||||
-rw-r--r-- | src/webview/spellchecker.js | 65 |
8 files changed, 77 insertions, 41 deletions
diff --git a/gulpfile.babel.js b/gulpfile.babel.js index d947974b3..b50001b2d 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js | |||
@@ -110,7 +110,11 @@ export function watch() { | |||
110 | } | 110 | } |
111 | 111 | ||
112 | export function webserver() { | 112 | export function webserver() { |
113 | gulp.src(paths.dest) | 113 | gulp.src([ |
114 | paths.dest, | ||
115 | `!${paths.dest}/electron/**`, | ||
116 | `!${paths.dest}/webview/**`, | ||
117 | ]) | ||
114 | .pipe(server({ | 118 | .pipe(server({ |
115 | livereload: true, | 119 | livereload: true, |
116 | })); | 120 | })); |
diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index eba236f16..79ac6e12f 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js | |||
@@ -1,5 +1,3 @@ | |||
1 | import SettingsModel from '../../models/Settings'; | ||
2 | |||
3 | export default class LocalApi { | 1 | export default class LocalApi { |
4 | // App | 2 | // App |
5 | async updateAppSettings(data) { | 3 | async updateAppSettings(data) { |
@@ -15,7 +13,7 @@ export default class LocalApi { | |||
15 | async getAppSettings() { | 13 | async getAppSettings() { |
16 | const settingsString = localStorage.getItem('app'); | 14 | const settingsString = localStorage.getItem('app'); |
17 | try { | 15 | try { |
18 | const settings = new SettingsModel(JSON.parse(settingsString) || {}); | 16 | const settings = JSON.parse(settingsString) || {}; |
19 | console.debug('LocalApi::getAppSettings resolves', settings); | 17 | console.debug('LocalApi::getAppSettings resolves', settings); |
20 | 18 | ||
21 | return settings; | 19 | return settings; |
diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index 878e46d6d..ff398aa33 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js | |||
@@ -64,10 +64,6 @@ const messages = defineMessages({ | |||
64 | id: 'settings.app.currentVersion', | 64 | id: 'settings.app.currentVersion', |
65 | defaultMessage: '!!!Current version:', | 65 | defaultMessage: '!!!Current version:', |
66 | }, | 66 | }, |
67 | restartRequired: { | ||
68 | id: 'settings.app.restartRequired', | ||
69 | defaultMessage: '!!!Changes require restart', | ||
70 | }, | ||
71 | }); | 67 | }); |
72 | 68 | ||
73 | @observer | 69 | @observer |
@@ -158,7 +154,6 @@ export default class EditSettingsForm extends Component { | |||
158 | {/* Advanced */} | 154 | {/* Advanced */} |
159 | <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2> | 155 | <h2 id="advanced">{intl.formatMessage(messages.headlineAdvanced)}</h2> |
160 | <Toggle field={form.$('enableSpellchecking')} /> | 156 | <Toggle field={form.$('enableSpellchecking')} /> |
161 | <p className="settings__help">{intl.formatMessage(messages.restartRequired)}</p> | ||
162 | {/* <Select field={form.$('spellcheckingLanguage')} /> */} | 157 | {/* <Select field={form.$('spellcheckingLanguage')} /> */} |
163 | 158 | ||
164 | {/* Updates */} | 159 | {/* Updates */} |
diff --git a/src/models/Settings.js b/src/models/Settings.js index 35bfe0d05..ca44da258 100644 --- a/src/models/Settings.js +++ b/src/models/Settings.js | |||
@@ -1,4 +1,4 @@ | |||
1 | import { observable } from 'mobx'; | 1 | import { observable, extendObservable } from 'mobx'; |
2 | import { DEFAULT_APP_SETTINGS } from '../config'; | 2 | import { DEFAULT_APP_SETTINGS } from '../config'; |
3 | 3 | ||
4 | export default class Settings { | 4 | export default class Settings { |
@@ -17,4 +17,8 @@ export default class Settings { | |||
17 | constructor(data) { | 17 | constructor(data) { |
18 | Object.assign(this, data); | 18 | Object.assign(this, data); |
19 | } | 19 | } |
20 | |||
21 | update(data) { | ||
22 | extendObservable(this, data); | ||
23 | } | ||
20 | } | 24 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index b04aafd78..113df6d55 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -297,7 +297,7 @@ export default class ServicesStore extends Store { | |||
297 | }); | 297 | }); |
298 | } else if (channel === 'notification') { | 298 | } else if (channel === 'notification') { |
299 | const options = args[0].options; | 299 | const options = args[0].options; |
300 | if (service.recipe.hasNotificationSound || service.isMuted) { | 300 | if (service.recipe.hasNotificationSound || service.isMuted || this.stores.settings.all.isAppMuted) { |
301 | Object.assign(options, { | 301 | Object.assign(options, { |
302 | silent: true, | 302 | silent: true, |
303 | }); | 303 | }); |
diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index 33473f16d..da99a720f 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js | |||
@@ -26,7 +26,7 @@ export default class SettingsStore extends Store { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | @computed get all() { | 28 | @computed get all() { |
29 | return this.allSettingsRequest.result || new SettingsModel(); | 29 | return new SettingsModel(this.allSettingsRequest.result); |
30 | } | 30 | } |
31 | 31 | ||
32 | @action async _update({ settings }) { | 32 | @action async _update({ settings }) { |
diff --git a/src/webview/plugin.js b/src/webview/plugin.js index c877132b1..cf38169d3 100644 --- a/src/webview/plugin.js +++ b/src/webview/plugin.js | |||
@@ -1,14 +1,14 @@ | |||
1 | import { ipcRenderer } from 'electron'; | 1 | import { ipcRenderer } from 'electron'; |
2 | import { ContextMenuListener, ContextMenuBuilder } from 'electron-spellchecker'; | ||
2 | import path from 'path'; | 3 | import path from 'path'; |
3 | 4 | ||
5 | import { isDevMode } from '../environment'; | ||
4 | import RecipeWebview from './lib/RecipeWebview'; | 6 | import RecipeWebview from './lib/RecipeWebview'; |
5 | 7 | ||
6 | import Spellchecker from './spellchecker.js'; | 8 | import Spellchecker from './spellchecker.js'; |
7 | import './notifications.js'; | 9 | import './notifications.js'; |
8 | import './ime.js'; | 10 | import './ime.js'; |
9 | 11 | ||
10 | const spellchecker = new Spellchecker(); | ||
11 | |||
12 | ipcRenderer.on('initializeRecipe', (e, data) => { | 12 | ipcRenderer.on('initializeRecipe', (e, data) => { |
13 | const modulePath = path.join(data.recipe.path, 'webview.js'); | 13 | const modulePath = path.join(data.recipe.path, 'webview.js'); |
14 | // Delete module from cache | 14 | // Delete module from cache |
@@ -21,20 +21,22 @@ ipcRenderer.on('initializeRecipe', (e, data) => { | |||
21 | } | 21 | } |
22 | }); | 22 | }); |
23 | 23 | ||
24 | const spellchecker = new Spellchecker(); | ||
25 | spellchecker.initialize(); | ||
26 | |||
27 | const contextMenuBuilder = new ContextMenuBuilder(spellchecker.handler, null, isDevMode); | ||
28 | |||
29 | new ContextMenuListener((info) => { // eslint-disable-line | ||
30 | contextMenuBuilder.showPopupMenu(info); | ||
31 | }); | ||
32 | |||
24 | ipcRenderer.on('settings-update', (e, data) => { | 33 | ipcRenderer.on('settings-update', (e, data) => { |
25 | if (data.enableSpellchecking) { | 34 | console.log('settings-update', data); |
26 | if (!spellchecker.isEnabled) { | 35 | spellchecker.toggleSpellchecker(data.enableSpellchecking); |
27 | spellchecker.enable(); | ||
28 | |||
29 | // TODO: this does not work yet, needs more testing | ||
30 | // if (data.spellcheckingLanguage !== 'auto') { | ||
31 | // console.log('set spellchecking language to', data.spellcheckingLanguage); | ||
32 | // spellchecker.switchLanguage(data.spellcheckingLanguage); | ||
33 | // } | ||
34 | } | ||
35 | } | ||
36 | }); | 36 | }); |
37 | 37 | ||
38 | // initSpellche | ||
39 | |||
38 | document.addEventListener('DOMContentLoaded', () => { | 40 | document.addEventListener('DOMContentLoaded', () => { |
39 | ipcRenderer.sendToHost('hello'); | 41 | ipcRenderer.sendToHost('hello'); |
40 | }, false); | 42 | }, false); |
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js index 5beb77e03..a504a4039 100644 --- a/src/webview/spellchecker.js +++ b/src/webview/spellchecker.js | |||
@@ -1,30 +1,63 @@ | |||
1 | import { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } from 'electron-spellchecker'; | 1 | import { SpellCheckHandler } from 'electron-spellchecker'; |
2 | 2 | ||
3 | import { isMac } from '../environment'; | 3 | import { isMac } from '../environment'; |
4 | 4 | ||
5 | export default class Spellchecker { | 5 | export default class Spellchecker { |
6 | isEnabled = false; | 6 | isInitialized = false; |
7 | spellchecker = null; | 7 | handler = null; |
8 | initRetries = 0; | ||
9 | DOMCheckInterval = null; | ||
10 | |||
11 | get inputs() { | ||
12 | return document.querySelectorAll('input[type="text"], [contenteditable="true"], textarea'); | ||
13 | } | ||
14 | |||
15 | initialize() { | ||
16 | this.handler = new SpellCheckHandler(); | ||
8 | 17 | ||
9 | enable() { | ||
10 | this.spellchecker = new SpellCheckHandler(); | ||
11 | if (!isMac) { | 18 | if (!isMac) { |
12 | this.spellchecker.attachToInput(); | 19 | this.attach(); |
13 | this.spellchecker.switchLanguage(navigator.language); | 20 | } else { |
21 | this.isInitialized = true; | ||
22 | } | ||
23 | } | ||
24 | |||
25 | attach() { | ||
26 | let initFailed = false; | ||
27 | |||
28 | if (this.initRetries > 3) { | ||
29 | console.error('Could not initialize spellchecker'); | ||
30 | return; | ||
14 | } | 31 | } |
15 | 32 | ||
16 | const contextMenuBuilder = new ContextMenuBuilder(this.spellchecker); | 33 | try { |
34 | this.handler.attachToInput(); | ||
35 | this.handler.switchLanguage(navigator.language); | ||
36 | } catch (err) { | ||
37 | initFailed = true; | ||
38 | this.initRetries = +1; | ||
39 | setTimeout(() => { this.attach(); console.warn('Spellchecker init failed, trying again in 5s'); }, 5000); | ||
40 | } | ||
17 | 41 | ||
18 | new ContextMenuListener((info) => { // eslint-disable-line | 42 | if (!initFailed) { |
19 | contextMenuBuilder.showPopupMenu(info); | 43 | this.isInitialized = true; |
44 | } | ||
45 | } | ||
46 | |||
47 | toggleSpellchecker(enable = false) { | ||
48 | this.inputs.forEach((input) => { | ||
49 | input.setAttribute('spellcheck', enable); | ||
20 | }); | 50 | }); |
51 | |||
52 | this.intervalHandler(enable); | ||
21 | } | 53 | } |
22 | 54 | ||
23 | // TODO: this does not work yet, needs more testing | 55 | intervalHandler(enable) { |
24 | // switchLanguage(language) { | 56 | clearInterval(this.DOMCheckInterval); |
25 | // if (language !== 'auto') { | 57 | |
26 | // this.spellchecker.switchLanguage(language); | 58 | if (enable) { |
27 | // } | 59 | this.DOMCheckInterval = setInterval(() => this.toggleSpellchecker(enable), 30000); |
28 | // } | 60 | } |
61 | } | ||
29 | } | 62 | } |
30 | 63 | ||