summaryrefslogtreecommitdiffstats
path: root/src/webview
diff options
context:
space:
mode:
Diffstat (limited to 'src/webview')
-rw-r--r--src/webview/ime.js10
-rw-r--r--src/webview/lib/RecipeWebview.js74
-rw-r--r--src/webview/notifications.js45
-rw-r--r--src/webview/plugin.js24
-rw-r--r--src/webview/spellchecker.js14
-rw-r--r--src/webview/zoom.js37
6 files changed, 204 insertions, 0 deletions
diff --git a/src/webview/ime.js b/src/webview/ime.js
new file mode 100644
index 000000000..43df6267c
--- /dev/null
+++ b/src/webview/ime.js
@@ -0,0 +1,10 @@
1const { ipcRenderer } = require('electron');
2const { claimDocumentFocus } = require('../helpers/webview-ime-focus-helpers');
3
4ipcRenderer.on('claim-document-focus', claimDocumentFocus);
5
6window.addEventListener('DOMContentLoaded', () => {
7 if (document.querySelector('[autofocus]')) {
8 ipcRenderer.sendToHost('autofocus');
9 }
10});
diff --git a/src/webview/lib/RecipeWebview.js b/src/webview/lib/RecipeWebview.js
new file mode 100644
index 000000000..1787f85e2
--- /dev/null
+++ b/src/webview/lib/RecipeWebview.js
@@ -0,0 +1,74 @@
1// @flow
2const { ipcRenderer } = require('electron');
3const fs = require('fs-extra');
4
5class RecipeWebview {
6 constructor() {
7 this.countCache = {
8 direct: 0,
9 indirect: 0,
10 };
11
12 ipcRenderer.on('poll', () => {
13 this.loopFunc();
14 });
15 }
16
17 loopFunc = () => null;
18
19 /**
20 * Initialize the loop
21 *
22 * @param {Function} Function that will be executed
23 */
24 loop(fn) {
25 this.loopFunc = fn;
26 }
27
28 /**
29 * Set the unread message badge
30 *
31 * @param {int} direct Set the count of direct messages
32 * eg. Slack direct mentions, or a
33 * message to @channel
34 * @param {int} indirect Set a badge that defines there are
35 * new messages but they do not involve
36 * me directly to me eg. in a channel
37 */
38 setBadge(direct = 0, indirect = 0) {
39 if (this.countCache.direct === direct
40 && this.countCache.indirect === indirect) return;
41
42 const count = {
43 direct,
44 indirect,
45 };
46
47 ipcRenderer.sendToHost('messages', count);
48 Object.assign(this.countCache, count);
49 }
50
51 /**
52 * Injects the contents of a CSS file into the current webview
53 *
54 * @param {Array} files CSS files that should be injected. This must
55 * be an absolute path to the file
56 */
57 injectCSS(...files) {
58 files.forEach((file) => {
59 const data = fs.readFileSync(file);
60 const styles = document.createElement('style');
61 styles.innerHTML = data.toString();
62
63 document.querySelector('head').appendChild(styles);
64 });
65 }
66
67 initialize(fn) {
68 if (typeof fn === 'function') {
69 fn();
70 }
71 }
72}
73
74module.exports = RecipeWebview;
diff --git a/src/webview/notifications.js b/src/webview/notifications.js
new file mode 100644
index 000000000..97ce9d69b
--- /dev/null
+++ b/src/webview/notifications.js
@@ -0,0 +1,45 @@
1const { ipcRenderer } = require('electron');
2const uuidV1 = require('uuid/v1');
3// const FranzNotificationStore = [];
4
5class Notification {
6 constructor(title = '', options = {}) {
7 this.title = title;
8 this.options = options;
9 this.notificationId = uuidV1();
10 this.onclick = () => {};
11
12 ipcRenderer.sendToHost('notification', {
13 notificationId: this.notificationId,
14 title,
15 options,
16 });
17
18 ipcRenderer.on(`notification-onclick:${this.notificationId}`, () => {
19 this.onclick();
20 });
21 }
22}
23
24Notification.permission = 'granted';
25
26Notification.requestPermission = (cb = null) => {
27 console.log(this);
28 if (!cb) {
29 return new Promise((resolve) => {
30 resolve(Notification.permission);
31 });
32 }
33
34 if (typeof (cb) === 'function') {
35 return cb(Notification.permission);
36 }
37
38 return Notification.permission;
39};
40
41Notification.close = () => {
42 // no implementation yet
43};
44
45window.Notification = Notification;
diff --git a/src/webview/plugin.js b/src/webview/plugin.js
new file mode 100644
index 000000000..ffc9084e4
--- /dev/null
+++ b/src/webview/plugin.js
@@ -0,0 +1,24 @@
1const { ipcRenderer } = require('electron');
2const path = require('path');
3
4const RecipeWebview = require('./lib/RecipeWebview');
5
6require('./notifications.js');
7require('./spellchecker.js');
8require('./ime.js');
9
10ipcRenderer.on('initializeRecipe', (e, data) => {
11 const modulePath = path.join(data.recipe.path, 'webview.js');
12 // Delete module from cache
13 delete require.cache[require.resolve(modulePath)];
14 try {
15 // eslint-disable-next-line
16 require(modulePath)(new RecipeWebview(), data);
17 } catch (err) {
18 console.error(err);
19 }
20});
21
22document.addEventListener('DOMContentLoaded', () => {
23 ipcRenderer.sendToHost('hello');
24}, false);
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
new file mode 100644
index 000000000..ec8807874
--- /dev/null
+++ b/src/webview/spellchecker.js
@@ -0,0 +1,14 @@
1import { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } from 'electron-spellchecker';
2
3window.spellCheckHandler = new SpellCheckHandler();
4setTimeout(() => {
5 window.spellCheckHandler.attachToInput();
6}, 1000);
7
8// TODO: should we set the language to user settings?
9// window.spellCheckHandler.switchLanguage('en-US');
10
11const contextMenuBuilder = new ContextMenuBuilder(window.spellCheckHandler);
12const contextMenuListener = new ContextMenuListener((info) => { // eslint-disable-line
13 contextMenuBuilder.showPopupMenu(info);
14});
diff --git a/src/webview/zoom.js b/src/webview/zoom.js
new file mode 100644
index 000000000..99c647036
--- /dev/null
+++ b/src/webview/zoom.js
@@ -0,0 +1,37 @@
1const electron = require('electron');
2
3const { ipcRenderer, webFrame } = electron;
4
5const maxZoomLevel = 9;
6const minZoomLevel = -8;
7let zoomLevel = 0;
8
9ipcRenderer.on('zoomIn', () => {
10 if (maxZoomLevel > zoomLevel) {
11 zoomLevel += 1;
12 }
13 webFrame.setZoomLevel(zoomLevel);
14
15 ipcRenderer.sendToHost('zoomLevel', { zoom: zoomLevel });
16});
17
18ipcRenderer.on('zoomOut', () => {
19 if (minZoomLevel < zoomLevel) {
20 zoomLevel -= 1;
21 }
22 webFrame.setZoomLevel(zoomLevel);
23
24 ipcRenderer.sendToHost('zoomLevel', { zoom: zoomLevel });
25});
26
27ipcRenderer.on('zoomReset', () => {
28 zoomLevel = 0;
29 webFrame.setZoomLevel(zoomLevel);
30
31 ipcRenderer.sendToHost('zoomLevel', { zoom: zoomLevel });
32});
33
34ipcRenderer.on('setZoom', (e, arg) => {
35 zoomLevel = arg;
36 webFrame.setZoomLevel(zoomLevel);
37});