From 074d93d4a8f84c6a84c273b3ec85ee1090683791 Mon Sep 17 00:00:00 2001 From: Hugo Torzuoli Date: Tue, 5 Mar 2019 10:19:24 +0100 Subject: Add missing bracket in brew install help (#1205) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f7ad7d179..724e779e0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many mor `$ brew cask install franz` -(Don't know homebrew? [brew.sh](https://brew.sh/) +(Don't know homebrew? [brew.sh](https://brew.sh/)) ## Development -- cgit v1.2.3-70-g09d2 From a73e6bd9814d49eeb1cc7ff350cb5e4a621fd4ad Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 7 Mar 2019 16:47:32 +0100 Subject: fix(Service) shortcuts for activating prev/next service fixes #1298 --- src/i18n/locales/defaultMessages.json | 26 ++++++++++++++++++ src/i18n/locales/en-US.json | 4 ++- src/i18n/messages/src/lib/Menu.json | 26 ++++++++++++++++++ src/lib/Menu.js | 52 +++++++++++++++++++++++++---------- src/stores/AppStore.js | 13 --------- 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 065398dc6..d3a97de78 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3875,6 +3875,32 @@ "column": 17, "line": 178 } + }, + { + "defaultMessage": "!!!Activate next service...", + "end": { + "column": 3, + "line": 185 + }, + "file": "src/lib/Menu.js", + "id": "menu.services.setNextServiceActive", + "start": { + "column": 23, + "line": 182 + } + }, + { + "defaultMessage": "!!!Activate previous service...", + "end": { + "column": 3, + "line": 189 + }, + "file": "src/lib/Menu.js", + "id": "menu.services.activatePreviousService", + "start": { + "column": 27, + "line": 186 + } } ], "path": "src/lib/Menu.json" diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index af6edd2df..a9ac92a3a 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -70,7 +70,9 @@ "menu.help.support": "Support", "menu.help.tos": "Terms of Service", "menu.services": "Services", + "menu.services.activatePreviousService": "Activate previous service", "menu.services.addNewService": "Add New Service...", + "menu.services.setNextServiceActive": "Activate next service", "menu.view": "View", "menu.view.enterFullScreen": "Enter Full Screen", "menu.view.exitFullScreen": "Exit Full Screen", @@ -280,4 +282,4 @@ "validation.url": "{field} is not a valid URL", "welcome.loginButton": "Login to your account", "welcome.signupButton": "Create a free account" -} \ No newline at end of file +} diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index 6958f0219..a131851aa 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -557,5 +557,31 @@ "line": 181, "column": 3 } + }, + { + "id": "menu.services.setNextServiceActive", + "defaultMessage": "!!!Activate next service...", + "file": "src/lib/Menu.js", + "start": { + "line": 182, + "column": 23 + }, + "end": { + "line": 185, + "column": 3 + } + }, + { + "id": "menu.services.activatePreviousService", + "defaultMessage": "!!!Activate previous service...", + "file": "src/lib/Menu.js", + "start": { + "line": 186, + "column": 27 + }, + "end": { + "line": 189, + "column": 3 + } } ] \ No newline at end of file diff --git a/src/lib/Menu.js b/src/lib/Menu.js index dce8ab969..7bdbd9159 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -179,6 +179,14 @@ const menuItems = defineMessages({ id: 'menu.services.addNewService', defaultMessage: '!!!Add New Service...', }, + activateNextService: { + id: 'menu.services.setNextServiceActive', + defaultMessage: '!!!Activate next service...', + }, + activatePreviousService: { + id: 'menu.services.activatePreviousService', + defaultMessage: '!!!Activate previous service...', + }, }); function getActiveWebview() { @@ -525,7 +533,7 @@ export default class FranzMenu { return; } - const intl = window.franz.intl; + const { intl } = window.franz; const tpl = isMac ? _templateFactory(intl) : _titleBarTemplateFactory(intl); tpl[1].submenu.push({ @@ -683,17 +691,6 @@ export default class FranzMenu { }, about); } - serviceTpl.unshift({ - label: intl.formatMessage(menuItems.addNewService), - accelerator: `${cmdKey}+N`, - click: () => { - this.actions.ui.openSettings({ path: 'recipes' }); - }, - enabled: this.stores.user.isLoggedIn, - }, { - type: 'separator', - }); - if (serviceTpl.length > 0) { tpl[3].submenu = serviceTpl; } @@ -704,10 +701,35 @@ export default class FranzMenu { } @computed get serviceTpl() { + const { intl } = window.franz; const services = this.stores.services.allDisplayed; + const menu = [{ + label: intl.formatMessage(menuItems.addNewService), + accelerator: `${cmdKey}+N`, + click: () => { + this.actions.ui.openSettings({ path: 'recipes' }); + }, + enabled: this.stores.user.isLoggedIn, + }, { + type: 'separator', + }, { + label: intl.formatMessage(menuItems.activateNextService), + accelerator: `${cmdKey}+alt+right`, + click: () => this.actions.service.setActiveNext(), + enabled: this.stores.user.isLoggedIn, + }, { + label: intl.formatMessage(menuItems.activatePreviousService), + accelerator: `${cmdKey}+alt+left`, + click: () => this.actions.service.setActivePrev(), + enabled: this.stores.user.isLoggedIn, + }, { + type: 'separator', + }]; + + menu.push(); if (this.stores.user.isLoggedIn) { - return services.map((service, i) => ({ + services.forEach((service, i) => (menu.push({ label: this._getServiceName(service), accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, type: 'radio', @@ -715,10 +737,10 @@ export default class FranzMenu { click: () => { this.actions.service.setActive({ serviceId: service.id }); }, - })); + }))); } - return []; + return menu; } _getServiceName(service) { diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index d933ca407..1db61a64e 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -157,19 +157,6 @@ export default class AppStore extends Store { this.stores.router.push(url); }); - // Set active the next service - key( - '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { - this.actions.service.setActiveNext(); - }, - ); - - // Set active the prev service - key( - '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => { - this.actions.service.setActivePrev(); - }, - ); // Global Mute key( -- cgit v1.2.3-70-g09d2 From 1df3342534ae100d732ad57c9eae7401e5e97a83 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 7 Mar 2019 17:18:44 +0100 Subject: fix(Service): Fix shortcut for (un)muting notifications & audio --- package-lock.json | 5 ----- package.json | 1 - src/i18n/messages/src/lib/Menu.json | 26 ++++++++++++++++++++++++++ src/lib/Menu.js | 32 ++++++++++++++++++++++---------- src/stores/AppStore.js | 24 ------------------------ 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82e9c9997..8499abda9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11454,11 +11454,6 @@ "integrity": "sha1-P55JkK3K0MaGwOcB92RYaPdfkes=", "dev": true }, - "keymaster": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/keymaster/-/keymaster-1.6.2.tgz", - "integrity": "sha1-4a5U0OqUiPn2C2a2aPAumhlGxus=" - }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", diff --git a/package.json b/package.json index 05f10849c..14e0df7ca 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "fs-extra": "7.0.1", "hex-to-rgba": "1.0.2", "jsonwebtoken": "^7.4.1", - "keymaster": "^1.6.2", "lodash": "^4.17.4", "mdi": "^1.9.33", "mime-types": "2.1.21", diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index a131851aa..9314f5cce 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -583,5 +583,31 @@ "line": 189, "column": 3 } + }, + { + "id": "sidebar.muteApp", + "defaultMessage": "!!!Disable notifications & audio", + "file": "src/lib/Menu.js", + "start": { + "line": 190, + "column": 11 + }, + "end": { + "line": 193, + "column": 3 + } + }, + { + "id": "sidebar.unmuteApp", + "defaultMessage": "!!!Enable notifications & audio", + "file": "src/lib/Menu.js", + "start": { + "line": 194, + "column": 13 + }, + "end": { + "line": 197, + "column": 3 + } } ] \ No newline at end of file diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 7bdbd9159..fb92644d0 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -187,6 +187,14 @@ const menuItems = defineMessages({ id: 'menu.services.activatePreviousService', defaultMessage: '!!!Activate previous service...', }, + muteApp: { + id: 'sidebar.muteApp', + defaultMessage: '!!!Disable notifications & audio', + }, + unmuteApp: { + id: 'sidebar.unmuteApp', + defaultMessage: '!!!Enable notifications & audio', + }, }); function getActiveWebview() { @@ -416,7 +424,7 @@ const _titleBarTemplateFactory = intl => [ }, { label: intl.formatMessage(menuItems.zoomIn), - accelerator: `${ctrlKey}+Plus`, + accelerator: `${ctrlKey}+=`, click() { const activeService = getActiveWebview(); activeService.getZoomLevel((level) => { @@ -702,34 +710,38 @@ export default class FranzMenu { @computed get serviceTpl() { const { intl } = window.franz; - const services = this.stores.services.allDisplayed; - const menu = [{ + const { user, services, settings } = this.stores; + if (!user.isLoggedIn) return []; + const menu = []; + + menu.push({ label: intl.formatMessage(menuItems.addNewService), accelerator: `${cmdKey}+N`, click: () => { this.actions.ui.openSettings({ path: 'recipes' }); }, - enabled: this.stores.user.isLoggedIn, }, { type: 'separator', }, { label: intl.formatMessage(menuItems.activateNextService), accelerator: `${cmdKey}+alt+right`, click: () => this.actions.service.setActiveNext(), - enabled: this.stores.user.isLoggedIn, }, { label: intl.formatMessage(menuItems.activatePreviousService), accelerator: `${cmdKey}+alt+left`, click: () => this.actions.service.setActivePrev(), - enabled: this.stores.user.isLoggedIn, + }, { + label: intl.formatMessage( + settings.all.app.isAppMuted ? menuItems.unmuteApp : menuItems.muteApp, + ).replace('&', '&&'), + accelerator: `${cmdKey}+shift+m`, + click: () => this.actions.app.toggleMuteApp(), }, { type: 'separator', - }]; - - menu.push(); + }); if (this.stores.user.isLoggedIn) { - services.forEach((service, i) => (menu.push({ + services.allDisplayed.forEach((service, i) => (menu.push({ label: this._getServiceName(service), accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, type: 'radio', diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 1db61a64e..7784ff1f9 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -3,7 +3,6 @@ import { action, computed, observable, reaction, } from 'mobx'; import moment from 'moment'; -import key from 'keymaster'; import { getDoNotDisturb } from '@meetfranz/electron-notification-state'; import AutoLaunch from 'auto-launch'; import prettyBytes from 'pretty-bytes'; @@ -157,28 +156,6 @@ export default class AppStore extends Store { this.stores.router.push(url); }); - - // Global Mute - key( - '⌘+shift+m ctrl+shift+m', () => { - this.actions.app.toggleMuteApp(); - }, - ); - - // We need to add an additional key listener for ctrl+ on windows. Otherwise only ctrl+shift+ would work - if (isWindows) { - key( - 'ctrl+=', () => { - debug('Windows: zoom in via ctrl+'); - const { webview } = this.stores.services.active; - webview.getZoomLevel((level) => { - // level 9 =~ +300% and setZoomLevel wouldnt zoom in further - if (level < 9) webview.setZoomLevel(level + 1); - }); - }, - ); - } - this.locale = this._getDefaultLocale(); this._healthCheck(); @@ -290,7 +267,6 @@ export default class AppStore extends Store { @action _muteApp({ isMuted, overrideSystemMute = true }) { this.isSystemMuteOverridden = overrideSystemMute; - this.actions.settings.update({ type: 'app', data: { -- cgit v1.2.3-70-g09d2 From 1044b503fb64d7a8fb98862470f05377ac2f8d2e Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 7 Mar 2019 17:27:42 +0100 Subject: add missing react-intl files --- src/i18n/locales/defaultMessages.json | 26 ++++++++++++++++++++++++++ src/i18n/locales/en-US.json | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index d3a97de78..0641c510c 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3901,6 +3901,32 @@ "column": 27, "line": 186 } + }, + { + "defaultMessage": "!!!Disable notifications & audio", + "end": { + "column": 3, + "line": 193 + }, + "file": "src/lib/Menu.js", + "id": "sidebar.muteApp", + "start": { + "column": 11, + "line": 190 + } + }, + { + "defaultMessage": "!!!Enable notifications & audio", + "end": { + "column": 3, + "line": 197 + }, + "file": "src/lib/Menu.js", + "id": "sidebar.unmuteApp", + "start": { + "column": 13, + "line": 194 + } } ], "path": "src/lib/Menu.json" diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index a9ac92a3a..7543d38bd 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -282,4 +282,4 @@ "validation.url": "{field} is not a valid URL", "welcome.loginButton": "Login to your account", "welcome.signupButton": "Create a free account" -} +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c62a6a6031f01c200a008d6ed68f6889c339880f Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Fri, 8 Mar 2019 15:08:44 +0100 Subject: correctly update services submenu on language change --- src/lib/Menu.js | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/lib/Menu.js b/src/lib/Menu.js index fb92644d0..7a60c448f 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -1,5 +1,5 @@ import { remote, shell } from 'electron'; -import { observable, autorun, computed } from 'mobx'; +import { observable, autorun } from 'mobx'; import { defineMessages } from 'react-intl'; import { isMac, ctrlKey, cmdKey } from '../environment'; @@ -535,7 +535,8 @@ export default class FranzMenu { } _build() { - const serviceTpl = Object.assign([], this.serviceTpl); // need to clone object so we don't modify computed (cached) object + // need to clone object so we don't modify computed (cached) object + const serviceTpl = Object.assign([], this.serviceTpl()); if (window.franz === undefined) { return; @@ -708,7 +709,7 @@ export default class FranzMenu { Menu.setApplicationMenu(menu); } - @computed get serviceTpl() { + serviceTpl() { const { intl } = window.franz; const { user, services, settings } = this.stores; if (!user.isLoggedIn) return []; @@ -740,17 +741,15 @@ export default class FranzMenu { type: 'separator', }); - if (this.stores.user.isLoggedIn) { - services.allDisplayed.forEach((service, i) => (menu.push({ - label: this._getServiceName(service), - accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, - type: 'radio', - checked: service.isActive, - click: () => { - this.actions.service.setActive({ serviceId: service.id }); - }, - }))); - } + services.allDisplayed.forEach((service, i) => (menu.push({ + label: this._getServiceName(service), + accelerator: i < 9 ? `${cmdKey}+${i + 1}` : null, + type: 'radio', + checked: service.isActive, + click: () => { + this.actions.service.setActive({ serviceId: service.id }); + }, + }))); return menu; } -- cgit v1.2.3-70-g09d2 From e66fcaa1a8d17d2edfc8e262b7e012a55c1b484b Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 8 Mar 2019 16:45:14 +0100 Subject: fix(Windows): Fix copy & paste in service context menus Closes #1316 --- src/webview/contextMenu.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index afb1d8912..a4a6ab899 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -33,6 +33,8 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck const canGoBack = webContents.canGoBack(); const canGoForward = webContents.canGoForward(); + // @adlk: we can't use roles here due to a bug with electron where electron.remote.webContents.getFocusedWebContents() returns the first webview in DOM instead of the focused one + // Github issue creation is pending let menuTpl = [ { type: 'separator', @@ -48,19 +50,32 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck type: 'separator', }, { id: 'cut', - role: can('Cut') ? 'cut' : '', + label: 'Cut', + click() { + if (can('Cut')) { + webContents.cut(); + } + }, enabled: can('Cut'), visible: hasText && props.isEditable, }, { id: 'copy', label: 'Copy', - role: can('Copy') ? 'copy' : '', + click() { + if (can('Copy')) { + webContents.copy(); + } + }, enabled: can('Copy'), visible: props.isEditable || hasText, }, { id: 'paste', label: 'Paste', - role: editFlags.canPaste ? 'paste' : '', + click() { + if (editFlags.canPaste) { + webContents.paste(); + } + }, enabled: editFlags.canPaste, visible: props.isEditable, }, { -- cgit v1.2.3-70-g09d2 From 5b02c4d3304a570562d4dd089e46624a58697f1f Mon Sep 17 00:00:00 2001 From: skoruppa Date: Fri, 8 Mar 2019 18:04:25 +0200 Subject: fix(Linux): Fix minimized window focusing (#1304) (@skoruppa) * trigger build * Check if window is minimized before restoring it * restore() should be executed only when window is minimized --- src/index.js | 5 ++++- src/lib/Tray.js | 8 ++++++++ src/stores/AppStore.js | 9 ++++----- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 0e222c3d6..05c793d98 100644 --- a/src/index.js +++ b/src/index.js @@ -72,7 +72,10 @@ if (!gotTheLock) { app.on('second-instance', (event, argv) => { // Someone tried to run a second instance, we should focus our window. if (mainWindow) { - if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.show(); + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } mainWindow.focus(); if (isWindows) { diff --git a/src/lib/Tray.js b/src/lib/Tray.js index 669b02709..192e24796 100644 --- a/src/lib/Tray.js +++ b/src/lib/Tray.js @@ -22,7 +22,11 @@ export default class TrayIcon { { label: 'Show Franz', click() { + if (app.mainWindow.isMinimized()) { + app.mainWindow.restore(); + } app.mainWindow.show(); + app.mainWindow.focus(); }, }, { label: 'Quit Franz', @@ -36,7 +40,11 @@ export default class TrayIcon { this.trayIcon.setContextMenu(trayMenu); this.trayIcon.on('click', () => { + if (app.mainWindow.isMinimized()) { + app.mainWindow.restore(); + } app.mainWindow.show(); + app.mainWindow.focus(); }); if (process.platform === 'darwin') { diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 7784ff1f9..89eb16fe2 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -12,7 +12,7 @@ import { URL } from 'url'; import Store from './lib/Store'; import Request from './lib/Request'; import { CHECK_INTERVAL, DEFAULT_APP_SETTINGS } from '../config'; -import { isMac, isLinux, isWindows } from '../environment'; +import { isMac } from '../environment'; import locales from '../i18n/translations'; import { gaEvent, gaPage } from '../lib/analytics'; import { onVisibilityChange } from '../helpers/visibility-helper'; @@ -195,12 +195,11 @@ export default class AppStore extends Store { }); this.actions.service.setActive({ serviceId }); - - if (isWindows) { + mainWindow.show(); + if (app.mainWindow.isMinimized()) { mainWindow.restore(); - } else if (isLinux) { - mainWindow.show(); } + mainWindow.focus(); } }; } -- cgit v1.2.3-70-g09d2 From 03589f613e7d1ef559904360f260caa4e98897ff Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 8 Mar 2019 17:33:50 +0100 Subject: fix(Notifications): Fix notifications & notification click when icon is blob --- src/stores/AppStore.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 89eb16fe2..84450845a 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -185,6 +185,11 @@ export default class AppStore extends Store { }) { if (this.stores.settings.all.app.isAppMuted) return; + // TODO: is there a simple way to use blobs for notifications without storing them on disk? + if (options.icon.startsWith('blob:')) { + delete options.icon; + } + const notification = new window.Notification(title, options); notification.onclick = (e) => { if (serviceId) { -- cgit v1.2.3-70-g09d2 From baa45d935540601c07977e4d786e0953165cf1fa Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Fri, 8 Mar 2019 17:34:27 +0100 Subject: Fix/service webview unmounting (#1328) * detach service when underlying webview unmounts * disable no-param-reassign eslint rule --- .eslintrc | 1 + src/actions/service.js | 4 + src/components/services/content/ServiceView.js | 136 ++++++++++++++++++++ src/components/services/content/ServiceWebview.js | 145 ++++------------------ src/components/services/content/Services.js | 7 +- src/containers/layout/AppLayoutContainer.js | 3 + src/stores/ServicesStore.js | 6 + 7 files changed, 180 insertions(+), 122 deletions(-) create mode 100644 src/components/services/content/ServiceView.js diff --git a/.eslintrc b/.eslintrc index e15148e96..743946d35 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,6 +2,7 @@ "parser": "babel-eslint", "extends": "eslint-config-airbnb", "rules": { + "no-param-reassign": 0, "import/extensions": 0, "import/no-extraneous-dependencies": 0, "import/no-unresolved": [2, { diff --git a/src/actions/service.js b/src/actions/service.js index 5d483b12a..ceaabc31e 100644 --- a/src/actions/service.js +++ b/src/actions/service.js @@ -1,4 +1,5 @@ import PropTypes from 'prop-types'; +import ServiceModel from '../models/Service'; export default { setActive: { @@ -36,6 +37,9 @@ export default { serviceId: PropTypes.string.isRequired, webview: PropTypes.object.isRequired, }, + detachService: { + service: PropTypes.instanceOf(ServiceModel).isRequired, + }, focusService: { serviceId: PropTypes.string.isRequired, }, diff --git a/src/components/services/content/ServiceView.js b/src/components/services/content/ServiceView.js new file mode 100644 index 000000000..5afc54f9d --- /dev/null +++ b/src/components/services/content/ServiceView.js @@ -0,0 +1,136 @@ +import React, { Component, Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { autorun } from 'mobx'; +import { observer } from 'mobx-react'; +import classnames from 'classnames'; + +import ServiceModel from '../../../models/Service'; +import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; +import WebviewLoader from '../../ui/WebviewLoader'; +import WebviewCrashHandler from './WebviewCrashHandler'; +import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; +import ServiceDisabled from './ServiceDisabled'; +import ServiceWebview from './ServiceWebview'; + +export default @observer class ServiceView extends Component { + static propTypes = { + service: PropTypes.instanceOf(ServiceModel).isRequired, + setWebviewReference: PropTypes.func.isRequired, + detachService: PropTypes.func.isRequired, + reload: PropTypes.func.isRequired, + edit: PropTypes.func.isRequired, + enable: PropTypes.func.isRequired, + isActive: PropTypes.bool, + }; + + static defaultProps = { + isActive: false, + }; + + state = { + forceRepaint: false, + targetUrl: '', + statusBarVisible: false, + }; + + autorunDisposer = null; + + componentDidMount() { + this.autorunDisposer = autorun(() => { + if (this.props.service.isActive) { + this.setState({ forceRepaint: true }); + setTimeout(() => { + this.setState({ forceRepaint: false }); + }, 100); + } + }); + } + + componentWillUnmount() { + this.autorunDisposer(); + } + + updateTargetUrl = (event) => { + let visible = true; + if (event.url === '' || event.url === '#') { + visible = false; + } + this.setState({ + targetUrl: event.url, + statusBarVisible: visible, + }); + }; + + render() { + const { + detachService, + service, + setWebviewReference, + reload, + edit, + enable, + } = this.props; + + const webviewClasses = classnames({ + services__webview: true, + 'services__webview-wrapper': true, + 'is-active': service.isActive, + 'services__webview--force-repaint': this.state.forceRepaint, + }); + + let statusBar = null; + if (this.state.statusBarVisible) { + statusBar = ( + + ); + } + + return ( +
+ {service.isActive && service.isEnabled && ( + + {service.hasCrashed && ( + + )} + {service.isEnabled && service.isLoading && service.isFirstLoad && ( + + )} + {service.isError && ( + + )} + + )} + {!service.isEnabled ? ( + + {service.isActive && ( + + )} + + ) : ( + + )} + {statusBar} +
+ ); + } +} diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index bb577e4cc..7252c695f 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js @@ -1,145 +1,50 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { autorun } from 'mobx'; import { observer } from 'mobx-react'; -import Webview from 'react-electron-web-view'; -import classnames from 'classnames'; +import ElectronWebView from 'react-electron-web-view'; import ServiceModel from '../../../models/Service'; -import StatusBarTargetUrl from '../../ui/StatusBarTargetUrl'; -import WebviewLoader from '../../ui/WebviewLoader'; -import WebviewCrashHandler from './WebviewCrashHandler'; -import WebviewErrorHandler from './ErrorHandlers/WebviewErrorHandler'; -import ServiceDisabled from './ServiceDisabled'; -export default @observer class ServiceWebview extends Component { +@observer +class ServiceWebview extends Component { static propTypes = { service: PropTypes.instanceOf(ServiceModel).isRequired, setWebviewReference: PropTypes.func.isRequired, - reload: PropTypes.func.isRequired, - edit: PropTypes.func.isRequired, - enable: PropTypes.func.isRequired, - isActive: PropTypes.bool, + detachService: PropTypes.func.isRequired, }; - static defaultProps = { - isActive: false, - }; - - state = { - forceRepaint: false, - targetUrl: '', - statusBarVisible: false, - }; - - autorunDisposer = null; - webview = null; - componentDidMount() { - this.autorunDisposer = autorun(() => { - if (this.props.service.isActive) { - this.setState({ forceRepaint: true }); - setTimeout(() => { - this.setState({ forceRepaint: false }); - }, 100); - } - }); - } - componentWillUnmount() { - this.autorunDisposer(); - } - - updateTargetUrl = (event) => { - let visible = true; - if (event.url === '' || event.url === '#') { - visible = false; - } - this.setState({ - targetUrl: event.url, - statusBarVisible: visible, - }); + const { service, detachService } = this.props; + detachService({ service }); } render() { const { service, setWebviewReference, - reload, - edit, - enable, } = this.props; - const webviewClasses = classnames({ - services__webview: true, - 'services__webview-wrapper': true, - 'is-active': service.isActive, - 'services__webview--force-repaint': this.state.forceRepaint, - }); - - let statusBar = null; - if (this.state.statusBarVisible) { - statusBar = ( - - ); - } - return ( -
- {service.isActive && service.isEnabled && ( - - {service.hasCrashed && ( - - )} - {service.isEnabled && service.isLoading && service.isFirstLoad && ( - - )} - {service.isError && ( - - )} - - )} - {!service.isEnabled ? ( - - {service.isActive && ( - - )} - - ) : ( - { this.webview = element; }} - autosize - src={service.url} - preload="./webview/recipe.js" - partition={`persist:service-${service.id}`} - onDidAttach={() => setWebviewReference({ - serviceId: service.id, - webview: this.webview.view, - })} - onUpdateTargetUrl={this.updateTargetUrl} - useragent={service.userAgent} - allowpopups - /> - )} - {statusBar} -
+ { this.webview = webview; }} + autosize + src={service.url} + preload="./webview/recipe.js" + partition={`persist:service-${service.id}`} + onDidAttach={() => { + setWebviewReference({ + serviceId: service.id, + webview: this.webview.view, + }); + }} + onUpdateTargetUrl={this.updateTargetUrl} + useragent={service.userAgent} + allowpopups + /> ); } } + +export default ServiceWebview; diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index 54f16ba12..8f8c38a11 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js @@ -4,7 +4,7 @@ import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; import { Link } from 'react-router'; import { defineMessages, intlShape } from 'react-intl'; -import Webview from './ServiceWebview'; +import ServiceView from './ServiceView'; import Appear from '../../ui/effects/Appear'; const messages = defineMessages({ @@ -22,6 +22,7 @@ export default @observer class Services extends Component { static propTypes = { services: MobxPropTypes.arrayOrObservableArray, setWebviewReference: PropTypes.func.isRequired, + detachService: PropTypes.func.isRequired, handleIPCMessage: PropTypes.func.isRequired, openWindow: PropTypes.func.isRequired, reload: PropTypes.func.isRequired, @@ -42,6 +43,7 @@ export default @observer class Services extends Component { services, handleIPCMessage, setWebviewReference, + detachService, openWindow, reload, openSettings, @@ -71,11 +73,12 @@ export default @observer class Services extends Component { )} {services.map(service => ( - reload({ serviceId: service.id })} edit={() => openSettings({ path: `services/edit/${service.id}` })} diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 749912c59..5a05ce431 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -42,6 +42,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e setActive, handleIPCMessage, setWebviewReference, + detachService, openWindow, reorder, reload, @@ -105,6 +106,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e services={services.allDisplayedUnordered} handleIPCMessage={handleIPCMessage} setWebviewReference={setWebviewReference} + detachService={detachService} openWindow={openWindow} reload={reload} openSettings={openSettings} @@ -160,6 +162,7 @@ AppLayoutContainer.wrappedComponent.propTypes = { toggleAudio: PropTypes.func.isRequired, handleIPCMessage: PropTypes.func.isRequired, setWebviewReference: PropTypes.func.isRequired, + detachService: PropTypes.func.isRequired, openWindow: PropTypes.func.isRequired, reloadUpdatedServices: PropTypes.func.isRequired, updateService: PropTypes.func.isRequired, diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index c63bef196..69e616f0c 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -44,6 +44,7 @@ export default class ServicesStore extends Store { this.actions.service.deleteService.listen(this._deleteService.bind(this)); this.actions.service.clearCache.listen(this._clearCache.bind(this)); this.actions.service.setWebviewReference.listen(this._setWebviewReference.bind(this)); + this.actions.service.detachService.listen(this._detachService.bind(this)); this.actions.service.focusService.listen(this._focusService.bind(this)); this.actions.service.focusActiveService.listen(this._focusActiveService.bind(this)); this.actions.service.toggleService.listen(this._toggleService.bind(this)); @@ -341,6 +342,11 @@ export default class ServicesStore extends Store { service.isAttached = true; } + @action _detachService({ service }) { + service.webview = null; + service.isAttached = false; + } + @action _focusService({ serviceId }) { const service = this.one(serviceId); -- cgit v1.2.3-70-g09d2 From eb6624f375b8bdbca77ea852f64e2e027f9cf489 Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 8 Mar 2019 17:35:38 +0100 Subject: Add notification debug events --- src/stores/AppStore.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 84450845a..351ad6422 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -191,6 +191,9 @@ export default class AppStore extends Store { } const notification = new window.Notification(title, options); + + debug('New notification', title, options); + notification.onclick = (e) => { if (serviceId) { this.actions.service.sendIPCMessage({ @@ -205,6 +208,8 @@ export default class AppStore extends Store { mainWindow.restore(); } mainWindow.focus(); + + debug('Notification click handler'); } }; } -- cgit v1.2.3-70-g09d2 From a0a750257bf781cb4bc0ace3432d3d33e2ee2da8 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea Date: Mon, 11 Mar 2019 22:46:09 +0100 Subject: Update electron to 4.0.8 Update required in order to fix performance degradation due to memory leak issue https://github.com/electron/electron/pull/16772. --- package-lock.json | 25 +++++++++++++++---------- package.json | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc9837ccb..53e6c37f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1191,9 +1191,9 @@ } }, "@types/node": { - "version": "10.12.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.21.tgz", - "integrity": "sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ==", + "version": "10.12.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.30.tgz", + "integrity": "sha512-nsqTN6zUcm9xtdJiM9OvOJ5EF0kOI8f1Zuug27O/rgtxCRJHGqncSWfCMZUP852dCKPsDsYXGvBhxfRjDBkF5Q==", "dev": true }, "JSONStream": { @@ -4282,9 +4282,9 @@ "dev": true }, "electron": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/electron/-/electron-4.0.4.tgz", - "integrity": "sha512-zG5VtLrmPfmw1fXY/3BEtRZk7OZ7djQhweZ6rW+R5NeF6s8RTz/AwTGtLoBo4z8wmJ5QTy0Y941FZw4pe5YlpA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/electron/-/electron-4.0.8.tgz", + "integrity": "sha512-FOBJIHkuv8wc15N+ZyqwDzPavYVu5CHMBEf14jHDWv7QW2vkEIpJjVK+PIT31kfZfvjsIP0j2wvA/FBsiqB7pw==", "dev": true, "requires": { "@types/node": "^10.12.18", @@ -5956,7 +5956,8 @@ "version": "2.1.1", "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6421,7 +6422,8 @@ "version": "5.1.1", "resolved": false, "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6485,6 +6487,7 @@ "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6533,13 +6536,15 @@ "version": "1.0.2", "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "resolved": false, "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true + "dev": true, + "optional": true } } }, diff --git a/package.json b/package.json index 633fa678f..12a01182e 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "cross-env": "^5.0.5", "cz-conventional-changelog": "2.1.0", "dotenv": "^4.0.0", - "electron": "4.0.4", + "electron": "4.0.8", "electron-builder": "20.38.4", "electron-rebuild": "^1.6.0", "eslint": "5.10.0", -- cgit v1.2.3-70-g09d2