aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-01-05 21:12:42 +0100
committerLibravatar Stefan Malzner <stefan@adlk.io>2019-01-05 21:12:42 +0100
commit904eb333103e0d3b9f6c23ca49d76d403f43ded3 (patch)
tree8f3367d306fb4d9d9f82e6bc5dd502853e63cbca /src
parentAdd lerna instructions (diff)
downloadferdium-app-904eb333103e0d3b9f6c23ca49d76d403f43ded3.tar.gz
ferdium-app-904eb333103e0d3b9f6c23ca49d76d403f43ded3.tar.zst
ferdium-app-904eb333103e0d3b9f6c23ca49d76d403f43ded3.zip
Merge
Diffstat (limited to 'src')
-rw-r--r--src/helpers/password-helpers.js4
-rw-r--r--src/index.js80
-rw-r--r--src/models/Service.js22
-rw-r--r--src/stores/ServicesStore.js16
-rw-r--r--src/stores/UIStore.js7
-rw-r--r--src/webview/recipe.js17
6 files changed, 99 insertions, 47 deletions
diff --git a/src/helpers/password-helpers.js b/src/helpers/password-helpers.js
index 7aacaa4d0..cf461e4f7 100644
--- a/src/helpers/password-helpers.js
+++ b/src/helpers/password-helpers.js
@@ -1,7 +1,7 @@
1import { SHA256 } from 'jshashes'; 1import crypto from 'crypto';
2 2
3export function hash(password) { 3export function hash(password) {
4 return new SHA256().b64(password); 4 return crypto.createHash('sha256').update(password).digest('base64');
5} 5}
6 6
7export function scorePassword(password) { 7export function scorePassword(password) {
diff --git a/src/index.js b/src/index.js
index 830166dcf..75da4ff88 100644
--- a/src/index.js
+++ b/src/index.js
@@ -46,35 +46,69 @@ if (isWindows) {
46} 46}
47 47
48// Force single window 48// Force single window
49const isSecondInstance = app.makeSingleInstance((argv) => { 49const gotTheLock = app.requestSingleInstanceLock();
50 if (mainWindow) { 50if (!gotTheLock) {
51 if (mainWindow.isMinimized()) mainWindow.restore(); 51 app.quit();
52 mainWindow.focus(); 52} else {
53 app.on('second-instance', (event, argv) => {
54 // Someone tried to run a second instance, we should focus our window.
55 if (mainWindow) {
56 if (mainWindow.isMinimized()) mainWindow.restore();
57 mainWindow.focus();
53 58
54 if (process.platform === 'win32') { 59 if (isWindows) {
55 // Keep only command line / deep linked arguments 60 // Keep only command line / deep linked arguments
56 const url = argv.slice(1); 61 const url = argv.slice(1);
57 62
58 if (url) { 63 if (url) {
59 handleDeepLink(mainWindow, url.toString()); 64 handleDeepLink(mainWindow, url.toString());
65 }
60 } 66 }
61 }
62 }
63 67
64 if (argv.includes('--reset-window')) { 68 if (argv.includes('--reset-window')) {
65 // Needs to be delayed to not interfere with mainWindow.restore(); 69 // Needs to be delayed to not interfere with mainWindow.restore();
66 setTimeout(() => { 70 setTimeout(() => {
67 debug('Resetting windows via Task'); 71 debug('Resetting windows via Task');
68 mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100); 72 mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100);
69 mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height); 73 mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height);
70 }, 1); 74 }, 1);
71 } 75 }
72}); 76 }
77 });
73 78
74if (isSecondInstance) { 79 // Create myWindow, load the rest of the app, etc...
75 console.log('An instance of Franz is already running. Exiting...'); 80 app.on('ready', () => {
76 app.exit(); 81 });
77} 82}
83// const isSecondInstance = app.makeSingleInstance((argv) => {
84// if (mainWindow) {
85// if (mainWindow.isMinimized()) mainWindow.restore();
86// mainWindow.focus();
87
88// if (process.platform === 'win32') {
89// // Keep only command line / deep linked arguments
90// const url = argv.slice(1);
91
92// if (url) {
93// handleDeepLink(mainWindow, url.toString());
94// }
95// }
96// }
97
98// if (argv.includes('--reset-window')) {
99// // Needs to be delayed to not interfere with mainWindow.restore();
100// setTimeout(() => {
101// debug('Resetting windows via Task');
102// mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100);
103// mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height);
104// }, 1);
105// }
106// });
107
108// if (isSecondInstance) {
109// console.log('An instance of Franz is already running. Exiting...');
110// app.exit();
111// }
78 112
79// Fix Unity indicator issue 113// Fix Unity indicator issue
80// https://github.com/electron/electron/issues/9046 114// https://github.com/electron/electron/issues/9046
diff --git a/src/models/Service.js b/src/models/Service.js
index 4cc6102ff..7a955a6d9 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -114,6 +114,13 @@ export default class Service {
114 }); 114 });
115 } 115 }
116 116
117 @computed get shareWithWebview() {
118 return {
119 spellcheckerLanguage: this.spellcheckerLanguage,
120 isDarkModeEnabled: this.isDarkModeEnabled,
121 };
122 }
123
117 @computed get url() { 124 @computed get url() {
118 if (this.recipe.hasCustomUrl && this.customUrl) { 125 if (this.recipe.hasCustomUrl && this.customUrl) {
119 let url; 126 let url;
@@ -162,14 +169,14 @@ export default class Service {
162 return userAgent; 169 return userAgent;
163 } 170 }
164 171
165 initializeWebViewEvents(store) { 172 initializeWebViewEvents({ handleIPCMessage, openWindow }) {
166 this.webview.addEventListener('ipc-message', e => store.actions.service.handleIPCMessage({ 173 this.webview.addEventListener('ipc-message', e => handleIPCMessage({
167 serviceId: this.id, 174 serviceId: this.id,
168 channel: e.channel, 175 channel: e.channel,
169 args: e.args, 176 args: e.args,
170 })); 177 }));
171 178
172 this.webview.addEventListener('new-window', (event, url, frameName, options) => store.actions.service.openWindow({ 179 this.webview.addEventListener('new-window', (event, url, frameName, options) => openWindow({
173 event, 180 event,
174 url, 181 url,
175 frameName, 182 frameName,
@@ -182,17 +189,20 @@ export default class Service {
182 this.isError = false; 189 this.isError = false;
183 }); 190 });
184 191
185 this.webview.addEventListener('did-frame-finish-load', () => { 192 const didLoad = () => {
186 this.isLoading = false; 193 this.isLoading = false;
187 194
188 if (!this.isError) { 195 if (!this.isError) {
189 this.isFirstLoad = false; 196 this.isFirstLoad = false;
190 } 197 }
191 }); 198 };
199
200 this.webview.addEventListener('did-frame-finish-load', didLoad.bind(this));
201 this.webview.addEventListener('did-navigate', didLoad.bind(this));
192 202
193 this.webview.addEventListener('did-fail-load', (event) => { 203 this.webview.addEventListener('did-fail-load', (event) => {
194 debug('Service failed to load', this.name, event); 204 debug('Service failed to load', this.name, event);
195 if (event.isMainFrame) { 205 if (event.isMainFrame && event.errorCode !== -3) {
196 this.isError = true; 206 this.isError = true;
197 this.errorMessage = event.errorDescription; 207 this.errorMessage = event.errorDescription;
198 this.isLoading = false; 208 this.isLoading = false;
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index 5b70ca271..84f84891a 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -1,5 +1,8 @@
1import { 1import {
2 action, reaction, computed, observable, 2 action,
3 reaction,
4 computed,
5 observable,
3} from 'mobx'; 6} from 'mobx';
4import { debounce, remove } from 'lodash'; 7import { debounce, remove } from 'lodash';
5 8
@@ -323,7 +326,11 @@ export default class ServicesStore extends Store {
323 service.webview = webview; 326 service.webview = webview;
324 327
325 if (!service.isAttached) { 328 if (!service.isAttached) {
326 service.initializeWebViewEvents(this); 329 debug('Webview is not attached, initializing');
330 service.initializeWebViewEvents({
331 handleIPCMessage: this.actions.service.handleIPCMessage,
332 openWindow: this.actions.service.openWindow,
333 });
327 service.initializeWebViewListener(); 334 service.initializeWebViewListener();
328 } 335 }
329 336
@@ -644,14 +651,15 @@ export default class ServicesStore extends Store {
644 const service = this.one(serviceId); 651 const service = this.one(serviceId);
645 652
646 if (service.webview) { 653 if (service.webview) {
647 service.webview.send('initialize-recipe', service); 654 debug('Initialize recipe', service.recipe.id, service.name);
655 service.webview.send('initialize-recipe', service.shareWithWebview, service.recipe);
648 } 656 }
649 } 657 }
650 658
651 _initRecipePolling(serviceId) { 659 _initRecipePolling(serviceId) {
652 const service = this.one(serviceId); 660 const service = this.one(serviceId);
653 661
654 const delay = 1000; 662 const delay = 2000;
655 663
656 if (service) { 664 if (service) {
657 if (service.timer !== null) { 665 if (service.timer !== null) {
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index d37ebe4c7..188c2fc44 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -1,8 +1,7 @@
1import { action, observable, computed } from 'mobx'; 1import { action, observable, computed } from 'mobx';
2import theme from '@meetfranz/theme';
2 3
3import Store from './lib/Store'; 4import Store from './lib/Store';
4import * as themeDefault from '../theme/default';
5import * as themeDark from '../theme/dark';
6 5
7export default class UIStore extends Store { 6export default class UIStore extends Store {
8 @observable showServicesUpdatedInfoBar = false; 7 @observable showServicesUpdatedInfoBar = false;
@@ -24,10 +23,10 @@ export default class UIStore extends Store {
24 23
25 @computed get theme() { 24 @computed get theme() {
26 if (this.stores.settings.all.app.darkMode) { 25 if (this.stores.settings.all.app.darkMode) {
27 return Object.assign({}, themeDefault, themeDark); 26 return theme('dark');
28 } 27 }
29 28
30 return themeDefault; 29 return theme('default');
31 } 30 }
32 31
33 // Actions 32 // Actions
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index 944883899..9aa89ce01 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -42,9 +42,9 @@ class RecipeController {
42 42
43 async initialize() { 43 async initialize() {
44 Object.keys(this.ipcEvents).forEach((channel) => { 44 Object.keys(this.ipcEvents).forEach((channel) => {
45 ipcRenderer.on(channel, (event, data) => { 45 ipcRenderer.on(channel, (...args) => {
46 debug('Received IPC event for channel', channel, 'with', data); 46 debug('Received IPC event for channel', channel, 'with', ...args);
47 this[this.ipcEvents[channel]](event, data); 47 this[this.ipcEvents[channel]](...args);
48 }); 48 });
49 }); 49 });
50 50
@@ -62,17 +62,18 @@ class RecipeController {
62 autorun(() => this.update()); 62 autorun(() => this.update());
63 } 63 }
64 64
65 loadRecipeModule(event, data) { 65 loadRecipeModule(event, config, recipe) {
66 debug('loadRecipeModule'); 66 debug('loadRecipeModule');
67 const modulePath = path.join(data.recipe.path, 'webview.js'); 67 const modulePath = path.join(recipe.path, 'webview.js');
68 debug('module path', modulePath);
68 // Delete module from cache 69 // Delete module from cache
69 delete require.cache[require.resolve(modulePath)]; 70 delete require.cache[require.resolve(modulePath)];
70 try { 71 try {
71 // eslint-disable-next-line 72 // eslint-disable-next-line
72 require(modulePath)(new RecipeWebview(), data); 73 require(modulePath)(new RecipeWebview(), {...config, recipe,});
73 debug('Initialize Recipe', data); 74 debug('Initialize Recipe', config, recipe);
74 75
75 this.settings.service = data; 76 this.settings.service = config;
76 } catch (err) { 77 } catch (err) {
77 console.error('Recipe initialization failed', err); 78 console.error('Recipe initialization failed', err);
78 } 79 }