aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md7
-rw-r--r--package-lock.json72
-rw-r--r--package.json6
-rw-r--r--src/components/auth/AuthLayout.js6
-rw-r--r--src/components/layout/AppLayout.js126
-rw-r--r--src/containers/auth/AuthLayoutContainer.js10
-rw-r--r--src/containers/layout/AppLayoutContainer.js1
-rw-r--r--src/containers/settings/SettingsWindow.js35
-rw-r--r--src/features/announcements/components/AnnouncementScreen.js2
-rw-r--r--src/features/delayApp/index.js5
-rw-r--r--src/features/delayApp/styles.js1
-rw-r--r--src/index.html1
-rw-r--r--src/stores/UIStore.js30
-rw-r--r--src/styles/layout.scss2
-rw-r--r--src/styles/reset.scss2
-rw-r--r--src/webview/contextMenu.js5
-rw-r--r--src/webview/spellchecker.js17
17 files changed, 171 insertions, 157 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1fe2ab45..70b77637e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
1# [5.2.0-beta.3](https://github.com/meetfranz/franz/compare/v5.2.0-beta.2...v5.2.0-beta.3) (2019-06-24)
2
3### General
4
5* **App:** Downgraded electron to 4.2.4 ([404c87a](https://github.com/meetfranz/franz/commit/404c87a))
6
7
1# [5.2.0-beta.2](https://github.com/meetfranz/franz/compare/v5.2.0-beta.1...v5.2.0-beta.2) (2019-06-12) 8# [5.2.0-beta.2](https://github.com/meetfranz/franz/compare/v5.2.0-beta.1...v5.2.0-beta.2) (2019-06-12)
2 9
3 10
diff --git a/package-lock.json b/package-lock.json
index 77575ad56..b4d86c5e1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "franz", 2 "name": "franz",
3 "version": "5.2.0-beta.1", 3 "version": "5.2.0-beta.3",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
@@ -2173,13 +2173,13 @@
2173 "requires": { 2173 "requires": {
2174 "@mdi/js": "^3.3.92", 2174 "@mdi/js": "^3.3.92",
2175 "@mdi/react": "^1.1.0", 2175 "@mdi/react": "^1.1.0",
2176 "@meetfranz/theme": "^1.0.13", 2176 "@meetfranz/theme": "^1.0.14",
2177 "react-html-attributes": "^1.4.3", 2177 "react-html-attributes": "^1.4.3",
2178 "react-loader": "^2.4.5" 2178 "react-loader": "^2.4.5"
2179 }, 2179 },
2180 "dependencies": { 2180 "dependencies": {
2181 "@meetfranz/theme": { 2181 "@meetfranz/theme": {
2182 "version": "1.0.13", 2182 "version": "1.0.14",
2183 "bundled": true, 2183 "bundled": true,
2184 "requires": { 2184 "requires": {
2185 "color": "^3.1.0" 2185 "color": "^3.1.0"
@@ -2198,12 +2198,12 @@
2198 "requires": { 2198 "requires": {
2199 "@mdi/js": "^3.3.92", 2199 "@mdi/js": "^3.3.92",
2200 "@mdi/react": "^1.1.0", 2200 "@mdi/react": "^1.1.0",
2201 "@meetfranz/theme": "^1.0.13", 2201 "@meetfranz/theme": "^1.0.14",
2202 "react-loader": "^2.4.5" 2202 "react-loader": "^2.4.5"
2203 }, 2203 },
2204 "dependencies": { 2204 "dependencies": {
2205 "@meetfranz/theme": { 2205 "@meetfranz/theme": {
2206 "version": "1.0.13", 2206 "version": "1.0.14",
2207 "bundled": true, 2207 "bundled": true,
2208 "requires": { 2208 "requires": {
2209 "color": "^3.1.0" 2209 "color": "^3.1.0"
@@ -6803,9 +6803,9 @@
6803 "dev": true 6803 "dev": true
6804 }, 6804 },
6805 "electron": { 6805 "electron": {
6806 "version": "5.0.2", 6806 "version": "4.2.4",
6807 "resolved": "https://registry.npmjs.org/electron/-/electron-5.0.2.tgz", 6807 "resolved": "https://registry.npmjs.org/electron/-/electron-4.2.4.tgz",
6808 "integrity": "sha512-bUHKQhyuOen/q8iHTkrnzqB9CAwBDI+vHbeu21kpq2bqAD+t25yfrmUEcYHaPL4fZOAhk6nnRqskF6/Xd+aZxg==", 6808 "integrity": "sha512-d4wEwJluMsRyRgbukLmFVTb6l1J+mc3RLB1ctbpMlSWDFvs+zknPWa+cHBzTWwrdgwINLddr69qsAW1ku6FqYw==",
6809 "dev": true, 6809 "dev": true,
6810 "requires": { 6810 "requires": {
6811 "@types/node": "^10.12.18", 6811 "@types/node": "^10.12.18",
@@ -6814,9 +6814,9 @@
6814 }, 6814 },
6815 "dependencies": { 6815 "dependencies": {
6816 "@types/node": { 6816 "@types/node": {
6817 "version": "10.14.4", 6817 "version": "10.14.9",
6818 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.4.tgz", 6818 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.9.tgz",
6819 "integrity": "sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg==", 6819 "integrity": "sha512-NelG/dSahlXYtSoVPErrp06tYFrvzj8XLWmKA+X8x0W//4MqbUyZu++giUG/v0bjAT6/Qxa8IjodrfdACyb0Fg==",
6820 "dev": true 6820 "dev": true
6821 } 6821 }
6822 } 6822 }
@@ -7043,12 +7043,14 @@
7043 } 7043 }
7044 }, 7044 },
7045 "electron-hunspell": { 7045 "electron-hunspell": {
7046 "version": "1.0.0-beta.7", 7046 "version": "0.1.1",
7047 "resolved": "https://registry.npmjs.org/electron-hunspell/-/electron-hunspell-1.0.0-beta.7.tgz", 7047 "resolved": "https://registry.npmjs.org/electron-hunspell/-/electron-hunspell-0.1.1.tgz",
7048 "integrity": "sha512-BByCXqU8sZbuzyoxKcBYjycp8ORiqjeYZd2OT8RNjVW+XGPmZkHewXUu4tUa1IXW6ij6IqojV5kr+xhYKLN1DA==", 7048 "integrity": "sha512-B3nOQqHexIX+8bz72FZkNk+iFBrdqS9DpV2SaH+t7T9SLbONBVBRLJ2Jj2ytXFUzvw81q7vz2dfxPCddh/E3ww==",
7049 "requires": { 7049 "requires": {
7050 "hunspell-asm": "^2.0.0", 7050 "hunspell-asm": "1.0.2",
7051 "tslib": "1.9.3" 7051 "lodash": "^4.17.11",
7052 "tslib": "1.9.3",
7053 "unixify": "1.0.0"
7052 } 7054 }
7053 }, 7055 },
7054 "electron-is-dev": { 7056 "electron-is-dev": {
@@ -11379,34 +11381,14 @@
11379 } 11381 }
11380 }, 11382 },
11381 "hunspell-asm": { 11383 "hunspell-asm": {
11382 "version": "2.0.0", 11384 "version": "1.0.2",
11383 "resolved": "https://registry.npmjs.org/hunspell-asm/-/hunspell-asm-2.0.0.tgz", 11385 "resolved": "https://registry.npmjs.org/hunspell-asm/-/hunspell-asm-1.0.2.tgz",
11384 "integrity": "sha512-FMIUBpy+bRREFAvC63RcYEK9U6+FdlEojGSVsvMTpuZ2CekYyUBwEfG4+ExIQOQyEN0U6f1MoVgrFqvgPNSA2g==", 11386 "integrity": "sha512-UTLBvc0yZiIcHl9qrgxnFTZbX3zF4CprzEY+u+N0iXlUKZnUJRIgvgppTdgiQTsucm5b0aN/rHsgXz2q/0kBRA==",
11385 "requires": { 11387 "requires": {
11386 "emscripten-wasm-loader": "^2.2.3", 11388 "emscripten-wasm-loader": "^1.0.0",
11387 "nanoid": "^2.0.1", 11389 "nanoid": "^1.0.2",
11388 "tslib": "^1.9.3", 11390 "tslib": "^1.9.0",
11389 "unixify": "^1.0.0" 11391 "unixify": "^1.0.0"
11390 },
11391 "dependencies": {
11392 "emscripten-wasm-loader": {
11393 "version": "2.2.3",
11394 "resolved": "https://registry.npmjs.org/emscripten-wasm-loader/-/emscripten-wasm-loader-2.2.3.tgz",
11395 "integrity": "sha512-//gI0afvtVnY7smttrPOW/BM+pTJLmdIcXAQV3fgRdQ0o6wm2vdSI0kjLYVOeo/rbtRsGgVuMLu6fT+O//EfaA==",
11396 "requires": {
11397 "getroot": "^1.0.0",
11398 "nanoid": "^1.3.4",
11399 "tslib": "^1.9.3",
11400 "unixify": "^1.0.0"
11401 },
11402 "dependencies": {
11403 "nanoid": {
11404 "version": "1.3.4",
11405 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.3.4.tgz",
11406 "integrity": "sha512-4ug4BsuHxiVHoRUe1ud6rUFT3WUMmjXt1W0quL0CviZQANdan7D8kqN5/maw53hmAApY/jfzMRkC57BNNs60ZQ=="
11407 }
11408 }
11409 }
11410 } 11392 }
11411 }, 11393 },
11412 "husky": { 11394 "husky": {
@@ -14385,9 +14367,9 @@
14385 "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==" 14367 "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="
14386 }, 14368 },
14387 "nanoid": { 14369 "nanoid": {
14388 "version": "2.0.3", 14370 "version": "1.3.4",
14389 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.0.3.tgz", 14371 "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-1.3.4.tgz",
14390 "integrity": "sha512-NbaoqdhIYmY6FXDRB4eYtDVC9Z9eCbn8TyaiC16LNKtpPv/aqa0tOPD8y6gNE4yUNnaZ7LLhYtXOev/6+cBtfw==" 14372 "integrity": "sha512-4ug4BsuHxiVHoRUe1ud6rUFT3WUMmjXt1W0quL0CviZQANdan7D8kqN5/maw53hmAApY/jfzMRkC57BNNs60ZQ=="
14391 }, 14373 },
14392 "nanomatch": { 14374 "nanomatch": {
14393 "version": "1.2.13", 14375 "version": "1.2.13",
diff --git a/package.json b/package.json
index 9060c32db..7bf1f8a4a 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
2 "name": "franz", 2 "name": "franz",
3 "productName": "Franz", 3 "productName": "Franz",
4 "appId": "com.meetfranz.franz", 4 "appId": "com.meetfranz.franz",
5 "version": "5.2.0-beta.2", 5 "version": "5.2.0-beta.4",
6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.", 6 "description": "Messaging app for WhatsApp, Slack, Telegram, HipChat, Hangouts and many many more.",
7 "copyright": "adlk x franz - Stefan Malzner", 7 "copyright": "adlk x franz - Stefan Malzner",
8 "main": "index.js", 8 "main": "index.js",
@@ -47,7 +47,7 @@
47 "du": "^0.1.0", 47 "du": "^0.1.0",
48 "electron-dl": "1.12.0", 48 "electron-dl": "1.12.0",
49 "electron-fetch": "1.3.0", 49 "electron-fetch": "1.3.0",
50 "electron-hunspell": "1.0.0-beta.7", 50 "electron-hunspell": "0.1.1",
51 "electron-is-dev": "1.0.1", 51 "electron-is-dev": "1.0.1",
52 "electron-react-titlebar": "0.8.1", 52 "electron-react-titlebar": "0.8.1",
53 "electron-updater": "4.0.6", 53 "electron-updater": "4.0.6",
@@ -118,7 +118,7 @@
118 "cross-env": "^5.0.5", 118 "cross-env": "^5.0.5",
119 "cz-conventional-changelog": "2.1.0", 119 "cz-conventional-changelog": "2.1.0",
120 "dotenv": "^4.0.0", 120 "dotenv": "^4.0.0",
121 "electron": "5.0.2", 121 "electron": "4.2.4",
122 "electron-builder": "20.40.2", 122 "electron-builder": "20.40.2",
123 "electron-rebuild": "1.8.4", 123 "electron-rebuild": "1.8.4",
124 "eslint": "5.10.0", 124 "eslint": "5.10.0",
diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js
index 3d43d4e5c..75a8cfc61 100644
--- a/src/components/auth/AuthLayout.js
+++ b/src/components/auth/AuthLayout.js
@@ -22,7 +22,6 @@ export default @observer class AuthLayout extends Component {
22 retryHealthCheck: PropTypes.func.isRequired, 22 retryHealthCheck: PropTypes.func.isRequired,
23 isHealthCheckLoading: PropTypes.bool.isRequired, 23 isHealthCheckLoading: PropTypes.bool.isRequired,
24 isFullScreen: PropTypes.bool.isRequired, 24 isFullScreen: PropTypes.bool.isRequired,
25 darkMode: PropTypes.bool.isRequired,
26 nextAppReleaseVersion: PropTypes.string, 25 nextAppReleaseVersion: PropTypes.string,
27 installAppUpdate: PropTypes.func.isRequired, 26 installAppUpdate: PropTypes.func.isRequired,
28 appUpdateIsDownloaded: PropTypes.bool.isRequired, 27 appUpdateIsDownloaded: PropTypes.bool.isRequired,
@@ -45,7 +44,6 @@ export default @observer class AuthLayout extends Component {
45 retryHealthCheck, 44 retryHealthCheck,
46 isHealthCheckLoading, 45 isHealthCheckLoading,
47 isFullScreen, 46 isFullScreen,
48 darkMode,
49 nextAppReleaseVersion, 47 nextAppReleaseVersion,
50 installAppUpdate, 48 installAppUpdate,
51 appUpdateIsDownloaded, 49 appUpdateIsDownloaded,
@@ -53,7 +51,7 @@ export default @observer class AuthLayout extends Component {
53 const { intl } = this.context; 51 const { intl } = this.context;
54 52
55 return ( 53 return (
56 <div className={darkMode ? 'theme__dark' : ''}> 54 <>
57 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />} 55 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />}
58 <div className="auth"> 56 <div className="auth">
59 {!isOnline && ( 57 {!isOnline && (
@@ -93,7 +91,7 @@ export default @observer class AuthLayout extends Component {
93 <img src="./assets/images/adlk.svg" alt="" /> 91 <img src="./assets/images/adlk.svg" alt="" />
94 </Link> 92 </Link>
95 </div> 93 </div>
96 </div> 94 </>
97 ); 95 );
98 } 96 }
99} 97}
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index 499bc097a..ebb9849ea 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -68,7 +68,6 @@ class AppLayout extends Component {
68 areRequiredRequestsSuccessful: PropTypes.bool.isRequired, 68 areRequiredRequestsSuccessful: PropTypes.bool.isRequired,
69 retryRequiredRequests: PropTypes.func.isRequired, 69 retryRequiredRequests: PropTypes.func.isRequired,
70 areRequiredRequestsLoading: PropTypes.bool.isRequired, 70 areRequiredRequestsLoading: PropTypes.bool.isRequired,
71 darkMode: PropTypes.bool.isRequired,
72 isDelayAppScreenVisible: PropTypes.bool.isRequired, 71 isDelayAppScreenVisible: PropTypes.bool.isRequired,
73 }; 72 };
74 73
@@ -101,7 +100,6 @@ class AppLayout extends Component {
101 areRequiredRequestsSuccessful, 100 areRequiredRequestsSuccessful,
102 retryRequiredRequests, 101 retryRequiredRequests,
103 areRequiredRequestsLoading, 102 areRequiredRequestsLoading,
104 darkMode,
105 isDelayAppScreenVisible, 103 isDelayAppScreenVisible,
106 } = this.props; 104 } = this.props;
107 105
@@ -109,69 +107,67 @@ class AppLayout extends Component {
109 107
110 return ( 108 return (
111 <ErrorBoundary> 109 <ErrorBoundary>
112 <div className={(darkMode ? 'theme__dark' : '')}> 110 <div className="app">
113 <div className="app"> 111 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />}
114 {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />} 112 <div className={`app__content ${classes.appContent}`}>
115 <div className={`app__content ${classes.appContent}`}> 113 {workspacesDrawer}
116 {workspacesDrawer} 114 {sidebar}
117 {sidebar} 115 <div className="app__service">
118 <div className="app__service"> 116 <WorkspaceSwitchingIndicator />
119 <WorkspaceSwitchingIndicator /> 117 {news.length > 0 && news.map(item => (
120 {news.length > 0 && news.map(item => ( 118 <InfoBar
121 <InfoBar 119 key={item.id}
122 key={item.id} 120 position="top"
123 position="top" 121 type={item.type}
124 type={item.type} 122 sticky={item.sticky}
125 sticky={item.sticky} 123 onHide={() => removeNewsItem({ newsId: item.id })}
126 onHide={() => removeNewsItem({ newsId: item.id })} 124 >
127 > 125 <span dangerouslySetInnerHTML={createMarkup(item.message)} />
128 <span dangerouslySetInnerHTML={createMarkup(item.message)} /> 126 </InfoBar>
129 </InfoBar> 127 ))}
130 ))} 128 {/* {!isOnline && (
131 {/* {!isOnline && ( 129 <InfoBar
132 <InfoBar 130 type="danger"
133 type="danger" 131 sticky
134 sticky 132 >
135 > 133 <span className="mdi mdi-flash" />
136 <span className="mdi mdi-flash" /> 134 {intl.formatMessage(globalMessages.notConnectedToTheInternet)}
137 {intl.formatMessage(globalMessages.notConnectedToTheInternet)} 135 </InfoBar>
138 </InfoBar> 136 )} */}
139 )} */} 137 {!areRequiredRequestsSuccessful && showRequiredRequestsError && (
140 {!areRequiredRequestsSuccessful && showRequiredRequestsError && ( 138 <InfoBar
141 <InfoBar 139 type="danger"
142 type="danger" 140 ctaLabel="Try again"
143 ctaLabel="Try again" 141 ctaLoading={areRequiredRequestsLoading}
144 ctaLoading={areRequiredRequestsLoading} 142 sticky
145 sticky 143 onClick={retryRequiredRequests}
146 onClick={retryRequiredRequests} 144 >
147 > 145 <span className="mdi mdi-flash" />
148 <span className="mdi mdi-flash" /> 146 {intl.formatMessage(messages.requiredRequestsFailed)}
149 {intl.formatMessage(messages.requiredRequestsFailed)} 147 </InfoBar>
150 </InfoBar> 148 )}
151 )} 149 {showServicesUpdatedInfoBar && (
152 {showServicesUpdatedInfoBar && ( 150 <InfoBar
153 <InfoBar 151 type="primary"
154 type="primary" 152 ctaLabel={intl.formatMessage(messages.buttonReloadServices)}
155 ctaLabel={intl.formatMessage(messages.buttonReloadServices)} 153 onClick={reloadServicesAfterUpdate}
156 onClick={reloadServicesAfterUpdate} 154 sticky
157 sticky 155 >
158 > 156 <span className="mdi mdi-power-plug" />
159 <span className="mdi mdi-power-plug" /> 157 {intl.formatMessage(messages.servicesUpdated)}
160 {intl.formatMessage(messages.servicesUpdated)} 158 </InfoBar>
161 </InfoBar> 159 )}
162 )} 160 {appUpdateIsDownloaded && (
163 {appUpdateIsDownloaded && ( 161 <AppUpdateInfoBar
164 <AppUpdateInfoBar 162 nextAppReleaseVersion={nextAppReleaseVersion}
165 nextAppReleaseVersion={nextAppReleaseVersion} 163 onInstallUpdate={installAppUpdate}
166 onInstallUpdate={installAppUpdate} 164 />
167 /> 165 )}
168 )} 166 {isDelayAppScreenVisible && (<DelayApp />)}
169 {isDelayAppScreenVisible && (<DelayApp />)} 167 <BasicAuth />
170 <BasicAuth /> 168 <ShareFranz />
171 <ShareFranz /> 169 {services}
172 {services} 170 {children}
173 {children}
174 </div>
175 </div> 171 </div>
176 </div> 172 </div>
177 </div> 173 </div>
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js
index 1f9c1ea61..427054d3d 100644
--- a/src/containers/auth/AuthLayoutContainer.js
+++ b/src/containers/auth/AuthLayoutContainer.js
@@ -2,7 +2,6 @@ import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { inject, observer } from 'mobx-react'; 3import { inject, observer } from 'mobx-react';
4import { ThemeProvider } from 'react-jss'; 4import { ThemeProvider } from 'react-jss';
5import { theme } from '@meetfranz/theme';
6 5
7import AuthLayout from '../../components/auth/AuthLayout'; 6import AuthLayout from '../../components/auth/AuthLayout';
8import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
@@ -24,24 +23,22 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
24 stores, actions, children, location, 23 stores, actions, children, location,
25 } = this.props; 24 } = this.props;
26 const { 25 const {
27 app, features, globalError, settings, 26 app, features, globalError,
28 } = stores; 27 } = stores;
29 28
30 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting 29 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting
31 && !features.defaultFeaturesRequest.wasExecuted; 30 && !features.defaultFeaturesRequest.wasExecuted;
32 31
33 const themeType = theme(settings.app.darkMode ? 'dark' : 'default');
34
35 if (isLoadingBaseFeatures) { 32 if (isLoadingBaseFeatures) {
36 return ( 33 return (
37 <ThemeProvider theme={theme(themeType)}> 34 <ThemeProvider theme={stores.ui.theme}>
38 <AppLoader /> 35 <AppLoader />
39 </ThemeProvider> 36 </ThemeProvider>
40 ); 37 );
41 } 38 }
42 39
43 return ( 40 return (
44 <ThemeProvider theme={theme(themeType)}> 41 <ThemeProvider theme={stores.ui.theme}>
45 <AuthLayout 42 <AuthLayout
46 error={globalError.response} 43 error={globalError.response}
47 pathname={location.pathname} 44 pathname={location.pathname}
@@ -50,7 +47,6 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
50 retryHealthCheck={actions.app.healthCheck} 47 retryHealthCheck={actions.app.healthCheck}
51 isHealthCheckLoading={app.healthCheckRequest.isExecuting} 48 isHealthCheckLoading={app.healthCheckRequest.isExecuting}
52 isFullScreen={app.isFullScreen} 49 isFullScreen={app.isFullScreen}
53 darkMode={app.isSystemDarkModeEnabled}
54 installAppUpdate={actions.app.installUpdate} 50 installAppUpdate={actions.app.installUpdate}
55 nextAppReleaseVersion={app.nextAppReleaseVersion} 51 nextAppReleaseVersion={app.nextAppReleaseVersion}
56 appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED} 52 appUpdateIsDownloaded={app.updateStatus === app.updateStatusTypes.DOWNLOADED}
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js
index d290a6094..cf3da71e8 100644
--- a/src/containers/layout/AppLayoutContainer.js
+++ b/src/containers/layout/AppLayoutContainer.js
@@ -148,7 +148,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e
148 areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful} 148 areRequiredRequestsSuccessful={requests.areRequiredRequestsSuccessful}
149 retryRequiredRequests={retryRequiredRequests} 149 retryRequiredRequests={retryRequiredRequests}
150 areRequiredRequestsLoading={requests.areRequiredRequestsLoading} 150 areRequiredRequestsLoading={requests.areRequiredRequestsLoading}
151 darkMode={settings.all.app.darkMode}
152 isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} 151 isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible}
153 > 152 >
154 {React.Children.count(children) > 0 ? children : null} 153 {React.Children.count(children) > 0 ? children : null}
diff --git a/src/containers/settings/SettingsWindow.js b/src/containers/settings/SettingsWindow.js
index 663b9e2e4..440d32a46 100644
--- a/src/containers/settings/SettingsWindow.js
+++ b/src/containers/settings/SettingsWindow.js
@@ -1,4 +1,5 @@
1import React, { Component } from 'react'; 1import React, { Component } from 'react';
2import ReactDOM from 'react-dom';
2import PropTypes from 'prop-types'; 3import PropTypes from 'prop-types';
3import { observer, inject } from 'mobx-react'; 4import { observer, inject } from 'mobx-react';
4 5
@@ -10,10 +11,23 @@ import ErrorBoundary from '../../components/util/ErrorBoundary';
10import { workspaceStore } from '../../features/workspaces'; 11import { workspaceStore } from '../../features/workspaces';
11 12
12export default @inject('stores', 'actions') @observer class SettingsContainer extends Component { 13export default @inject('stores', 'actions') @observer class SettingsContainer extends Component {
14 portalRoot = document.querySelector('#portalContainer');
15
16 el = document.createElement('div');
17
18 componentDidMount() {
19 this.portalRoot.appendChild(this.el);
20 }
21
22 componentWillUnmount() {
23 this.portalRoot.removeChild(this.el);
24 }
25
13 render() { 26 render() {
14 const { children, stores } = this.props; 27 const { children, stores } = this.props;
15 const { closeSettings } = this.props.actions.ui; 28 const { closeSettings } = this.props.actions.ui;
16 29
30
17 const navigation = ( 31 const navigation = (
18 <Navigation 32 <Navigation
19 serviceCount={stores.services.all.length} 33 serviceCount={stores.services.all.length}
@@ -21,15 +35,18 @@ export default @inject('stores', 'actions') @observer class SettingsContainer ex
21 /> 35 />
22 ); 36 );
23 37
24 return ( 38 return ReactDOM.createPortal(
25 <ErrorBoundary> 39 (
26 <Layout 40 <ErrorBoundary>
27 navigation={navigation} 41 <Layout
28 closeSettings={closeSettings} 42 navigation={navigation}
29 > 43 closeSettings={closeSettings}
30 {children} 44 >
31 </Layout> 45 {children}
32 </ErrorBoundary> 46 </Layout>
47 </ErrorBoundary>
48 ),
49 this.el,
33 ); 50 );
34 } 51 }
35} 52}
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js
index e7c5fe395..03bd5ba41 100644
--- a/src/features/announcements/components/AnnouncementScreen.js
+++ b/src/features/announcements/components/AnnouncementScreen.js
@@ -28,7 +28,7 @@ const smallScreen = '1000px';
28const styles = theme => ({ 28const styles = theme => ({
29 container: { 29 container: {
30 background: theme.colorBackground, 30 background: theme.colorBackground,
31 position: 'absolute', 31 position: 'relative',
32 top: 0, 32 top: 0,
33 zIndex: 140, 33 zIndex: 140,
34 width: '100%', 34 width: '100%',
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js
index 67f0fc5e6..39fae3b20 100644
--- a/src/features/delayApp/index.js
+++ b/src/features/delayApp/index.js
@@ -33,7 +33,7 @@ export default function init(stores) {
33 }; 33 };
34 34
35 reaction( 35 reaction(
36 () => stores.user.isLoggedIn && stores.features.features.needToWaitToProceed && !stores.user.data.isPremium, 36 () => stores.user.isLoggedIn && stores.services.allServicesRequest.wasExecuted && stores.features.features.needToWaitToProceed && !stores.user.data.isPremium,
37 (isEnabled) => { 37 (isEnabled) => {
38 if (isEnabled) { 38 if (isEnabled) {
39 debug('Enabling `delayApp` feature'); 39 debug('Enabling `delayApp` feature');
@@ -45,6 +45,7 @@ export default function init(stores) {
45 45
46 autorun(() => { 46 autorun(() => {
47 if (stores.services.all.length === 0) { 47 if (stores.services.all.length === 0) {
48 debug('seas', stores.services.all.length);
48 shownAfterLaunch = true; 49 shownAfterLaunch = true;
49 return; 50 return;
50 } 51 }
@@ -64,7 +65,7 @@ export default function init(stores) {
64 debug('Resetting app delay'); 65 debug('Resetting app delay');
65 66
66 setVisibility(false); 67 setVisibility(false);
67 }, DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait + 1000); // timer needs to be able to hit 0 68 }, config.delayDuration + 1000); // timer needs to be able to hit 0
68 } 69 }
69 }); 70 });
70 } else { 71 } else {
diff --git a/src/features/delayApp/styles.js b/src/features/delayApp/styles.js
index 5c214cfdf..69c3c7a27 100644
--- a/src/features/delayApp/styles.js
+++ b/src/features/delayApp/styles.js
@@ -1,7 +1,6 @@
1export default theme => ({ 1export default theme => ({
2 container: { 2 container: {
3 background: theme.colorBackground, 3 background: theme.colorBackground,
4 position: 'absolute',
5 top: 0, 4 top: 0,
6 width: '100%', 5 width: '100%',
7 display: 'flex', 6 display: 'flex',
diff --git a/src/index.html b/src/index.html
index bf15e2d4e..f29aa2686 100644
--- a/src/index.html
+++ b/src/index.html
@@ -10,6 +10,7 @@
10 <div class="window-draggable"></div> 10 <div class="window-draggable"></div>
11 <div class="dev-warning">DEV MODE</div> 11 <div class="dev-warning">DEV MODE</div>
12 <div id="root"></div> 12 <div id="root"></div>
13 <div id="portalContainer"></div>
13 <script> 14 <script>
14 document.querySelector('body').classList.add(process.env.OS_PLATFORM ? process.env.OS_PLATFORM : process.platform); 15 document.querySelector('body').classList.add(process.env.OS_PLATFORM ? process.env.OS_PLATFORM : process.platform);
15 16
diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js
index a95a8e1e0..9680c5bcc 100644
--- a/src/stores/UIStore.js
+++ b/src/stores/UIStore.js
@@ -1,4 +1,9 @@
1import { action, observable, computed } from 'mobx'; 1import {
2 action,
3 observable,
4 computed,
5 reaction,
6} from 'mobx';
2import { theme } from '@meetfranz/theme'; 7import { theme } from '@meetfranz/theme';
3 8
4import Store from './lib/Store'; 9import Store from './lib/Store';
@@ -15,10 +20,18 @@ export default class UIStore extends Store {
15 this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this)); 20 this.actions.ui.toggleServiceUpdatedInfoBar.listen(this._toggleServiceUpdatedInfoBar.bind(this));
16 } 21 }
17 22
23 setup() {
24 reaction(
25 () => this.isDarkThemeActive,
26 () => this._setupThemeInDOM(),
27 { fireImmediately: true },
28 );
29 }
30
18 @computed get showMessageBadgesEvenWhenMuted() { 31 @computed get showMessageBadgesEvenWhenMuted() {
19 const settings = this.stores.settings.all; 32 const settings = this.stores.settings.all;
20 33
21 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.isAppMuted; 34 return (settings.app.isAppMuted && settings.app.showMessageBadgeWhenMuted) || !settings.app.isAppMuted;
22 } 35 }
23 36
24 @computed get isDarkThemeActive() { 37 @computed get isDarkThemeActive() {
@@ -26,7 +39,7 @@ export default class UIStore extends Store {
26 } 39 }
27 40
28 @computed get theme() { 41 @computed get theme() {
29 if (this.isDarkThemeActive) return theme('dark'); 42 if (this.isDarkThemeActive || this.stores.settings.app.darkMode) return theme('dark');
30 return theme('default'); 43 return theme('default');
31 } 44 }
32 45
@@ -47,4 +60,15 @@ export default class UIStore extends Store {
47 } 60 }
48 this.showServicesUpdatedInfoBar = visibility; 61 this.showServicesUpdatedInfoBar = visibility;
49 } 62 }
63
64 // Reactions
65 _setupThemeInDOM() {
66 const body = document.querySelector('body');
67
68 if (!this.isDarkThemeActive) {
69 body.classList.remove('theme__dark');
70 } else {
71 body.classList.add('theme__dark');
72 }
73 }
50} 74}
diff --git a/src/styles/layout.scss b/src/styles/layout.scss
index e858b7904..9f226b61c 100644
--- a/src/styles/layout.scss
+++ b/src/styles/layout.scss
@@ -39,7 +39,7 @@ html { overflow: hidden; }
39 .app__content { display: flex; } 39 .app__content { display: flex; }
40 40
41 .app__service { 41 .app__service {
42 position: relative; 42 // position: relative;
43 display: flex; 43 display: flex;
44 flex: 1; 44 flex: 1;
45 flex-direction: column; 45 flex-direction: column;
diff --git a/src/styles/reset.scss b/src/styles/reset.scss
index 80328dcef..f46ede4a2 100644
--- a/src/styles/reset.scss
+++ b/src/styles/reset.scss
@@ -64,7 +64,7 @@ body {
64 font-size: 1.4rem; 64 font-size: 1.4rem;
65 line-height: 1; 65 line-height: 1;
66 66
67 .theme__dark { color: $dark-theme-gray-smoke; } 67 &.theme__dark { color: $dark-theme-gray-smoke; }
68} 68}
69 69
70* { 70* {
diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js
index 967e8e667..a4a6ab899 100644
--- a/src/webview/contextMenu.js
+++ b/src/webview/contextMenu.js
@@ -280,13 +280,12 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
280}; 280};
281 281
282export default function contextMenu(spellcheckProvider, isSpellcheckEnabled, getDefaultSpellcheckerLanguage, getSpellcheckerLanguage) { 282export default function contextMenu(spellcheckProvider, isSpellcheckEnabled, getDefaultSpellcheckerLanguage, getSpellcheckerLanguage) {
283 webContents.on('context-menu', async (e, props) => { 283 webContents.on('context-menu', (e, props) => {
284 e.preventDefault(); 284 e.preventDefault();
285 285
286 let suggestions = []; 286 let suggestions = [];
287 if (spellcheckProvider && props.misspelledWord) { 287 if (spellcheckProvider && props.misspelledWord) {
288 debug('Mispelled word', props.misspelledWord); 288 suggestions = spellcheckProvider.getSuggestion(props.misspelledWord);
289 suggestions = await spellcheckProvider.getSuggestion(props.misspelledWord);
290 289
291 debug('Suggestions', suggestions); 290 debug('Suggestions', suggestions);
292 } 291 }
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index 417d1ea1a..9158b3b94 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -1,8 +1,6 @@
1import { webFrame } from 'electron'; 1import { webFrame } from 'electron';
2import { attachSpellCheckProvider, SpellCheckerProvider } from 'electron-hunspell'; 2import { SpellCheckerProvider } from 'electron-hunspell';
3import { ENVIRONMENT } from 'hunspell-asm';
4import path from 'path'; 3import path from 'path';
5import { readFileSync } from 'fs';
6 4
7import { DICTIONARY_PATH } from '../config'; 5import { DICTIONARY_PATH } from '../config';
8import { SPELLCHECKER_LOCALES } from '../i18n/languages'; 6import { SPELLCHECKER_LOCALES } from '../i18n/languages';
@@ -12,12 +10,11 @@ const debug = require('debug')('Franz:spellchecker');
12let provider; 10let provider;
13let currentDict; 11let currentDict;
14let _isEnabled = false; 12let _isEnabled = false;
15let attached;
16 13
17async function loadDictionary(locale) { 14async function loadDictionary(locale) {
18 try { 15 try {
19 const fileLocation = path.join(DICTIONARY_PATH, `hunspell-dict-${locale}/${locale}`); 16 const fileLocation = path.join(DICTIONARY_PATH, `hunspell-dict-${locale}/${locale}`);
20 await provider.loadDictionary(locale, readFileSync(`${fileLocation}.dic`), readFileSync(`${fileLocation}.aff`)); 17 await provider.loadDictionary(locale, `${fileLocation}.dic`, `${fileLocation}.aff`);
21 debug('Loaded dictionary', locale, 'from', fileLocation); 18 debug('Loaded dictionary', locale, 'from', fileLocation);
22 } catch (err) { 19 } catch (err) {
23 console.error('Could not load dictionary', err); 20 console.error('Could not load dictionary', err);
@@ -44,7 +41,7 @@ export async function switchDict(locale) {
44 provider.unloadDictionary(locale); 41 provider.unloadDictionary(locale);
45 } 42 }
46 loadDictionary(locale); 43 loadDictionary(locale);
47 attached.switchLanguage(locale); 44 provider.switchDictionary(locale);
48 45
49 debug('Switched dictionary to', locale); 46 debug('Switched dictionary to', locale);
50 47
@@ -61,14 +58,12 @@ export default async function initialize(languageCode = 'en-us') {
61 const locale = languageCode.toLowerCase(); 58 const locale = languageCode.toLowerCase();
62 59
63 debug('Init spellchecker'); 60 debug('Init spellchecker');
64 await provider.initialize({ environment: ENVIRONMENT.NODE }); 61 await provider.initialize();
65 62 // await loadDictionaries();
66 debug('Attaching spellcheck provider');
67 attached = await attachSpellCheckProvider(provider);
68 63
69 debug('Available spellchecker dictionaries', provider.availableDictionaries); 64 debug('Available spellchecker dictionaries', provider.availableDictionaries);
70 65
71 attached.switchLanguage(locale); 66 switchDict(locale);
72 67
73 return provider; 68 return provider;
74 } catch (err) { 69 } catch (err) {