aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/services/content/ErrorHandlers/WebviewErrorHandler.js2
-rw-r--r--src/components/services/content/ErrorHandlers/styles.js6
-rw-r--r--src/components/services/content/ServiceWebview.js3
-rw-r--r--src/components/services/content/Services.js3
-rw-r--r--src/config.js3
-rw-r--r--src/containers/layout/AppLayoutContainer.js1
-rw-r--r--src/environment.js6
-rw-r--r--src/helpers/asar-helpers.js3
-rw-r--r--src/index.js142
-rw-r--r--src/models/Service.js4
-rw-r--r--src/stores/AppStore.js7
-rw-r--r--src/stores/ServicesStore.js15
-rw-r--r--src/stores/UserStore.js27
-rw-r--r--src/styles/layout.scss2
-rw-r--r--src/theme/dark/index.js3
-rw-r--r--src/theme/default/index.js3
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
34export default @injectSheet(styles) @observer class WebviewCrashHandler extends Component { 34export 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 @@
1export default { 1export 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 @@
1import electron from 'electron'; 1import electron from 'electron';
2import path from 'path'; 2import path from 'path';
3import { asarPath } from './helpers/asar-helpers';
3 4
4const app = process.type === 'renderer' ? electron.remote.app : electron.app; 5const app = process.type === 'renderer' ? electron.remote.app : electron.app;
5const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences; 6const systemPreferences = process.type === 'renderer' ? electron.remote.systemPreferences : electron.systemPreferences;
@@ -57,4 +58,4 @@ export const FILE_SYSTEM_SETTINGS_TYPES = [
57export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config'); 58export 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
60export const DICTIONARY_PATH = path.join(__dirname, 'dictionaries').replace('app.asar', 'app.asar.unpacked'); 61export 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 @@
1import isDev from 'electron-is-dev';
2
1import { LIVE_API, DEV_API, LOCAL_API } from './config'; 3import { LIVE_API, DEV_API, LOCAL_API } from './config';
2 4
3export const isDevMode = Boolean(process.execPath.match(/[\\/]electron/)); 5export const isDevMode = isDev;
4export const useLiveAPI = process.env.LIVE_API; 6export const useLiveAPI = process.env.LIVE_API;
5export const useLocalAPI = process.env.LOCAL_API; 7export const useLocalAPI = process.env.LOCAL_API;
6 8
7let platform = process.platform; 9let { platform } = process;
8if (process.env.OS_PLATFORM) { 10if (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 @@
1export 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 7import isDevMode from 'electron-is-dev';
8import fs from 'fs-extra'; 8import fs from 'fs-extra';
9import path from 'path'; 9import path from 'path';
10import windowStateKeeper from 'electron-window-state'; 10import windowStateKeeper from 'electron-window-state';
11 11
12// Set app directory before loading user modules
13if (isDevMode) {
14 app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev'));
15}
16
17/* eslint-disable import/first */
12import { 18import {
13 isDevMode,
14 isMac, 19 isMac,
15 isWindows, 20 isWindows,
16 isLinux, 21 isLinux,
17} from './environment'; 22} from './environment';
18
19import { mainIpcHandler as basicAuthHandler } from './features/basicAuth'; 23import { mainIpcHandler as basicAuthHandler } from './features/basicAuth';
20
21// DEV MODE: Save user data into FranzDev
22if (isDevMode) {
23 app.setPath('userData', path.join(app.getPath('appData'), 'FranzDev'));
24}
25/* eslint-disable import/first */
26import ipcApi from './electron/ipc-api'; 24import ipcApi from './electron/ipc-api';
27import Tray from './lib/Tray'; 25import Tray from './lib/Tray';
28import Settings from './electron/Settings'; 26import 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';
36import { asarPath } from './helpers/asar-helpers';
38/* eslint-enable import/first */ 37/* eslint-enable import/first */
39 38
40const debug = require('debug')('Franz:App'); 39const debug = require('debug')('Franz:App');
@@ -44,6 +43,17 @@ const debug = require('debug')('Franz:App');
44let mainWindow; 43let mainWindow;
45let willQuitApp = false; 44let willQuitApp = false;
46 45
46// Register methods to be called once the window has been loaded.
47let onDidLoadFns = [];
48
49function 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
48fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp')); 58fs.emptyDirSync(path.join(app.getPath('userData'), 'recipes', 'temp'));
49fs.ensureFileSync(path.join(app.getPath('userData'), 'window-state.json')); 59fs.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.
261app.on('ready', () => { 263app.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
338app.on('will-finish-launching', () => { 352app.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
348app.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;
8export const colorHeadline = legacyStyles.darkThemeTextColor; 8export const colorHeadline = legacyStyles.darkThemeTextColor;
9export const colorText = legacyStyles.darkThemeTextColor; 9export const colorText = legacyStyles.darkThemeTextColor;
10 10
11// Error Handler
12export const colorWebviewErrorHandlerBackground = legacyStyles.darkThemeGrayDarkest;
13
11// Loader 14// Loader
12export const colorFullscreenLoaderSpinner = '#FFF'; 15export const colorFullscreenLoaderSpinner = '#FFF';
13export const colorWebviewLoaderBackground = hexToRgba(legacyStyles.darkThemeGrayDarkest, 0.5); 16export 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;
23export const colorSubscriptionContainerActionButtonBackground = brandPrimary; 23export const colorSubscriptionContainerActionButtonBackground = brandPrimary;
24export const colorSubscriptionContainerActionButtonColor = '#FFF'; 24export const colorSubscriptionContainerActionButtonColor = '#FFF';
25 25
26// Error Handler
27export const colorWebviewErrorHandlerBackground = legacyStyles.themeGrayLighter;
28
26// Loader 29// Loader
27export const colorAppLoaderSpinner = '#FFF'; 30export const colorAppLoaderSpinner = '#FFF';
28export const colorFullscreenLoaderSpinner = legacyStyles.themeGrayDark; 31export const colorFullscreenLoaderSpinner = legacyStyles.themeGrayDark;