aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--electron-builder.yml7
-rw-r--r--package-lock.json6
-rw-r--r--package.json2
-rw-r--r--packages/theme/src/themes/dark/index.ts1
-rw-r--r--packages/theme/src/themes/default/index.ts1
-rw-r--r--src/components/services/content/ServiceWebview.js12
-rw-r--r--src/components/services/content/Services.js12
-rw-r--r--src/components/ui/Modal/styles.js2
-rw-r--r--src/features/workspaces/components/WorkspaceDrawer.js4
-rw-r--r--src/features/workspaces/components/WorkspaceDrawerItem.js4
-rw-r--r--src/index.js17
-rw-r--r--src/models/Service.js41
-rw-r--r--src/stores/ServicesStore.js1
-rw-r--r--src/webview/recipe.js8
14 files changed, 82 insertions, 36 deletions
diff --git a/electron-builder.yml b/electron-builder.yml
index 97aafa207..081149531 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -9,6 +9,7 @@ compression: maximum
9mac: 9mac:
10 category: public.app-category.productivity 10 category: public.app-category.productivity
11 icon: ./build-helpers/images/icon.icns 11 icon: ./build-helpers/images/icon.icns
12 darkModeSupport: true
12 13
13dmg: 14dmg:
14 background: ./build-helpers/images/dmgInstaller.tiff 15 background: ./build-helpers/images/dmgInstaller.tiff
@@ -39,10 +40,10 @@ nsis:
39 perMachine: false 40 perMachine: false
40 oneClick: true 41 oneClick: true
41 42
42protocols: 43protocols:
43 name: Franz 44 name: Franz
44 schemes: [franz] 45 schemes: [franz]
45 46
46asarUnpack: 47asarUnpack:
47 - ./dictionaries 48 - ./dictionaries
48 - ./assets/images/taskbar 49 - ./assets/images/taskbar
diff --git a/package-lock.json b/package-lock.json
index af319225e..b0cc72ec7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6946,9 +6946,9 @@
6946 "dev": true 6946 "dev": true
6947 }, 6947 },
6948 "electron": { 6948 "electron": {
6949 "version": "6.0.11", 6949 "version": "6.0.10",
6950 "resolved": "https://registry.npmjs.org/electron/-/electron-6.0.11.tgz", 6950 "resolved": "https://registry.npmjs.org/electron/-/electron-6.0.10.tgz",
6951 "integrity": "sha512-mi1oHmeFIQrg+CDQ6lbugZAloOxuWPm/ecEKYe1230PGlDoWND7SYStiWQ2eI4YXAEOL/NvuY88ogemu1qhdBg==", 6951 "integrity": "sha512-eTFm6uTn7NKZE1OtSZSOxNuOrCXXeUR0U3vdF3R00byB7mrNe5AOaXEDDMwtzRGGY1jMuUX9Z7RvgXaCXRYSmw==",
6952 "dev": true, 6952 "dev": true,
6953 "requires": { 6953 "requires": {
6954 "@types/node": "^10.12.18", 6954 "@types/node": "^10.12.18",
diff --git a/package.json b/package.json
index 51da0fe93..09874bc59 100644
--- a/package.json
+++ b/package.json
@@ -120,7 +120,7 @@
120 "cross-env": "^5.0.5", 120 "cross-env": "^5.0.5",
121 "cz-conventional-changelog": "2.1.0", 121 "cz-conventional-changelog": "2.1.0",
122 "dotenv": "^4.0.0", 122 "dotenv": "^4.0.0",
123 "electron": "6.0.11", 123 "electron": "6.0.10",
124 "electron-builder": "21.2.0", 124 "electron-builder": "21.2.0",
125 "electron-rebuild": "1.8.4", 125 "electron-rebuild": "1.8.4",
126 "eslint": "5.10.0", 126 "eslint": "5.10.0",
diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts
index e94f54c55..67d0cfb71 100644
--- a/packages/theme/src/themes/dark/index.ts
+++ b/packages/theme/src/themes/dark/index.ts
@@ -66,6 +66,7 @@ export const selectSearchColor = inputBackground;
66 66
67// Modal 67// Modal
68export const colorModalOverlayBackground = color(legacyStyles.darkThemeBlack).alpha(0.8).rgb().string(); 68export const colorModalOverlayBackground = color(legacyStyles.darkThemeBlack).alpha(0.8).rgb().string();
69export const colorModalBackground = colorContentBackground;
69 70
70// Services 71// Services
71export const services = merge({}, defaultStyles.services, { 72export const services = merge({}, defaultStyles.services, {
diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts
index 4e042afce..057fde72f 100644
--- a/packages/theme/src/themes/default/index.ts
+++ b/packages/theme/src/themes/default/index.ts
@@ -145,6 +145,7 @@ export const badgeBorderRadius = 50;
145 145
146// Modal 146// Modal
147export const colorModalOverlayBackground = color('#000').alpha(0.5).rgb().string(); 147export const colorModalOverlayBackground = color('#000').alpha(0.5).rgb().string();
148export const colorModalBackground = colorContentBackground;
148 149
149// Services 150// Services
150export const services = { 151export const services = {
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js
index 07bd17d9c..b3198d36a 100644
--- a/src/components/services/content/ServiceWebview.js
+++ b/src/components/services/content/ServiceWebview.js
@@ -20,6 +20,13 @@ class ServiceWebview extends Component {
20 detachService({ service }); 20 detachService({ service });
21 } 21 }
22 22
23 refocusWebview = () => {
24 const { webview } = this;
25 if (!webview) return;
26 webview.view.blur();
27 webview.view.focus();
28 };
29
23 render() { 30 render() {
24 const { 31 const {
25 service, 32 service,
@@ -28,7 +35,10 @@ class ServiceWebview extends Component {
28 35
29 return ( 36 return (
30 <ElectronWebView 37 <ElectronWebView
31 ref={(webview) => { this.webview = webview; }} 38 ref={(webview) => {
39 this.webview = webview;
40 webview.view.addEventListener('did-stop-loading', this.refocusWebview);
41 }}
32 autosize 42 autosize
33 src={service.url} 43 src={service.url}
34 preload="./webview/recipe.js" 44 preload="./webview/recipe.js"
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js
index 73c27bfb6..b6291666b 100644
--- a/src/components/services/content/Services.js
+++ b/src/components/services/content/Services.js
@@ -56,16 +56,24 @@ export default @observer @injectSheet(styles) class Services extends Component {
56 56
57 state = { 57 state = {
58 showConfetti: true, 58 showConfetti: true,
59 } 59 };
60
61 _confettiTimeout = null;
60 62
61 componentDidMount() { 63 componentDidMount() {
62 window.setTimeout(() => { 64 this._confettiTimeout = window.setTimeout(() => {
63 this.setState({ 65 this.setState({
64 showConfetti: false, 66 showConfetti: false,
65 }); 67 });
66 }, ms('8s')); 68 }, ms('8s'));
67 } 69 }
68 70
71 componentWillUnmount() {
72 if (this._confettiTimeout) {
73 clearTimeout(this._confettiTimeout);
74 }
75 }
76
69 render() { 77 render() {
70 const { 78 const {
71 services, 79 services,
diff --git a/src/components/ui/Modal/styles.js b/src/components/ui/Modal/styles.js
index 49b970c97..c2bebf9bb 100644
--- a/src/components/ui/Modal/styles.js
+++ b/src/components/ui/Modal/styles.js
@@ -13,7 +13,7 @@ export default theme => ({
13 display: 'flex', 13 display: 'flex',
14 }, 14 },
15 modal: { 15 modal: {
16 background: '#FFF', 16 background: theme.colorModalBackground,
17 maxWidth: '90%', 17 maxWidth: '90%',
18 height: 'auto', 18 height: 'auto',
19 margin: 'auto auto', 19 margin: 'auto auto',
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js
index e7bc0b157..ee6f8416c 100644
--- a/src/features/workspaces/components/WorkspaceDrawer.js
+++ b/src/features/workspaces/components/WorkspaceDrawer.js
@@ -204,8 +204,9 @@ class WorkspaceDrawer extends Component {
204 }} 204 }}
205 services={getServicesForWorkspace(null)} 205 services={getServicesForWorkspace(null)}
206 isActive={actualWorkspace == null} 206 isActive={actualWorkspace == null}
207 shortcutIndex={0}
207 /> 208 />
208 {workspaces.map(workspace => ( 209 {workspaces.map((workspace, index) => (
209 <WorkspaceDrawerItem 210 <WorkspaceDrawerItem
210 key={workspace.id} 211 key={workspace.id}
211 name={workspace.name} 212 name={workspace.name}
@@ -218,6 +219,7 @@ class WorkspaceDrawer extends Component {
218 }} 219 }}
219 onContextMenuEditClick={() => workspaceActions.edit({ workspace })} 220 onContextMenuEditClick={() => workspaceActions.edit({ workspace })}
220 services={getServicesForWorkspace(workspace)} 221 services={getServicesForWorkspace(workspace)}
222 shortcutIndex={index + 1}
221 /> 223 />
222 ))} 224 ))}
223 <div 225 <div
diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js
index 59a2144d3..18f424d8a 100644
--- a/src/features/workspaces/components/WorkspaceDrawerItem.js
+++ b/src/features/workspaces/components/WorkspaceDrawerItem.js
@@ -5,6 +5,7 @@ import { observer } from 'mobx-react';
5import injectSheet from 'react-jss'; 5import injectSheet from 'react-jss';
6import classnames from 'classnames'; 6import classnames from 'classnames';
7import { defineMessages, intlShape } from 'react-intl'; 7import { defineMessages, intlShape } from 'react-intl';
8import { ctrlKey } from '../../../environment';
8 9
9const { Menu } = remote; 10const { Menu } = remote;
10 11
@@ -69,6 +70,7 @@ class WorkspaceDrawerItem extends Component {
69 onClick: PropTypes.func.isRequired, 70 onClick: PropTypes.func.isRequired,
70 services: PropTypes.arrayOf(PropTypes.string).isRequired, 71 services: PropTypes.arrayOf(PropTypes.string).isRequired,
71 onContextMenuEditClick: PropTypes.func, 72 onContextMenuEditClick: PropTypes.func,
73 shortcutIndex: PropTypes.number.isRequired,
72 }; 74 };
73 75
74 static defaultProps = { 76 static defaultProps = {
@@ -87,6 +89,7 @@ class WorkspaceDrawerItem extends Component {
87 onClick, 89 onClick,
88 onContextMenuEditClick, 90 onContextMenuEditClick,
89 services, 91 services,
92 shortcutIndex,
90 } = this.props; 93 } = this.props;
91 const { intl } = this.context; 94 const { intl } = this.context;
92 95
@@ -112,6 +115,7 @@ class WorkspaceDrawerItem extends Component {
112 onContextMenu={() => ( 115 onContextMenu={() => (
113 onContextMenuEditClick && contextMenu.popup(remote.getCurrentWindow()) 116 onContextMenuEditClick && contextMenu.popup(remote.getCurrentWindow())
114 )} 117 )}
118 data-tip={`${shortcutIndex <= 9 ? `(${ctrlKey}+Alt+${shortcutIndex})` : ''}`}
115 > 119 >
116 <span 120 <span
117 className={classnames([ 121 className={classnames([
diff --git a/src/index.js b/src/index.js
index d9d51fd5b..7de7a5e1c 100644
--- a/src/index.js
+++ b/src/index.js
@@ -331,22 +331,7 @@ app.on('login', (event, webContents, request, authInfo, callback) => {
331 debug('browser login event', authInfo); 331 debug('browser login event', authInfo);
332 event.preventDefault(); 332 event.preventDefault();
333 333
334 if (authInfo.isProxy && authInfo.scheme === 'basic') { 334 if (!authInfo.isProxy && authInfo.scheme === 'basic') {
335 debug('Sending service echo ping');
336 webContents.send('get-service-id');
337
338 ipcMain.once('service-id', (e, id) => {
339 debug('Received service id', id);
340
341 const ps = proxySettings.get(id);
342 if (ps) {
343 debug('Sending proxy auth callback for service', id);
344 callback(ps.user, ps.password);
345 } else {
346 debug('No proxy auth config found for', id);
347 }
348 });
349 } else if (authInfo.scheme === 'basic') {
350 debug('basic auth handler', authInfo); 335 debug('basic auth handler', authInfo);
351 basicAuthHandler(mainWindow, authInfo); 336 basicAuthHandler(mainWindow, authInfo);
352 } 337 }
diff --git a/src/models/Service.js b/src/models/Service.js
index 023103048..e45c39564 100644
--- a/src/models/Service.js
+++ b/src/models/Service.js
@@ -188,19 +188,24 @@ export default class Service {
188 return userAgent; 188 return userAgent;
189 } 189 }
190 190
191 initializeWebViewEvents({ handleIPCMessage, openWindow }) { 191 initializeWebViewEvents({ handleIPCMessage, openWindow, stores }) {
192 const webContents = this.webview.getWebContents();
193
192 this.webview.addEventListener('ipc-message', e => handleIPCMessage({ 194 this.webview.addEventListener('ipc-message', e => handleIPCMessage({
193 serviceId: this.id, 195 serviceId: this.id,
194 channel: e.channel, 196 channel: e.channel,
195 args: e.args, 197 args: e.args,
196 })); 198 }));
197 199
198 this.webview.addEventListener('new-window', (event, url, frameName, options) => openWindow({ 200 this.webview.addEventListener('new-window', (event, url, frameName, options) => {
199 event, 201 console.log('open window', event, url, frameName, options);
200 url, 202 openWindow({
201 frameName, 203 event,
202 options, 204 url,
203 })); 205 frameName,
206 options,
207 });
208 });
204 209
205 this.webview.addEventListener('did-start-loading', (event) => { 210 this.webview.addEventListener('did-start-loading', (event) => {
206 debug('Did start load', this.name, event); 211 debug('Did start load', this.name, event);
@@ -234,6 +239,28 @@ export default class Service {
234 debug('Service crashed', this.name); 239 debug('Service crashed', this.name);
235 this.hasCrashed = true; 240 this.hasCrashed = true;
236 }); 241 });
242
243 webContents.on('login', (event, request, authInfo, callback) => {
244 // const authCallback = callback;
245 debug('browser login event', authInfo);
246 event.preventDefault();
247
248 if (authInfo.isProxy && authInfo.scheme === 'basic') {
249 debug('Sending service echo ping');
250 webContents.send('get-service-id');
251
252 debug('Received service id', this.id);
253
254 const ps = stores.settings.proxy[this.id];
255
256 if (ps) {
257 debug('Sending proxy auth callback for service', this.id);
258 callback(ps.user, ps.password);
259 } else {
260 debug('No proxy auth config found for', this.id);
261 }
262 }
263 });
237 } 264 }
238 265
239 initializeWebViewListener() { 266 initializeWebViewListener() {
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js
index d1fd2be3d..08befe4eb 100644
--- a/src/stores/ServicesStore.js
+++ b/src/stores/ServicesStore.js
@@ -345,6 +345,7 @@ export default class ServicesStore extends Store {
345 service.initializeWebViewEvents({ 345 service.initializeWebViewEvents({
346 handleIPCMessage: this.actions.service.handleIPCMessage, 346 handleIPCMessage: this.actions.service.handleIPCMessage,
347 openWindow: this.actions.service.openWindow, 347 openWindow: this.actions.service.openWindow,
348 stores: this.stores,
348 }); 349 });
349 service.initializeWebViewListener(); 350 service.initializeWebViewListener();
350 } 351 }
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index 60660d8f1..e3e13b726 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -12,6 +12,7 @@ import contextMenu from './contextMenu';
12import './notifications'; 12import './notifications';
13 13
14import { DEFAULT_APP_SETTINGS } from '../config'; 14import { DEFAULT_APP_SETTINGS } from '../config';
15import { isDevMode } from '../environment';
15 16
16const debug = require('debug')('Franz:Plugin'); 17const debug = require('debug')('Franz:Plugin');
17 18
@@ -173,6 +174,7 @@ new RecipeController();
173// Patching window.open 174// Patching window.open
174const originalWindowOpen = window.open; 175const originalWindowOpen = window.open;
175 176
177
176window.open = (url, frameName, features) => { 178window.open = (url, frameName, features) => {
177 if (!url && !frameName && !features) { 179 if (!url && !frameName && !features) {
178 // The service hasn't yet supplied a URL (as used in Skype). 180 // The service hasn't yet supplied a URL (as used in Skype).
@@ -201,9 +203,13 @@ window.open = (url, frameName, features) => {
201 } 203 }
202 204
203 // We need to differentiate if the link should be opened in a popup or in the systems default browser 205 // We need to differentiate if the link should be opened in a popup or in the systems default browser
204 if (!frameName && !features) { 206 if (!frameName && !features && typeof features !== 'string') {
205 return ipcRenderer.sendToHost('new-window', url); 207 return ipcRenderer.sendToHost('new-window', url);
206 } 208 }
207 209
208 return originalWindowOpen(url, frameName, features); 210 return originalWindowOpen(url, frameName, features);
209}; 211};
212
213if (isDevMode) {
214 window.log = console.log;
215}