diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/services/content/ErrorHandlers/WebviewErrorHandler.js | 2 | ||||
-rw-r--r-- | src/components/services/content/ErrorHandlers/styles.js | 6 | ||||
-rw-r--r-- | src/components/services/content/ServiceWebview.js | 3 | ||||
-rw-r--r-- | src/components/services/content/Services.js | 3 | ||||
-rw-r--r-- | src/config.js | 3 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 1 | ||||
-rw-r--r-- | src/environment.js | 6 | ||||
-rw-r--r-- | src/helpers/asar-helpers.js | 3 | ||||
-rw-r--r-- | src/index.js | 142 | ||||
-rw-r--r-- | src/models/Service.js | 4 | ||||
-rw-r--r-- | src/stores/AppStore.js | 7 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 15 | ||||
-rw-r--r-- | src/stores/UserStore.js | 27 | ||||
-rw-r--r-- | src/styles/layout.scss | 2 | ||||
-rw-r--r-- | src/theme/dark/index.js | 3 | ||||
-rw-r--r-- | src/theme/default/index.js | 3 |
16 files changed, 143 insertions, 87 deletions
diff --git a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js index 415a8d1b5..37ccc8e51 100644 --- a/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js +++ b/src/components/services/content/ErrorHandlers/WebviewErrorHandler.js | |||
@@ -31,7 +31,7 @@ const messages = defineMessages({ | |||
31 | }, | 31 | }, |
32 | }); | 32 | }); |
33 | 33 | ||
34 | export default @injectSheet(styles) @observer class WebviewCrashHandler extends Component { | 34 | export default @injectSheet(styles) @observer class WebviewErrorHandler extends Component { |
35 | static propTypes = { | 35 | static propTypes = { |
36 | name: PropTypes.string.isRequired, | 36 | name: PropTypes.string.isRequired, |
37 | reload: PropTypes.func.isRequired, | 37 | reload: PropTypes.func.isRequired, |
diff --git a/src/components/services/content/ErrorHandlers/styles.js b/src/components/services/content/ErrorHandlers/styles.js index f11386798..9e2509ee5 100644 --- a/src/components/services/content/ErrorHandlers/styles.js +++ b/src/components/services/content/ErrorHandlers/styles.js | |||
@@ -1,4 +1,4 @@ | |||
1 | export default { | 1 | export default theme => ({ |
2 | component: { | 2 | component: { |
3 | left: 0, | 3 | left: 0, |
4 | position: 'absolute', | 4 | position: 'absolute', |
@@ -6,7 +6,7 @@ export default { | |||
6 | width: '100%', | 6 | width: '100%', |
7 | zIndex: 0, | 7 | zIndex: 0, |
8 | alignItems: 'center', | 8 | alignItems: 'center', |
9 | // background: $theme-gray-lighter; | 9 | background: theme.colorWebviewErrorHandlerBackground, |
10 | display: 'flex', | 10 | display: 'flex', |
11 | flexDirection: 'column', | 11 | flexDirection: 'column', |
12 | justifyContent: 'center', | 12 | justifyContent: 'center', |
@@ -22,4 +22,4 @@ export default { | |||
22 | margin: [0, 10, 0, 10], | 22 | margin: [0, 10, 0, 10], |
23 | }, | 23 | }, |
24 | }, | 24 | }, |
25 | }; | 25 | }); |
diff --git a/src/components/services/content/ServiceWebview.js b/src/components/services/content/ServiceWebview.js index b1a2c0207..bb577e4cc 100644 --- a/src/components/services/content/ServiceWebview.js +++ b/src/components/services/content/ServiceWebview.js | |||
@@ -18,7 +18,6 @@ export default @observer class ServiceWebview extends Component { | |||
18 | setWebviewReference: PropTypes.func.isRequired, | 18 | setWebviewReference: PropTypes.func.isRequired, |
19 | reload: PropTypes.func.isRequired, | 19 | reload: PropTypes.func.isRequired, |
20 | edit: PropTypes.func.isRequired, | 20 | edit: PropTypes.func.isRequired, |
21 | isAppMuted: PropTypes.bool.isRequired, | ||
22 | enable: PropTypes.func.isRequired, | 21 | enable: PropTypes.func.isRequired, |
23 | isActive: PropTypes.bool, | 22 | isActive: PropTypes.bool, |
24 | }; | 23 | }; |
@@ -69,7 +68,6 @@ export default @observer class ServiceWebview extends Component { | |||
69 | setWebviewReference, | 68 | setWebviewReference, |
70 | reload, | 69 | reload, |
71 | edit, | 70 | edit, |
72 | isAppMuted, | ||
73 | enable, | 71 | enable, |
74 | } = this.props; | 72 | } = this.props; |
75 | 73 | ||
@@ -137,7 +135,6 @@ export default @observer class ServiceWebview extends Component { | |||
137 | })} | 135 | })} |
138 | onUpdateTargetUrl={this.updateTargetUrl} | 136 | onUpdateTargetUrl={this.updateTargetUrl} |
139 | useragent={service.userAgent} | 137 | useragent={service.userAgent} |
140 | muted={isAppMuted || service.isMuted} | ||
141 | allowpopups | 138 | allowpopups |
142 | /> | 139 | /> |
143 | )} | 140 | )} |
diff --git a/src/components/services/content/Services.js b/src/components/services/content/Services.js index 1aeb17e03..54f16ba12 100644 --- a/src/components/services/content/Services.js +++ b/src/components/services/content/Services.js | |||
@@ -26,7 +26,6 @@ export default @observer class Services extends Component { | |||
26 | openWindow: PropTypes.func.isRequired, | 26 | openWindow: PropTypes.func.isRequired, |
27 | reload: PropTypes.func.isRequired, | 27 | reload: PropTypes.func.isRequired, |
28 | openSettings: PropTypes.func.isRequired, | 28 | openSettings: PropTypes.func.isRequired, |
29 | isAppMuted: PropTypes.bool.isRequired, | ||
30 | update: PropTypes.func.isRequired, | 29 | update: PropTypes.func.isRequired, |
31 | }; | 30 | }; |
32 | 31 | ||
@@ -46,7 +45,6 @@ export default @observer class Services extends Component { | |||
46 | openWindow, | 45 | openWindow, |
47 | reload, | 46 | reload, |
48 | openSettings, | 47 | openSettings, |
49 | isAppMuted, | ||
50 | update, | 48 | update, |
51 | } = this.props; | 49 | } = this.props; |
52 | const { intl } = this.context; | 50 | const { intl } = this.context; |
@@ -81,7 +79,6 @@ export default @observer class Services extends Component { | |||
81 | openWindow={openWindow} | 79 | openWindow={openWindow} |
82 | reload={() => reload({ serviceId: service.id })} | 80 | reload={() => reload({ serviceId: service.id })} |
83 | edit={() => openSettings({ path: `services/edit/${service.id}` })} | 81 | edit={() => openSettings({ path: `services/edit/${service.id}` })} |
84 | isAppMuted={isAppMuted} | ||
85 | enable={() => update({ | 82 | enable={() => update({ |
86 | serviceId: service.id, | 83 | serviceId: service.id, |
87 | serviceData: { | 84 | serviceData: { |
diff --git a/src/config.js b/src/config.js index 789ddd1a0..101a4379a 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -1,5 +1,6 @@ | |||
1 | import electron from 'electron'; | 1 | import electron from 'electron'; |
2 | import path from 'path'; | 2 | import path from 'path'; |
3 | import { asarPath } from './helpers/asar-helpers'; | ||
3 | 4 | ||
4 | const app = process.type === 'renderer' ? electron.remote.app : electron.app; | 5 | const app = process.type === 'renderer' ? electron.remote.app : electron.app; |
5 | const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences; | 6 | const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences; |
@@ -57,4 +58,4 @@ export const FILE_SYSTEM_SETTINGS_TYPES = [ | |||
57 | export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config'); | 58 | export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config'); |
58 | 59 | ||
59 | // Replacing app.asar is not beautiful but unforunately necessary | 60 | // Replacing app.asar is not beautiful but unforunately necessary |
60 | export const DICTIONARY_PATH = path.join(__dirname, 'dictionaries').replace('app.asar', 'app.asar.unpacked'); | 61 | export const DICTIONARY_PATH = asarPath(path.join(__dirname, 'dictionaries').replace('app.asar', 'app.asar.unpacked')); |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 430b49b55..749912c59 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -108,7 +108,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
108 | openWindow={openWindow} | 108 | openWindow={openWindow} |
109 | reload={reload} | 109 | reload={reload} |
110 | openSettings={openSettings} | 110 | openSettings={openSettings} |
111 | isAppMuted={settings.all.app.isAppMuted} | ||
112 | update={updateService} | 111 | update={updateService} |
113 | /> | 112 | /> |
114 | ); | 113 | ); |
diff --git a/src/environment.js b/src/environment.js index e1762129b..73b1c7ab2 100644 --- a/src/environment.js +++ b/src/environment.js | |||
@@ -1,10 +1,12 @@ | |||
1 | import isDev from 'electron-is-dev'; | ||
2 | |||
1 | import { LIVE_API, DEV_API, LOCAL_API } from './config'; | 3 | import { LIVE_API, DEV_API, LOCAL_API } from './config'; |
2 | 4 | ||
3 | export const isDevMode = Boolean(process.execPath.match(/[\\/]electron/)); | 5 | export const isDevMode = isDev; |
4 | export const useLiveAPI = process.env.LIVE_API; | 6 | export const useLiveAPI = process.env.LIVE_API; |
5 | export const useLocalAPI = process.env.LOCAL_API; | 7 | export const useLocalAPI = process.env.LOCAL_API; |
6 | 8 | ||
7 | let platform = process.platform; | 9 | let { platform } = process; |
8 | if (process.env.OS_PLATFORM) { | 10 | if (process.env.OS_PLATFORM) { |
9 | platform = process.env.OS_PLATFORM; | 11 | platform = process.env.OS_PLATFORM; |
10 | } | 12 | } |
diff --git a/src/helpers/asar-helpers.js b/src/helpers/asar-helpers.js new file mode 100644 index 000000000..9e4380c06 --- /dev/null +++ b/src/helpers/asar-helpers.js | |||
@@ -0,0 +1,3 @@ | |||
1 | export function asarPath(dir = '') { | ||
2 | return dir.replace('app.asar', 'app.asar.unpacked'); | ||
3 | } | ||
diff --git a/src/index.js b/src/index.js index f34df8c17..6a0ee600f 100644 --- a/src/index.js +++ b/src/index.js | |||
@@ -4,25 +4,23 @@ import { | |||
4 | shell, | 4 | shell, |
5 | ipcMain, | 5 | ipcMain, |
6 | } from 'electron'; | 6 | } from 'electron'; |
7 | 7 | import isDevMode from 'electron-is-dev'; | |
8 | import fs from 'fs-extra'; | 8 | import fs from 'fs-extra'; |
9 | import path from 'path'; | 9 | import path from 'path'; |
10 | import windowStateKeeper from 'electron-window-state'; | 10 | import windowStateKeeper from 'electron-window-state'; |
11 | 11 | ||
12 | // Set app directory before loading user modules | ||
13 | if (isDevMode) { | ||
14 | app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev')); | ||
15 | } | ||
16 | |||
17 | /* eslint-disable import/first */ | ||
12 | import { | 18 | import { |
13 | isDevMode, | ||
14 | isMac, | 19 | isMac, |
15 | isWindows, | 20 | isWindows, |
16 | isLinux, | 21 | isLinux, |
17 | } from './environment'; | 22 | } from './environment'; |
18 | |||
19 | import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; | 23 | import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; |
20 | |||
21 | // DEV MODE: Save user data into FranzDev | ||
22 | if (isDevMode) { | ||
23 | app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev')); | ||
24 | } | ||
25 | /* eslint-disable import/first */ | ||
26 | import ipcApi from './electron/ipc-api'; | 24 | import ipcApi from './electron/ipc-api'; |
27 | import Tray from './lib/Tray'; | 25 | import Tray from './lib/Tray'; |
28 | import Settings from './electron/Settings'; | 26 | import Settings from './electron/Settings'; |
@@ -35,6 +33,7 @@ import { | |||
35 | DEFAULT_APP_SETTINGS, | 33 | DEFAULT_APP_SETTINGS, |
36 | DEFAULT_WINDOW_OPTIONS, | 34 | DEFAULT_WINDOW_OPTIONS, |
37 | } from './config'; | 35 | } from './config'; |
36 | import { asarPath } from './helpers/asar-helpers'; | ||
38 | /* eslint-enable import/first */ | 37 | /* eslint-enable import/first */ |
39 | 38 | ||
40 | const debug = require('debug')('Franz:App'); | 39 | const debug = require('debug')('Franz:App'); |
@@ -44,6 +43,17 @@ const debug = require('debug')('Franz:App'); | |||
44 | let mainWindow; | 43 | let mainWindow; |
45 | let willQuitApp = false; | 44 | let willQuitApp = false; |
46 | 45 | ||
46 | // Register methods to be called once the window has been loaded. | ||
47 | let onDidLoadFns = []; | ||
48 | |||
49 | function onDidLoad(fn) { | ||
50 | if (onDidLoadFns) { | ||
51 | onDidLoadFns.push(fn); | ||
52 | } else if (mainWindow) { | ||
53 | fn(mainWindow); | ||
54 | } | ||
55 | } | ||
56 | |||
47 | // Ensure that the recipe directory exists | 57 | // Ensure that the recipe directory exists |
48 | fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); | 58 | fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); |
49 | fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json')); | 59 | fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json')); |
@@ -65,58 +75,32 @@ if (!gotTheLock) { | |||
65 | mainWindow.focus(); | 75 | mainWindow.focus(); |
66 | 76 | ||
67 | if (isWindows) { | 77 | if (isWindows) { |
68 | // Keep only command line / deep linked arguments | 78 | onDidLoad((window) => { |
69 | const url = argv.slice(1); | 79 | // Keep only command line / deep linked arguments |
70 | 80 | const url = argv.slice(1); | |
71 | if (url) { | 81 | if (url) { |
72 | handleDeepLink(mainWindow, url.toString()); | 82 | handleDeepLink(window, url.toString()); |
73 | } | 83 | } |
74 | } | 84 | |
75 | 85 | if (argv.includes('--reset-window')) { | |
76 | if (argv.includes('--reset-window')) { | 86 | // Needs to be delayed to not interfere with mainWindow.restore(); |
77 | // Needs to be delayed to not interfere with mainWindow.restore(); | 87 | setTimeout(() => { |
78 | setTimeout(() => { | 88 | debug('Resetting windows via Task'); |
79 | debug('Resetting windows via Task'); | 89 | window.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100); |
80 | mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100); | 90 | window.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height); |
81 | mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height); | 91 | }, 1); |
82 | }, 1); | 92 | } else if (argv.includes('--quit')) { |
93 | // Needs to be delayed to not interfere with mainWindow.restore(); | ||
94 | setTimeout(() => { | ||
95 | debug('Quitting Franz via Task'); | ||
96 | app.quit(); | ||
97 | }, 1); | ||
98 | } | ||
99 | }); | ||
83 | } | 100 | } |
84 | } | 101 | } |
85 | }); | 102 | }); |
86 | |||
87 | // Create myWindow, load the rest of the app, etc... | ||
88 | app.on('ready', () => { | ||
89 | }); | ||
90 | } | 103 | } |
91 | // const isSecondInstance = app.makeSingleInstance((argv) => { | ||
92 | // if (mainWindow) { | ||
93 | // if (mainWindow.isMinimized()) mainWindow.restore(); | ||
94 | // mainWindow.focus(); | ||
95 | |||
96 | // if (process.platform === 'win32') { | ||
97 | // // Keep only command line / deep linked arguments | ||
98 | // const url = argv.slice(1); | ||
99 | |||
100 | // if (url) { | ||
101 | // handleDeepLink(mainWindow, url.toString()); | ||
102 | // } | ||
103 | // } | ||
104 | // } | ||
105 | |||
106 | // if (argv.includes('--reset-window')) { | ||
107 | // // Needs to be delayed to not interfere with mainWindow.restore(); | ||
108 | // setTimeout(() => { | ||
109 | // debug('Resetting windows via Task'); | ||
110 | // mainWindow.setPosition(DEFAULT_WINDOW_OPTIONS.x + 100, DEFAULT_WINDOW_OPTIONS.y + 100); | ||
111 | // mainWindow.setSize(DEFAULT_WINDOW_OPTIONS.width, DEFAULT_WINDOW_OPTIONS.height); | ||
112 | // }, 1); | ||
113 | // } | ||
114 | // }); | ||
115 | |||
116 | // if (isSecondInstance) { | ||
117 | // console.log('An instance of Franz is already running. Exiting...'); | ||
118 | // app.exit(); | ||
119 | // } | ||
120 | 104 | ||
121 | // Fix Unity indicator issue | 105 | // Fix Unity indicator issue |
122 | // https://github.com/electron/electron/issues/9046 | 106 | // https://github.com/electron/electron/issues/9046 |
@@ -166,6 +150,14 @@ const createWindow = () => { | |||
166 | }, | 150 | }, |
167 | }); | 151 | }); |
168 | 152 | ||
153 | mainWindow.webContents.on('did-finish-load', () => { | ||
154 | const fns = onDidLoadFns; | ||
155 | onDidLoadFns = null; | ||
156 | for (const fn of fns) { | ||
157 | fn(mainWindow); | ||
158 | } | ||
159 | }); | ||
160 | |||
169 | // Initialize System Tray | 161 | // Initialize System Tray |
170 | const trayIcon = new Tray(); | 162 | const trayIcon = new Tray(); |
171 | 163 | ||
@@ -190,6 +182,16 @@ const createWindow = () => { | |||
190 | mainWindow.webContents.openDevTools(); | 182 | mainWindow.webContents.openDevTools(); |
191 | } | 183 | } |
192 | 184 | ||
185 | // Windows deep linking handling on app launch | ||
186 | if (isWindows) { | ||
187 | onDidLoad((window) => { | ||
188 | const url = process.argv.slice(1); | ||
189 | if (url) { | ||
190 | handleDeepLink(window, url.toString()); | ||
191 | } | ||
192 | }); | ||
193 | } | ||
194 | |||
193 | // Emitted when the window is closed. | 195 | // Emitted when the window is closed. |
194 | mainWindow.on('close', (e) => { | 196 | mainWindow.on('close', (e) => { |
195 | // Dereference the window object, usually you would store windows | 197 | // Dereference the window object, usually you would store windows |
@@ -259,14 +261,26 @@ const createWindow = () => { | |||
259 | // initialization and is ready to create browser windows. | 261 | // initialization and is ready to create browser windows. |
260 | // Some APIs can only be used after this event occurs. | 262 | // Some APIs can only be used after this event occurs. |
261 | app.on('ready', () => { | 263 | app.on('ready', () => { |
264 | // Register App URL | ||
265 | app.setAsDefaultProtocolClient('franz'); | ||
266 | |||
267 | if (isDevMode) { | ||
268 | app.setAsDefaultProtocolClient('franz-dev'); | ||
269 | } | ||
270 | |||
262 | if (process.platform === 'win32') { | 271 | if (process.platform === 'win32') { |
263 | app.setUserTasks([{ | 272 | app.setUserTasks([{ |
264 | program: process.execPath, | 273 | program: process.execPath, |
265 | arguments: `${isDevMode ? `${__dirname} ` : ''}--reset-window`, | 274 | arguments: `${isDevMode ? `${__dirname} ` : ''}--reset-window`, |
266 | iconPath: path.join(`${__dirname}`, '../src/assets/images/taskbar/win32/display.ico'), | 275 | iconPath: asarPath(path.join(isDevMode ? `${__dirname}../src/` : __dirname, 'assets/images/taskbar/win32/display.ico')), |
267 | iconIndex: 0, | 276 | iconIndex: 0, |
268 | title: 'Move Franz to Current Display', | 277 | title: 'Move Franz to Current Display', |
269 | description: 'Restore the position and size of Franz', | 278 | description: 'Restore the position and size of Franz', |
279 | }, { | ||
280 | program: process.execPath, | ||
281 | arguments: `${isDevMode ? `${__dirname} ` : ''}--quit`, | ||
282 | iconIndex: 0, | ||
283 | title: 'Quit Franz', | ||
270 | }]); | 284 | }]); |
271 | } | 285 | } |
272 | 286 | ||
@@ -336,13 +350,13 @@ app.on('activate', () => { | |||
336 | }); | 350 | }); |
337 | 351 | ||
338 | app.on('will-finish-launching', () => { | 352 | app.on('will-finish-launching', () => { |
339 | // Protocol handler for osx | 353 | // Protocol handler for macOS |
340 | app.on('open-url', (event, url) => { | 354 | app.on('open-url', (event, url) => { |
341 | event.preventDefault(); | 355 | event.preventDefault(); |
342 | console.log(`open-url event: ${url}`); | 356 | |
343 | handleDeepLink(mainWindow, url); | 357 | onDidLoad((window) => { |
358 | debug('open-url event', url); | ||
359 | handleDeepLink(window, url); | ||
360 | }); | ||
344 | }); | 361 | }); |
345 | }); | 362 | }); |
346 | |||
347 | // Register App URL | ||
348 | app.setAsDefaultProtocolClient('franz'); | ||
diff --git a/src/models/Service.js b/src/models/Service.js index 3b8bebdef..8a2a8d3d8 100644 --- a/src/models/Service.js +++ b/src/models/Service.js | |||
@@ -15,7 +15,7 @@ export default class Service { | |||
15 | 15 | ||
16 | events = {}; | 16 | events = {}; |
17 | 17 | ||
18 | isAttached = false; | 18 | @observable isAttached = false; |
19 | 19 | ||
20 | @observable isActive = false; // Is current webview active | 20 | @observable isActive = false; // Is current webview active |
21 | 21 | ||
@@ -202,7 +202,7 @@ export default class Service { | |||
202 | 202 | ||
203 | this.webview.addEventListener('did-fail-load', (event) => { | 203 | this.webview.addEventListener('did-fail-load', (event) => { |
204 | debug('Service failed to load', this.name, event); | 204 | debug('Service failed to load', this.name, event); |
205 | if (event.isMainFrame && event.errorCode !== -27 && event.errorCode !== -3) { | 205 | if (event.isMainFrame && event.errorCode !== -21 && event.errorCode !== -3) { |
206 | this.isError = true; | 206 | this.isError = true; |
207 | this.errorMessage = event.errorDescription; | 207 | this.errorMessage = event.errorDescription; |
208 | this.isLoading = false; | 208 | this.isLoading = false; |
diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index dd4642d70..b21d48a11 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js | |||
@@ -143,10 +143,13 @@ export default class AppStore extends Store { | |||
143 | 143 | ||
144 | // Handle deep linking (franz://) | 144 | // Handle deep linking (franz://) |
145 | ipcRenderer.on('navigateFromDeepLink', (event, data) => { | 145 | ipcRenderer.on('navigateFromDeepLink', (event, data) => { |
146 | const { url } = data; | 146 | debug('Navigate from deep link', data); |
147 | let { url } = data; | ||
147 | if (!url) return; | 148 | if (!url) return; |
148 | 149 | ||
149 | this.stores.router.push(data.url); | 150 | url = url.replace(/\/$/, ''); |
151 | |||
152 | this.stores.router.push(url); | ||
150 | }); | 153 | }); |
151 | 154 | ||
152 | // Set active the next service | 155 | // Set active the next service |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 0ab57312a..efd57a09d 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -70,6 +70,7 @@ export default class ServicesStore extends Store { | |||
70 | this._mapActiveServiceToServiceModelReaction.bind(this), | 70 | this._mapActiveServiceToServiceModelReaction.bind(this), |
71 | this._saveActiveService.bind(this), | 71 | this._saveActiveService.bind(this), |
72 | this._logoutReaction.bind(this), | 72 | this._logoutReaction.bind(this), |
73 | this._handleMuteSettings.bind(this), | ||
73 | ]); | 74 | ]); |
74 | 75 | ||
75 | // Just bind this | 76 | // Just bind this |
@@ -627,6 +628,20 @@ export default class ServicesStore extends Store { | |||
627 | } | 628 | } |
628 | } | 629 | } |
629 | 630 | ||
631 | _handleMuteSettings() { | ||
632 | const { enabled } = this; | ||
633 | const { isAppMuted } = this.stores.settings.app; | ||
634 | |||
635 | enabled.forEach((service) => { | ||
636 | const { isAttached } = service; | ||
637 | const isMuted = isAppMuted || service.isMuted; | ||
638 | |||
639 | if (isAttached) { | ||
640 | service.webview.setAudioMuted(isMuted); | ||
641 | } | ||
642 | }); | ||
643 | } | ||
644 | |||
630 | _shareSettingsWithServiceProcess() { | 645 | _shareSettingsWithServiceProcess() { |
631 | const settings = this.stores.settings.app; | 646 | const settings = this.stores.settings.app; |
632 | this.actions.service.sendIPCMessageToAllServices({ | 647 | this.actions.service.sendIPCMessageToAllServices({ |
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 7addb5760..77d84afe1 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js | |||
@@ -129,10 +129,6 @@ export default class UserStore extends Store { | |||
129 | return Boolean(localStorage.getItem('authToken')); | 129 | return Boolean(localStorage.getItem('authToken')); |
130 | } | 130 | } |
131 | 131 | ||
132 | // @computed get isTokenValid() { | ||
133 | // return this.authToken !== null && moment(this.tokenExpiry).isAfter(moment()); | ||
134 | // } | ||
135 | |||
136 | @computed get isTokenExpired() { | 132 | @computed get isTokenExpired() { |
137 | if (!this.authToken) return false; | 133 | if (!this.authToken) return false; |
138 | 134 | ||
@@ -160,6 +156,14 @@ export default class UserStore extends Store { | |||
160 | gaEvent('User', 'login'); | 156 | gaEvent('User', 'login'); |
161 | } | 157 | } |
162 | 158 | ||
159 | @action _tokenLogin(authToken) { | ||
160 | this._setUserData(authToken); | ||
161 | |||
162 | this.stores.router.push('/'); | ||
163 | |||
164 | gaEvent('User', 'tokenLogin'); | ||
165 | } | ||
166 | |||
163 | @action async _signup({ | 167 | @action async _signup({ |
164 | firstname, lastname, email, password, accountType, company, | 168 | firstname, lastname, email, password, accountType, company, |
165 | }) { | 169 | }) { |
@@ -206,6 +210,8 @@ export default class UserStore extends Store { | |||
206 | } | 210 | } |
207 | 211 | ||
208 | @action async _update({ userData }) { | 212 | @action async _update({ userData }) { |
213 | if (!this.isLoggedIn) return; | ||
214 | |||
209 | const response = await this.updateUserInfoRequest.execute(userData)._promise; | 215 | const response = await this.updateUserInfoRequest.execute(userData)._promise; |
210 | 216 | ||
211 | this.getUserInfoRequest.patch(() => response.data); | 217 | this.getUserInfoRequest.patch(() => response.data); |
@@ -222,6 +228,7 @@ export default class UserStore extends Store { | |||
222 | // workaround mobx issue | 228 | // workaround mobx issue |
223 | localStorage.removeItem('authToken'); | 229 | localStorage.removeItem('authToken'); |
224 | window.localStorage.removeItem('authToken'); | 230 | window.localStorage.removeItem('authToken'); |
231 | |||
225 | this.getUserInfoRequest.invalidate().reset(); | 232 | this.getUserInfoRequest.invalidate().reset(); |
226 | this.authToken = null; | 233 | this.authToken = null; |
227 | } | 234 | } |
@@ -262,6 +269,18 @@ export default class UserStore extends Store { | |||
262 | const { router } = this.stores; | 269 | const { router } = this.stores; |
263 | const currentRoute = router.location.pathname; | 270 | const currentRoute = router.location.pathname; |
264 | if (!this.isLoggedIn | 271 | if (!this.isLoggedIn |
272 | && currentRoute.includes('token=')) { | ||
273 | router.push(this.WELCOME_ROUTE); | ||
274 | const token = currentRoute.split('=')[1]; | ||
275 | |||
276 | const data = this._parseToken(token); | ||
277 | if (data) { | ||
278 | // Give this some time to sink | ||
279 | setTimeout(() => { | ||
280 | this._tokenLogin(token); | ||
281 | }, 1000); | ||
282 | } | ||
283 | } else if (!this.isLoggedIn | ||
265 | && !currentRoute.includes(this.BASE_ROUTE)) { | 284 | && !currentRoute.includes(this.BASE_ROUTE)) { |
266 | router.push(this.WELCOME_ROUTE); | 285 | router.push(this.WELCOME_ROUTE); |
267 | } else if (this.isLoggedIn | 286 | } else if (this.isLoggedIn |
diff --git a/src/styles/layout.scss b/src/styles/layout.scss index ebf468cf0..8b7cc512a 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss | |||
@@ -19,7 +19,7 @@ html { overflow: hidden; } | |||
19 | 19 | ||
20 | &:hover, | 20 | &:hover, |
21 | &:active { color: $dark-theme-gray-smoke; } | 21 | &:active { color: $dark-theme-gray-smoke; } |
22 | &.is-muted { color: $dark-theme-gray; } | 22 | &.is-muted { color: $theme-brand-primary; } |
23 | } | 23 | } |
24 | } | 24 | } |
25 | 25 | ||
diff --git a/src/theme/dark/index.js b/src/theme/dark/index.js index 429284f9e..8fdb321f3 100644 --- a/src/theme/dark/index.js +++ b/src/theme/dark/index.js | |||
@@ -8,6 +8,9 @@ export const colorBackgroundSubscriptionContainer = legacyStyles.themeBrandInfo; | |||
8 | export const colorHeadline = legacyStyles.darkThemeTextColor; | 8 | export const colorHeadline = legacyStyles.darkThemeTextColor; |
9 | export const colorText = legacyStyles.darkThemeTextColor; | 9 | export const colorText = legacyStyles.darkThemeTextColor; |
10 | 10 | ||
11 | // Error Handler | ||
12 | export const colorWebviewErrorHandlerBackground = legacyStyles.darkThemeGrayDarkest; | ||
13 | |||
11 | // Loader | 14 | // Loader |
12 | export const colorFullscreenLoaderSpinner = '#FFF'; | 15 | export const colorFullscreenLoaderSpinner = '#FFF'; |
13 | export const colorWebviewLoaderBackground = hexToRgba(legacyStyles.darkThemeGrayDarkest, 0.5); | 16 | export const colorWebviewLoaderBackground = hexToRgba(legacyStyles.darkThemeGrayDarkest, 0.5); |
diff --git a/src/theme/default/index.js b/src/theme/default/index.js index 3ce8e7f0e..61410073d 100644 --- a/src/theme/default/index.js +++ b/src/theme/default/index.js | |||
@@ -23,6 +23,9 @@ export const colorSubscriptionContainerTitle = brandPrimary; | |||
23 | export const colorSubscriptionContainerActionButtonBackground = brandPrimary; | 23 | export const colorSubscriptionContainerActionButtonBackground = brandPrimary; |
24 | export const colorSubscriptionContainerActionButtonColor = '#FFF'; | 24 | export const colorSubscriptionContainerActionButtonColor = '#FFF'; |
25 | 25 | ||
26 | // Error Handler | ||
27 | export const colorWebviewErrorHandlerBackground = legacyStyles.themeGrayLighter; | ||
28 | |||
26 | // Loader | 29 | // Loader |
27 | export const colorAppLoaderSpinner = '#FFF'; | 30 | export const colorAppLoaderSpinner = '#FFF'; |
28 | export const colorFullscreenLoaderSpinner = legacyStyles.themeGrayDark; | 31 | export const colorFullscreenLoaderSpinner = legacyStyles.themeGrayDark; |