aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2017-11-07 12:25:00 +0100
committerLibravatar GitHub <noreply@github.com>2017-11-07 12:25:00 +0100
commitc55885e69e195e4413fda3bffffafeaee7c0c9d5 (patch)
treeb13a2894796e45df60c92cf4c999b2974d400091
parentFix lint errors (diff)
parentfix(App): Prevent app from redirecting when dropping link (diff)
downloadferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.tar.gz
ferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.tar.zst
ferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.zip
Merge branch 'develop' into reload-crashed-service
-rw-r--r--.github/ISSUE_TEMPLATE.md2
-rw-r--r--CHANGELOG.md30
-rw-r--r--README.md3
-rw-r--r--electron-builder.yml2
-rw-r--r--package.json5
-rw-r--r--src/api/server/ServerApi.js17
-rw-r--r--src/app.js4
-rw-r--r--src/components/settings/services/EditServiceForm.js6
-rw-r--r--src/environment.js11
-rw-r--r--src/index.js34
-rw-r--r--src/lib/Menu.js5
-rw-r--r--src/models/Recipe.js19
-rw-r--r--src/models/Service.js7
-rw-r--r--src/stores/AppStore.js69
-rw-r--r--src/webview/notifications.js41
-rw-r--r--yarn.lock38
16 files changed, 176 insertions, 117 deletions
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 4ef48f240..c11a2994f 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,5 +1,7 @@
1<!--- Provide a general summary of the issue in the Title above --> 1<!--- Provide a general summary of the issue in the Title above -->
2 2
3<!-- This repository is only for the Franz client. Please use this form ( https://adlk.typeform.com/to/Bj7vGq ) for service requests or check out the guide ( https://github.com/meetfranz/plugins ) to create your own service integration. -->
4
3<!--- If you want to propose a feature, use this template: https://raw.githubusercontent.com/meetfranz/franz/master/.github/FEATURE_PROPOSAL_TEMPLATE.md --> 5<!--- If you want to propose a feature, use this template: https://raw.githubusercontent.com/meetfranz/franz/master/.github/FEATURE_PROPOSAL_TEMPLATE.md -->
4 6
5### Expected Behavior 7### Expected Behavior
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6551ed51..024afe93c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
1<a name="5.0.0-beta.13"></a>
2# [5.0.0-beta.13](https://github.com/meetfranz/franz/compare/v5.0.0-beta.12...v5.0.0-beta.13) (2017-11-06)
3
4### Bug Fixes
5
6* **Windows:** Fix issue with multiple close handlers that prevent the app from quitting ([eea593e](https://github.com/meetfranz/franz/commit/eea593e))
7
8
9<a name="5.0.0-beta.12"></a>
10# [5.0.0-beta.12](https://github.com/meetfranz/franz/compare/v5.0.0-beta.11...v5.0.0-beta.12) (2017-11-05)
11
12### Features
13
14* **Menu:** Add "About Franz" Menu item to Windows/Linux ([a21b770](https://github.com/meetfranz/franz/commit/a21b770))
15* **Menu:** Add menu item to toggle (service) dev tools ([e8da383](https://github.com/meetfranz/franz/commit/e8da383))
16* **Translation:** Add italian translation ([ab348cc](https://github.com/meetfranz/franz/commit/ab348cc)) ([dnlup](https://github.com/dnlup))
17
18
19### Bug Fixes
20
21* **App:** Add checks to service url validation to prevent app freeze ([db8515f](https://github.com/meetfranz/franz/commit/db8515f))
22* **macOS:** Fix disable launch Franz on start ([34bba09](https://github.com/meetfranz/franz/commit/34bba09))
23* **Windows:** Launch Franz on start when selected ([34bba09](https://github.com/meetfranz/franz/commit/34bba09))
24* **Onboarding:** Fix issue with import of on-premise services ([7c7d27d](https://github.com/meetfranz/franz/commit/7c7d27d))
25* **Shortcuts:** Flip shortcut to navigate to next/previous service ([37d5923](https://github.com/meetfranz/franz/commit/37d5923))
26* **Windows:** Open Window when app is pinned to taskbar and minimized to system tray ([777814a](https://github.com/meetfranz/franz/commit/777814a))
27* **Recipes:** Recipe developers don't need Premium Supporter Account for debugging ([7a9947a](https://github.com/meetfranz/franz/commit/7a9947a)), closes [#23](https://github.com/meetfranz/franz/issues/23)
28
29
30
1<a name="5.0.0-beta.11"></a> 31<a name="5.0.0-beta.11"></a>
2# [5.0.0-beta.11](https://github.com/meetfranz/franz/compare/v5.0.0-beta.10...v5.0.0-beta.11) (2017-10-24) 32# [5.0.0-beta.11](https://github.com/meetfranz/franz/compare/v5.0.0-beta.10...v5.0.0-beta.11) (2017-10-24)
3 33
diff --git a/README.md b/README.md
index 2a0d30f1e..6110573a8 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,9 @@
9 9
10Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more. 10Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.
11 11
12## [Download Franz](https://www.meetfranz.com)
13👉 www.meetfranz.com
14
12 15
13## Development 16## Development
14 17
diff --git a/electron-builder.yml b/electron-builder.yml
index 0a01a03d8..3f7ad1e85 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -29,5 +29,5 @@ linux:
29 - target: deb 29 - target: deb
30 30
31nsis: 31nsis:
32 perMachine: true 32 perMachine: false
33 oneClick: true 33 oneClick: true
diff --git a/package.json b/package.json
index dcb05bf6a..9b56cdf27 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
2 "name": "franz", 2 "name": "franz",
3 "productName": "Franz", 3 "productName": "Franz",
4 "appId": "com.meetfranz.franz", 4 "appId": "com.meetfranz.franz",
5 "version": "5.0.0-beta.11", 5 "version": "5.0.0-beta.13",
6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.", 6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.",
7 "copyright": "adlk x franz - Stefan Malzner", 7 "copyright": "adlk x franz - Stefan Malzner",
8 "main": "index.js", 8 "main": "index.js",
@@ -27,12 +27,13 @@
27 "license": "Apache-2.0", 27 "license": "Apache-2.0",
28 "dependencies": { 28 "dependencies": {
29 "@paulcbetts/system-idle-time": "^1.0.4", 29 "@paulcbetts/system-idle-time": "^1.0.4",
30 "address-rfc2822": "^2.0.1",
31 "auto-launch": "https://github.com/meetfranz/node-auto-launch.git",
30 "babel-polyfill": "^6.23.0", 32 "babel-polyfill": "^6.23.0",
31 "babel-runtime": "^6.23.0", 33 "babel-runtime": "^6.23.0",
32 "classnames": "^2.2.5", 34 "classnames": "^2.2.5",
33 "electron-fetch": "^1.1.0", 35 "electron-fetch": "^1.1.0",
34 "electron-spellchecker": "^1.2.0", 36 "electron-spellchecker": "^1.2.0",
35 "electron-squirrel-startup": "^1.0.0",
36 "electron-updater": "^2.4.3", 37 "electron-updater": "^2.4.3",
37 "electron-window-state": "^4.1.0", 38 "electron-window-state": "^4.1.0",
38 "fs-extra": "^3.0.1", 39 "fs-extra": "^3.0.1",
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js
index 8b0b7563c..932b70cdc 100644
--- a/src/api/server/ServerApi.js
+++ b/src/api/server/ServerApi.js
@@ -499,7 +499,7 @@ export default class ServerApi {
499 499
500 return recipe; 500 return recipe;
501 }), 501 }),
502 ).catch(err => console.error(err)); 502 ).catch(err => console.error('Can\'t load recipe', err));
503 } 503 }
504 504
505 _mapRecipePreviewModel(recipes) { 505 _mapRecipePreviewModel(recipes) {
@@ -562,9 +562,16 @@ export default class ServerApi {
562 .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp'); 562 .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp');
563 563
564 const recipes = paths.map((id) => { 564 const recipes = paths.map((id) => {
565 // eslint-disable-next-line 565 let Recipe;
566 const Recipe = require(id)(RecipeModel); 566 try {
567 return new Recipe(loadRecipeConfig(id)); 567 // eslint-disable-next-line
568 Recipe = require(id)(RecipeModel);
569 return new Recipe(loadRecipeConfig(id));
570 } catch (err) {
571 console.error(err);
572 }
573
574 return false;
568 }).filter(recipe => recipe.id).map((data) => { 575 }).filter(recipe => recipe.id).map((data) => {
569 const recipe = data; 576 const recipe = data;
570 577
@@ -579,7 +586,7 @@ export default class ServerApi {
579 586
580 return recipes; 587 return recipes;
581 } catch (err) { 588 } catch (err) {
582 console.debug('Folder `recipe/dev` does not exist'); 589 console.debug('Could not load dev recipes');
583 return false; 590 return false;
584 } 591 }
585 } 592 }
diff --git a/src/app.js b/src/app.js
index b539ea494..a0b88611c 100644
--- a/src/app.js
+++ b/src/app.js
@@ -101,3 +101,7 @@ window.addEventListener('load', () => {
101 }; 101 };
102 window.franz.render(); 102 window.franz.render();
103}); 103});
104
105// Prevent drag and drop into window from redirecting
106window.addEventListener('dragover', event => event.preventDefault());
107window.addEventListener('drop', event => event.preventDefault());
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index fac0f6b9a..9b359a78e 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -69,10 +69,6 @@ const messages = defineMessages({
69export default class EditServiceForm extends Component { 69export default class EditServiceForm extends Component {
70 static propTypes = { 70 static propTypes = {
71 recipe: PropTypes.instanceOf(Recipe).isRequired, 71 recipe: PropTypes.instanceOf(Recipe).isRequired,
72 // service: PropTypes.oneOfType([
73 // PropTypes.object,
74 // PropTypes.instanceOf(Service),
75 // ]),
76 service(props, propName) { 72 service(props, propName) {
77 if (props.action === 'edit' && !(props[propName] instanceof Service)) { 73 if (props.action === 'edit' && !(props[propName] instanceof Service)) {
78 return new Error(`'${propName}'' is expected to be of type 'Service' 74 return new Error(`'${propName}'' is expected to be of type 'Service'
@@ -207,7 +203,7 @@ export default class EditServiceForm extends Component {
207 )} 203 )}
208 {recipe.hasCustomUrl && ( 204 {recipe.hasCustomUrl && (
209 <TabItem title={intl.formatMessage(messages.tabOnPremise)}> 205 <TabItem title={intl.formatMessage(messages.tabOnPremise)}>
210 {user.isPremium ? ( 206 {user.isPremium || recipe.author.find(a => a.email === user.email) ? (
211 <div> 207 <div>
212 <Input field={form.$('customUrl')} /> 208 <Input field={form.$('customUrl')} />
213 {form.error === 'url-validation-error' && ( 209 {form.error === 'url-validation-error' && (
diff --git a/src/environment.js b/src/environment.js
index 7bb2db134..e185120c0 100644
--- a/src/environment.js
+++ b/src/environment.js
@@ -8,16 +8,7 @@ export const isMac = process.platform === 'darwin';
8export const isWindows = process.platform === 'win32'; 8export const isWindows = process.platform === 'win32';
9export const isLinux = process.platform === 'linux'; 9export const isLinux = process.platform === 'linux';
10 10
11let ctrlShortcutKey; 11export const ctrlKey = isMac ? '⌘' : 'Ctrl';
12if (isMac) {
13 ctrlShortcutKey = '⌘';
14} else if (isWindows) {
15 ctrlShortcutKey = 'Ctrl';
16} else {
17 ctrlShortcutKey = 'Alt';
18}
19
20export const ctrlKey = ctrlShortcutKey;
21 12
22let api; 13let api;
23if (!isDevMode || (isDevMode && useLiveAPI)) { 14if (!isDevMode || (isDevMode && useLiveAPI)) {
diff --git a/src/index.js b/src/index.js
index 030736fee..f0fe56ae5 100644
--- a/src/index.js
+++ b/src/index.js
@@ -2,18 +2,14 @@ import { app, BrowserWindow, shell } from 'electron';
2import fs from 'fs-extra'; 2import fs from 'fs-extra';
3import path from 'path'; 3import path from 'path';
4 4
5/* eslint-disable */
6if (require('electron-squirrel-startup')) app.quit();
7
8import windowStateKeeper from 'electron-window-state'; 5import windowStateKeeper from 'electron-window-state';
9 6
10import { isDevMode, isWindows } from './environment'; 7import { isDevMode, isWindows } from './environment';
11import ipcApi from './electron/ipc-api'; 8import ipcApi from './electron/ipc-api';
12import Tray from './lib/Tray'; 9import Tray from './lib/Tray';
13import Settings from './electron/Settings'; 10import Settings from './electron/Settings';
14import { appId } from './package.json'; 11import { appId } from './package.json'; // eslint-disable-line import/no-unresolved
15import './electron/exception'; 12import './electron/exception';
16/* eslint-enable */
17 13
18// Keep a global reference of the window object, if you don't, the window will 14// Keep a global reference of the window object, if you don't, the window will
19// be closed automatically when the JavaScript object is garbage collected. 15// be closed automatically when the JavaScript object is garbage collected.
@@ -22,6 +18,7 @@ let willQuitApp = false;
22 18
23// Ensure that the recipe directory exists 19// Ensure that the recipe directory exists
24fs.ensureDir(path.join(app.getPath('userData'), 'recipes')); 20fs.ensureDir(path.join(app.getPath('userData'), 'recipes'));
21fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp'));
25 22
26// Set App ID for Windows 23// Set App ID for Windows
27if (isWindows) { 24if (isWindows) {
@@ -29,19 +26,18 @@ if (isWindows) {
29} 26}
30 27
31// Force single window 28// Force single window
32if (process.platform !== 'darwin') { 29const isSecondInstance = app.makeSingleInstance(() => {
33 const isSecondInstance = app.makeSingleInstance(() => { 30 if (mainWindow) {
34 if (mainWindow) { 31 if (mainWindow.isMinimized()) mainWindow.restore();
35 if (mainWindow.isMinimized()) mainWindow.restore(); 32 mainWindow.focus();
36 mainWindow.focus();
37 }
38 });
39
40 if (isSecondInstance) {
41 app.quit();
42 } 33 }
34});
35
36if (isSecondInstance) {
37 app.exit();
43} 38}
44 39
40
45// Initialize Settings 41// Initialize Settings
46const settings = new Settings(); 42const settings = new Settings();
47 43
@@ -89,9 +85,13 @@ const createWindow = async () => {
89 // when you should delete the corresponding element. 85 // when you should delete the corresponding element.
90 if (!willQuitApp && (settings.get('runInBackground') === undefined || settings.get('runInBackground'))) { 86 if (!willQuitApp && (settings.get('runInBackground') === undefined || settings.get('runInBackground'))) {
91 e.preventDefault(); 87 e.preventDefault();
92 mainWindow.hide(); 88 if (isWindows) {
89 mainWindow.minimize();
90 } else {
91 mainWindow.hide();
92 }
93 93
94 if (process.platform === 'win32') { 94 if (isWindows && settings.get('minimizeToSystemTray')) {
95 mainWindow.setSkipTaskbar(true); 95 mainWindow.setSkipTaskbar(true);
96 } 96 }
97 } else { 97 } else {
diff --git a/src/lib/Menu.js b/src/lib/Menu.js
index 6bbf302ca..8f0a92c3d 100644
--- a/src/lib/Menu.js
+++ b/src/lib/Menu.js
@@ -1,7 +1,7 @@
1import { remote, shell } from 'electron'; 1import { remote, shell } from 'electron';
2import { autorun, computed, observable, toJS } from 'mobx'; 2import { autorun, computed, observable, toJS } from 'mobx';
3 3
4import { isMac, isLinux } from '../environment'; 4import { isMac } from '../environment';
5 5
6const { app, Menu, dialog } = remote; 6const { app, Menu, dialog } = remote;
7 7
@@ -276,10 +276,9 @@ export default class FranzMenu {
276 const services = this.stores.services.enabled; 276 const services = this.stores.services.enabled;
277 277
278 if (this.stores.user.isLoggedIn) { 278 if (this.stores.user.isLoggedIn) {
279 const systemAcceleratorKey = isLinux ? 'Alt' : 'CmdOrCtrl';
280 return services.map((service, i) => ({ 279 return services.map((service, i) => ({
281 label: service.name, 280 label: service.name,
282 accelerator: i <= 9 ? `${systemAcceleratorKey}+${i + 1}` : null, 281 accelerator: i <= 9 ? `CmdOrCtrl+${i + 1}` : null,
283 type: 'radio', 282 type: 'radio',
284 checked: service.isActive, 283 checked: service.isActive,
285 click: () => { 284 click: () => {
diff --git a/src/models/Recipe.js b/src/models/Recipe.js
index 43a3450b1..9971df77c 100644
--- a/src/models/Recipe.js
+++ b/src/models/Recipe.js
@@ -1,7 +1,8 @@
1import emailParser from 'address-rfc2822';
2
1export default class Recipe { 3export default class Recipe {
2 id = ''; 4 id = '';
3 name = ''; 5 name = '';
4 author = '';
5 description = ''; 6 description = '';
6 version = '1.0'; 7 version = '1.0';
7 path = ''; 8 path = '';
@@ -25,12 +26,13 @@ export default class Recipe {
25 } 26 }
26 27
27 if (!data.id) { 28 if (!data.id) {
28 throw Error('Recipe requires Id'); 29 // Franz 4 recipes do not have an Id
30 throw Error(`Recipe '${data.name}' requires Id`);
29 } 31 }
30 32
31 this.id = data.id || this.id; 33 this.id = data.id || this.id;
32 this.name = data.name || this.name; 34 this.name = data.name || this.name;
33 this.author = data.author || this.author; 35 this.rawAuthor = data.author || this.author;
34 this.description = data.description || this.description; 36 this.description = data.description || this.description;
35 this.version = data.version || this.version; 37 this.version = data.version || this.version;
36 this.path = data.path; 38 this.path = data.path;
@@ -49,4 +51,15 @@ export default class Recipe {
49 51
50 this.message = data.config.message || this.message; 52 this.message = data.config.message || this.message;
51 } 53 }
54
55 get author() {
56 try {
57 const addresses = emailParser.parse(this.rawAuthor);
58 return addresses.map(a => ({ email: a.address, name: a.phrase }));
59 } catch (err) {
60 console.warn(`Not a valid author for ${this.name}`);
61 }
62
63 return [];
64 }
52} 65}
diff --git a/src/models/Service.js b/src/models/Service.js
index 89d6748b5..c7276821a 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -58,7 +58,12 @@ export default class Service {
58 58
59 @computed get url() { 59 @computed get url() {
60 if (this.recipe.hasCustomUrl && this.customUrl) { 60 if (this.recipe.hasCustomUrl && this.customUrl) {
61 let url = normalizeUrl(this.customUrl); 61 let url;
62 try {
63 url = normalizeUrl(this.customUrl);
64 } catch (err) {
65 console.error(`Service (${this.recipe.name}): '${this.customUrl}' is not a valid Url.`);
66 }
62 67
63 if (typeof this.recipe.buildUrl === 'function') { 68 if (typeof this.recipe.buildUrl === 'function') {
64 url = this.recipe.buildUrl(url); 69 url = this.recipe.buildUrl(url);
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js
index f608a689e..ecfd621d3 100644
--- a/src/stores/AppStore.js
+++ b/src/stores/AppStore.js
@@ -2,19 +2,23 @@ import { remote, ipcRenderer, shell } from 'electron';
2import { action, observable } from 'mobx'; 2import { action, observable } from 'mobx';
3import moment from 'moment'; 3import moment from 'moment';
4import key from 'keymaster'; 4import key from 'keymaster';
5import path from 'path'; 5// import path from 'path';
6import idleTimer from '@paulcbetts/system-idle-time'; 6import idleTimer from '@paulcbetts/system-idle-time';
7import AutoLaunch from 'auto-launch';
7 8
8import Store from './lib/Store'; 9import Store from './lib/Store';
9import Request from './lib/Request'; 10import Request from './lib/Request';
10import { CHECK_INTERVAL } from '../config'; 11import { CHECK_INTERVAL } from '../config';
11import { isMac, isLinux } from '../environment'; 12import { isMac } from '../environment';
12import locales from '../i18n/translations'; 13import locales from '../i18n/translations';
13import { gaEvent } from '../lib/analytics'; 14import { gaEvent } from '../lib/analytics';
14import Miner from '../lib/Miner'; 15import Miner from '../lib/Miner';
15 16
16const { app, powerMonitor } = remote; 17const { app, powerMonitor } = remote;
17const defaultLocale = 'en-US'; 18const defaultLocale = 'en-US';
19const autoLauncher = new AutoLaunch({
20 name: 'Franz',
21});
18 22
19export default class AppStore extends Store { 23export default class AppStore extends Store {
20 updateStatusTypes = { 24 updateStatusTypes = {
@@ -41,7 +45,7 @@ export default class AppStore extends Store {
41 miner = null; 45 miner = null;
42 @observable minerHashrate = 0.0; 46 @observable minerHashrate = 0.0;
43 47
44 constructor(...args: any) { 48 constructor(...args) {
45 super(...args); 49 super(...args);
46 50
47 // Register action handlers 51 // Register action handlers
@@ -152,33 +156,24 @@ export default class AppStore extends Store {
152 indicator = '•'; 156 indicator = '•';
153 } else if (unreadDirectMessageCount === 0 && unreadIndirectMessageCount === 0) { 157 } else if (unreadDirectMessageCount === 0 && unreadIndirectMessageCount === 0) {
154 indicator = 0; 158 indicator = 0;
159 } else {
160 indicator = parseInt(indicator, 10);
155 } 161 }
156 162
157 ipcRenderer.send('updateAppIndicator', { indicator }); 163 ipcRenderer.send('updateAppIndicator', { indicator });
158 } 164 }
159 165
160 @action _launchOnStartup({ enable, openInBackground }) { 166 @action _launchOnStartup({ enable }) {
161 this.autoLaunchOnStart = enable; 167 this.autoLaunchOnStart = enable;
162 168
163 let settings = { 169 try {
164 openAtLogin: enable, 170 if (enable) {
165 }; 171 autoLauncher.enable();
166 172 } else {
167 // For Windows 173 autoLauncher.disable();
168 if (process.platform === 'win32') {
169 settings = Object.assign({
170 openAsHidden: openInBackground,
171 path: app.getPath('exe'),
172 args: [
173 '--processStart', `"${path.basename(app.getPath('exe'))}"`,
174 ],
175 }, settings);
176
177 if (openInBackground) {
178 settings.args.push(
179 '--process-start-args', '"--hidden"',
180 );
181 } 174 }
175 } catch (err) {
176 console.warn(err);
182 } 177 }
183 178
184 gaEvent('App', enable ? 'enable autostart' : 'disable autostart'); 179 gaEvent('App', enable ? 'enable autostart' : 'disable autostart');
@@ -287,31 +282,19 @@ export default class AppStore extends Store {
287 } 282 }
288 283
289 async _autoStart() { 284 async _autoStart() {
290 if (!isLinux) { 285 this.autoLaunchOnStart = await this._checkAutoStart();
291 this._checkAutoStart();
292 286
293 // we need to wait until the settings request is resolved 287 // we need to wait until the settings request is resolved
294 await this.stores.settings.allSettingsRequest; 288 await this.stores.settings.allSettingsRequest;
295
296 // We don't set autostart on first launch for macOS as disabling
297 // the option is currently broken
298 // https://github.com/meetfranz/franz/issues/17
299 // https://github.com/electron/electron/issues/10880
300 if (process.platform === 'darwin') return;
301 289
302 if (!this.stores.settings.all.appStarts) { 290 if (!this.stores.settings.all.appStarts) {
303 this.actions.app.launchOnStartup({ 291 this.actions.app.launchOnStartup({
304 enable: true, 292 enable: true,
305 }); 293 });
306 }
307 } 294 }
308 } 295 }
309 296
310 _checkAutoStart() { 297 async _checkAutoStart() {
311 const loginItem = app.getLoginItemSettings({ 298 return autoLauncher.isEnabled() || false;
312 path: app.getPath('exe'),
313 });
314
315 this.autoLaunchOnStart = loginItem.openAtLogin;
316 } 299 }
317} 300}
diff --git a/src/webview/notifications.js b/src/webview/notifications.js
index b3397148d..4055b10de 100644
--- a/src/webview/notifications.js
+++ b/src/webview/notifications.js
@@ -1,47 +1,46 @@
1const { ipcRenderer } = require('electron'); 1const { ipcRenderer } = require('electron');
2const uuidV1 = require('uuid/v1'); 2const uuidV1 = require('uuid/v1');
3// const FranzNotificationStore = [];
4 3
5class Notification { 4class Notification {
5 static permission = 'granted';
6
6 constructor(title = '', options = {}) { 7 constructor(title = '', options = {}) {
7 this.title = title; 8 this.title = title;
8 this.options = options; 9 this.options = options;
9 this.notificationId = uuidV1(); 10 this.notificationId = uuidV1();
10 this.onclick = () => { };
11 11
12 ipcRenderer.sendToHost('notification', Notification.onNotify({ 12 ipcRenderer.sendToHost('notification', this.onNotify({
13 notificationId: this.notificationId, 13 notificationId: this.notificationId,
14 title, 14 title,
15 options, 15 options,
16 })); 16 }));
17 17
18 ipcRenderer.on(`notification-onclick:${this.notificationId}`, () => { 18 ipcRenderer.once(`notification-onclick:${this.notificationId}`, () => {
19 this.onclick(); 19 this.onclick();
20 }); 20 });
21 } 21 }
22}
23 22
24Notification.permission = 'granted'; 23 static requestPermission(cb = null) {
24 if (!cb) {
25 return new Promise((resolve) => {
26 resolve(Notification.permission);
27 });
28 }
25 29
26Notification.requestPermission = (cb = null) => { 30 if (typeof (cb) === 'function') {
27 console.log(this); 31 return cb(Notification.permission);
28 if (!cb) { 32 }
29 return new Promise((resolve) => {
30 resolve(Notification.permission);
31 });
32 }
33 33
34 if (typeof (cb) === 'function') { 34 return Notification.permission;
35 return cb(Notification.permission);
36 } 35 }
37 36
38 return Notification.permission; 37 onNotify(data) {
39}; 38 return data;
39 }
40 40
41Notification.close = () => { 41 onClick() {}
42 // no implementation yet
43};
44 42
45Notification.onNotify = data => data; 43 close() {}
44}
46 45
47window.Notification = Notification; 46window.Notification = Notification;
diff --git a/yarn.lock b/yarn.lock
index a01368a4a..0bedbac27 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -80,6 +80,12 @@ acorn@^5.1.1:
80 version "5.1.2" 80 version "5.1.2"
81 resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" 81 resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
82 82
83address-rfc2822@^2.0.1:
84 version "2.0.1"
85 resolved "https://registry.yarnpkg.com/address-rfc2822/-/address-rfc2822-2.0.1.tgz#1a1bdb942b5e20e2c1ba5d5f396d5824ff7ae6ea"
86 dependencies:
87 email-addresses "^3.0.0"
88
83after@0.8.2: 89after@0.8.2:
84 version "0.8.2" 90 version "0.8.2"
85 resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" 91 resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
@@ -151,6 +157,10 @@ anymatch@^1.3.0:
151 micromatch "^2.1.5" 157 micromatch "^2.1.5"
152 normalize-path "^2.0.0" 158 normalize-path "^2.0.0"
153 159
160applescript@^1.0.0:
161 version "1.0.0"
162 resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317"
163
154aproba@^1.0.3: 164aproba@^1.0.3:
155 version "1.1.2" 165 version "1.1.2"
156 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" 166 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
@@ -319,6 +329,16 @@ asynckit@^0.4.0:
319 version "0.4.0" 329 version "0.4.0"
320 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 330 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
321 331
332"auto-launch@https://github.com/meetfranz/node-auto-launch.git":
333 version "5.0.1"
334 resolved "https://github.com/meetfranz/node-auto-launch.git#b90a0470467eb84435e6554ae9db1e2c6db79e61"
335 dependencies:
336 applescript "^1.0.0"
337 mkdirp "^0.5.1"
338 path-is-absolute "^1.0.0"
339 untildify "^3.0.2"
340 winreg "1.2.2"
341
322aws-sign2@~0.6.0: 342aws-sign2@~0.6.0:
323 version "0.6.0" 343 version "0.6.0"
324 resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" 344 resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
@@ -1998,12 +2018,6 @@ electron-spellchecker@^1.2.0:
1998 rxjs-serial-subscription "^0.1.1" 2018 rxjs-serial-subscription "^0.1.1"
1999 spawn-rx "^2.0.7" 2019 spawn-rx "^2.0.7"
2000 2020
2001electron-squirrel-startup@^1.0.0:
2002 version "1.0.0"
2003 resolved "https://registry.yarnpkg.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz#19b4e55933fa0ef8f556784b9c660f772546a0b8"
2004 dependencies:
2005 debug "^2.2.0"
2006
2007electron-to-chromium@^1.3.18: 2021electron-to-chromium@^1.3.18:
2008 version "1.3.20" 2022 version "1.3.20"
2009 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz#2eedd5ccbae7ddc557f68ad1fce9c172e915e4e5" 2023 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz#2eedd5ccbae7ddc557f68ad1fce9c172e915e4e5"
@@ -2041,6 +2055,10 @@ electron@^1.7.9:
2041 electron-download "^3.0.1" 2055 electron-download "^3.0.1"
2042 extract-zip "^1.0.3" 2056 extract-zip "^1.0.3"
2043 2057
2058email-addresses@^3.0.0:
2059 version "3.0.1"
2060 resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.0.1.tgz#c1fc20c189e7f96d4012d375db5feaccdd24391c"
2061
2044emojis-list@^2.0.0: 2062emojis-list@^2.0.0:
2045 version "2.1.0" 2063 version "2.1.0"
2046 resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" 2064 resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
@@ -5949,6 +5967,10 @@ universalify@^0.1.0:
5949 version "0.1.1" 5967 version "0.1.1"
5950 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" 5968 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
5951 5969
5970untildify@^3.0.2:
5971 version "3.0.2"
5972 resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.2.tgz#7f1f302055b3fea0f3e81dc78eb36766cb65e3f1"
5973
5952unzip-response@^2.0.1: 5974unzip-response@^2.0.1:
5953 version "2.0.1" 5975 version "2.0.1"
5954 resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" 5976 resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
@@ -6133,6 +6155,10 @@ window-size@^0.1.4:
6133 version "0.1.4" 6155 version "0.1.4"
6134 resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" 6156 resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
6135 6157
6158winreg@1.2.2:
6159 version "1.2.2"
6160 resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.2.tgz#8509afa3b71c5bbd110a6d7c6247ec67736c598f"
6161
6136word-wrap@^1.0.3: 6162word-wrap@^1.0.3:
6137 version "1.2.3" 6163 version "1.2.3"
6138 resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 6164 resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"