diff options
author | Stefan Malzner <stefan@adlk.io> | 2017-11-07 12:25:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-07 12:25:00 +0100 |
commit | c55885e69e195e4413fda3bffffafeaee7c0c9d5 (patch) | |
tree | b13a2894796e45df60c92cf4c999b2974d400091 /src | |
parent | Fix lint errors (diff) | |
parent | fix(App): Prevent app from redirecting when dropping link (diff) | |
download | ferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.tar.gz ferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.tar.zst ferdium-app-c55885e69e195e4413fda3bffffafeaee7c0c9d5.zip |
Merge branch 'develop' into reload-crashed-service
Diffstat (limited to 'src')
-rw-r--r-- | src/api/server/ServerApi.js | 17 | ||||
-rw-r--r-- | src/app.js | 4 | ||||
-rw-r--r-- | src/components/settings/services/EditServiceForm.js | 6 | ||||
-rw-r--r-- | src/environment.js | 11 | ||||
-rw-r--r-- | src/index.js | 34 | ||||
-rw-r--r-- | src/lib/Menu.js | 5 | ||||
-rw-r--r-- | src/models/Recipe.js | 19 | ||||
-rw-r--r-- | src/models/Service.js | 7 | ||||
-rw-r--r-- | src/stores/AppStore.js | 69 | ||||
-rw-r--r-- | src/webview/notifications.js | 41 |
10 files changed, 105 insertions, 108 deletions
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 | ||
106 | window.addEventListener('dragover', event => event.preventDefault()); | ||
107 | window.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({ | |||
69 | export default class EditServiceForm extends Component { | 69 | export 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'; | |||
8 | export const isWindows = process.platform === 'win32'; | 8 | export const isWindows = process.platform === 'win32'; |
9 | export const isLinux = process.platform === 'linux'; | 9 | export const isLinux = process.platform === 'linux'; |
10 | 10 | ||
11 | let ctrlShortcutKey; | 11 | export const ctrlKey = isMac ? '⌘' : 'Ctrl'; |
12 | if (isMac) { | ||
13 | ctrlShortcutKey = '⌘'; | ||
14 | } else if (isWindows) { | ||
15 | ctrlShortcutKey = 'Ctrl'; | ||
16 | } else { | ||
17 | ctrlShortcutKey = 'Alt'; | ||
18 | } | ||
19 | |||
20 | export const ctrlKey = ctrlShortcutKey; | ||
21 | 12 | ||
22 | let api; | 13 | let api; |
23 | if (!isDevMode || (isDevMode && useLiveAPI)) { | 14 | if (!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'; | |||
2 | import fs from 'fs-extra'; | 2 | import fs from 'fs-extra'; |
3 | import path from 'path'; | 3 | import path from 'path'; |
4 | 4 | ||
5 | /* eslint-disable */ | ||
6 | if (require('electron-squirrel-startup')) app.quit(); | ||
7 | |||
8 | import windowStateKeeper from 'electron-window-state'; | 5 | import windowStateKeeper from 'electron-window-state'; |
9 | 6 | ||
10 | import { isDevMode, isWindows } from './environment'; | 7 | import { isDevMode, isWindows } from './environment'; |
11 | import ipcApi from './electron/ipc-api'; | 8 | import ipcApi from './electron/ipc-api'; |
12 | import Tray from './lib/Tray'; | 9 | import Tray from './lib/Tray'; |
13 | import Settings from './electron/Settings'; | 10 | import Settings from './electron/Settings'; |
14 | import { appId } from './package.json'; | 11 | import { appId } from './package.json'; // eslint-disable-line import/no-unresolved |
15 | import './electron/exception'; | 12 | import './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 |
24 | fs.ensureDir(path.join(app.getPath('userData'), 'recipes')); | 20 | fs.ensureDir(path.join(app.getPath('userData'), 'recipes')); |
21 | fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); | ||
25 | 22 | ||
26 | // Set App ID for Windows | 23 | // Set App ID for Windows |
27 | if (isWindows) { | 24 | if (isWindows) { |
@@ -29,19 +26,18 @@ if (isWindows) { | |||
29 | } | 26 | } |
30 | 27 | ||
31 | // Force single window | 28 | // Force single window |
32 | if (process.platform !== 'darwin') { | 29 | const 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 | |||
36 | if (isSecondInstance) { | ||
37 | app.exit(); | ||
43 | } | 38 | } |
44 | 39 | ||
40 | |||
45 | // Initialize Settings | 41 | // Initialize Settings |
46 | const settings = new Settings(); | 42 | const 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 @@ | |||
1 | import { remote, shell } from 'electron'; | 1 | import { remote, shell } from 'electron'; |
2 | import { autorun, computed, observable, toJS } from 'mobx'; | 2 | import { autorun, computed, observable, toJS } from 'mobx'; |
3 | 3 | ||
4 | import { isMac, isLinux } from '../environment'; | 4 | import { isMac } from '../environment'; |
5 | 5 | ||
6 | const { app, Menu, dialog } = remote; | 6 | const { 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 @@ | |||
1 | import emailParser from 'address-rfc2822'; | ||
2 | |||
1 | export default class Recipe { | 3 | export 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'; | |||
2 | import { action, observable } from 'mobx'; | 2 | import { action, observable } from 'mobx'; |
3 | import moment from 'moment'; | 3 | import moment from 'moment'; |
4 | import key from 'keymaster'; | 4 | import key from 'keymaster'; |
5 | import path from 'path'; | 5 | // import path from 'path'; |
6 | import idleTimer from '@paulcbetts/system-idle-time'; | 6 | import idleTimer from '@paulcbetts/system-idle-time'; |
7 | import AutoLaunch from 'auto-launch'; | ||
7 | 8 | ||
8 | import Store from './lib/Store'; | 9 | import Store from './lib/Store'; |
9 | import Request from './lib/Request'; | 10 | import Request from './lib/Request'; |
10 | import { CHECK_INTERVAL } from '../config'; | 11 | import { CHECK_INTERVAL } from '../config'; |
11 | import { isMac, isLinux } from '../environment'; | 12 | import { isMac } from '../environment'; |
12 | import locales from '../i18n/translations'; | 13 | import locales from '../i18n/translations'; |
13 | import { gaEvent } from '../lib/analytics'; | 14 | import { gaEvent } from '../lib/analytics'; |
14 | import Miner from '../lib/Miner'; | 15 | import Miner from '../lib/Miner'; |
15 | 16 | ||
16 | const { app, powerMonitor } = remote; | 17 | const { app, powerMonitor } = remote; |
17 | const defaultLocale = 'en-US'; | 18 | const defaultLocale = 'en-US'; |
19 | const autoLauncher = new AutoLaunch({ | ||
20 | name: 'Franz', | ||
21 | }); | ||
18 | 22 | ||
19 | export default class AppStore extends Store { | 23 | export 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 @@ | |||
1 | const { ipcRenderer } = require('electron'); | 1 | const { ipcRenderer } = require('electron'); |
2 | const uuidV1 = require('uuid/v1'); | 2 | const uuidV1 = require('uuid/v1'); |
3 | // const FranzNotificationStore = []; | ||
4 | 3 | ||
5 | class Notification { | 4 | class 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 | ||
24 | Notification.permission = 'granted'; | 23 | static requestPermission(cb = null) { |
24 | if (!cb) { | ||
25 | return new Promise((resolve) => { | ||
26 | resolve(Notification.permission); | ||
27 | }); | ||
28 | } | ||
25 | 29 | ||
26 | Notification.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 | ||
41 | Notification.close = () => { | 41 | onClick() {} |
42 | // no implementation yet | ||
43 | }; | ||
44 | 42 | ||
45 | Notification.onNotify = data => data; | 43 | close() {} |
44 | } | ||
46 | 45 | ||
47 | window.Notification = Notification; | 46 | window.Notification = Notification; |