aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2019-09-06 09:28:12 +0200
committerLibravatar Stefan Malzner <stefan@adlk.io>2019-09-06 09:28:12 +0200
commitb5b2976f447779a584f0d2fdcce21c8e62156df3 (patch)
tree9c13cf950b28f9d8824c5a1c028a53aae4bedeef /src
parentUpdate 3rd party recipe wording (diff)
parentFix race condition when team data is not yet loaded (diff)
downloadferdium-app-b5b2976f447779a584f0d2fdcce21c8e62156df3.tar.gz
ferdium-app-b5b2976f447779a584f0d2fdcce21c8e62156df3.tar.zst
ferdium-app-b5b2976f447779a584f0d2fdcce21c8e62156df3.zip
Merge branch 'develop' of https://github.com/meetfranz/franz into develop
Diffstat (limited to 'src')
-rw-r--r--src/components/layout/AppLayout.js10
-rw-r--r--src/features/announcements/store.js5
-rw-r--r--src/features/delayApp/index.js10
-rw-r--r--src/features/todos/components/TodosWebview.js104
-rw-r--r--src/features/todos/containers/TodosScreen.js2
-rw-r--r--src/features/todos/store.js22
-rw-r--r--src/stores/UserStore.js6
7 files changed, 92 insertions, 67 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
index 941e60bfd..200777ae6 100644
--- a/src/components/layout/AppLayout.js
+++ b/src/components/layout/AppLayout.js
@@ -125,7 +125,15 @@ class AppLayout extends Component {
125 sticky={item.sticky} 125 sticky={item.sticky}
126 onHide={() => removeNewsItem({ newsId: item.id })} 126 onHide={() => removeNewsItem({ newsId: item.id })}
127 > 127 >
128 <span dangerouslySetInnerHTML={createMarkup(item.message)} /> 128 <span
129 dangerouslySetInnerHTML={createMarkup(item.message)}
130 onClick={(event) => {
131 const { target } = event;
132 if (target && target.hasAttribute('data-is-news-cta')) {
133 removeNewsItem({ newsId: item.id });
134 }
135 }}
136 />
129 </InfoBar> 137 </InfoBar>
130 ))} 138 ))}
131 {hasActivatedTrial && ( 139 {hasActivatedTrial && (
diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js
index de7ed2596..d58afbc8e 100644
--- a/src/features/announcements/store.js
+++ b/src/features/announcements/store.js
@@ -63,6 +63,11 @@ export class AnnouncementsStore extends FeatureStore {
63 return this.stores.settings.stats.appStarts <= 1; 63 return this.stores.settings.stats.appStarts <= 1;
64 } 64 }
65 65
66 @computed get isAnnouncementShown() {
67 const { router } = this.stores;
68 return router.location.pathname.includes('/announcements');
69 }
70
66 async start(stores, actions) { 71 async start(stores, actions) {
67 debug('AnnouncementsStore::start'); 72 debug('AnnouncementsStore::start');
68 this.stores = stores; 73 this.stores = stores;
diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js
index 627537de7..c0029873a 100644
--- a/src/features/delayApp/index.js
+++ b/src/features/delayApp/index.js
@@ -44,14 +44,16 @@ export default function init(stores) {
44 config.delayDuration = globalConfig.wait !== undefined ? globalConfig.wait : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait; 44 config.delayDuration = globalConfig.wait !== undefined ? globalConfig.wait : DEFAULT_FEATURES_CONFIG.needToWaitToProceedConfig.wait;
45 45
46 autorun(() => { 46 autorun(() => {
47 if (stores.services.allDisplayed.length === 0) { 47 const { isAnnouncementShown } = stores.announcements;
48 debug('seas', stores.services.all.length); 48 if (stores.services.allDisplayed.length === 0 || isAnnouncementShown) {
49 shownAfterLaunch = true; 49 shownAfterLaunch = true;
50 setVisibility(false);
50 return; 51 return;
51 } 52 }
52 53
53 const diff = moment().diff(timeLastDelay); 54 const diff = moment().diff(timeLastDelay);
54 if ((stores.app.isFocused && diff >= config.delayOffset) || !shownAfterLaunch) { 55 const itsTimeToWait = diff >= config.delayOffset;
56 if (!isAnnouncementShown && ((stores.app.isFocused && itsTimeToWait) || !shownAfterLaunch)) {
55 debug(`App will be delayed for ${config.delayDuration / 1000}s`); 57 debug(`App will be delayed for ${config.delayDuration / 1000}s`);
56 58
57 setVisibility(true); 59 setVisibility(true);
@@ -66,6 +68,8 @@ export default function init(stores) {
66 68
67 setVisibility(false); 69 setVisibility(false);
68 }, config.delayDuration + 1000); // timer needs to be able to hit 0 70 }, config.delayDuration + 1000); // timer needs to be able to hit 0
71 } else {
72 setVisibility(false);
69 } 73 }
70 }); 74 });
71 } else { 75 } else {
diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js
index 44c94a3ff..c06183e37 100644
--- a/src/features/todos/components/TodosWebview.js
+++ b/src/features/todos/components/TodosWebview.js
@@ -41,10 +41,6 @@ const styles = theme => ({
41 '&:hover $closeTodosButton': { 41 '&:hover $closeTodosButton': {
42 opacity: 1, 42 opacity: 1,
43 }, 43 },
44 },
45 webview: {
46 height: '100%',
47
48 '& webview': { 44 '& webview': {
49 height: '100%', 45 height: '100%',
50 }, 46 },
@@ -245,60 +241,58 @@ class TodosWebview extends Component {
245 const { intl } = this.context; 241 const { intl } = this.context;
246 242
247 return ( 243 return (
248 <> 244 <div
249 <div 245 className={classes.root}
250 className={classes.root} 246 style={{ width: isVisible ? width : 0 }}
251 style={{ width: isVisible ? width : 0 }} 247 onMouseUp={() => this.stopResize()}
252 onMouseUp={() => this.stopResize()} 248 ref={(node) => { this.node = node; }}
253 ref={(node) => { this.node = node; }} 249 >
250 <button
251 onClick={() => togglePanel()}
252 className={isVisible ? classes.closeTodosButton : classes.openTodosButton}
253 type="button"
254 > 254 >
255 <button 255 <Icon icon={isVisible ? mdiChevronRight : mdiCheckAll} size={2} />
256 onClick={() => togglePanel()} 256 </button>
257 className={isVisible ? classes.closeTodosButton : classes.openTodosButton} 257 <div
258 type="button" 258 className={classes.resizeHandler}
259 > 259 style={Object.assign({ left: delta }, isDragging ? { width: 600, marginLeft: -200 } : {})} // This hack is required as resizing with webviews beneath behaves quite bad
260 <Icon icon={isVisible ? mdiChevronRight : mdiCheckAll} size={2} /> 260 onMouseDown={e => this.startResize(e)}
261 </button> 261 />
262 {isDragging && (
262 <div 263 <div
263 className={classes.resizeHandler} 264 className={classes.dragIndicator}
264 style={Object.assign({ left: delta }, isDragging ? { width: 600, marginLeft: -200 } : {})} // This hack is required as resizing with webviews beneath behaves quite bad 265 style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad
265 onMouseDown={e => this.startResize(e)} 266 />
267 )}
268 {isTodosIncludedInCurrentPlan ? (
269 <Webview
270 className={classes.webview}
271 onDidAttach={() => {
272 const { setTodosWebview } = this.props;
273 setTodosWebview(this.webview);
274 this.startListeningToIpcMessages();
275 }}
276 partition="persist:todos"
277 preload="./features/todos/preload.js"
278 ref={(webview) => { this.webview = webview ? webview.view : null; }}
279 src={environment.TODOS_FRONTEND}
266 /> 280 />
267 {isDragging && ( 281 ) : (
268 <div 282 <Appear>
269 className={classes.dragIndicator} 283 <div className={classes.premiumContainer}>
270 style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad 284 <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={4} />
271 /> 285 <p>{intl.formatMessage(messages.premiumInfo)}</p>
272 )} 286 <p>{intl.formatMessage(messages.rolloutInfo)}</p>
273 {isTodosIncludedInCurrentPlan ? ( 287 <UpgradeButton
274 <Webview 288 className={classes.premiumCTA}
275 className={classes.webview} 289 gaEventInfo={{ category: 'Todos', event: 'upgrade' }}
276 onDidAttach={() => { 290 short
277 const { setTodosWebview } = this.props; 291 />
278 setTodosWebview(this.webview); 292 </div>
279 this.startListeningToIpcMessages(); 293 </Appear>
280 }} 294 )}
281 partition="persist:todos" 295 </div>
282 preload="./features/todos/preload.js"
283 ref={(webview) => { this.webview = webview ? webview.view : null; }}
284 src={environment.TODOS_FRONTEND}
285 />
286 ) : (
287 <Appear>
288 <div className={classes.premiumContainer}>
289 <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={4} />
290 <p>{intl.formatMessage(messages.premiumInfo)}</p>
291 <p>{intl.formatMessage(messages.rolloutInfo)}</p>
292 <UpgradeButton
293 className={classes.premiumCTA}
294 gaEventInfo={{ category: 'Todos', event: 'upgrade' }}
295 short
296 />
297 </div>
298 </Appear>
299 )}
300 </div>
301 </>
302 ); 296 );
303 } 297 }
304} 298}
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js
index 65afc985b..a5da0b014 100644
--- a/src/features/todos/containers/TodosScreen.js
+++ b/src/features/todos/containers/TodosScreen.js
@@ -11,7 +11,7 @@ import { todoActions } from '../actions';
11@inject('stores', 'actions') @observer 11@inject('stores', 'actions') @observer
12class TodosScreen extends Component { 12class TodosScreen extends Component {
13 render() { 13 render() {
14 if (!todosStore || !todosStore.isFeatureActive) { 14 if (!todosStore || !todosStore.isFeatureActive || todosStore.isTodosPanelForceHidden) {
15 return null; 15 return null;
16 } 16 }
17 17
diff --git a/src/features/todos/store.js b/src/features/todos/store.js
index 5c6abff4c..ea05077ab 100644
--- a/src/features/todos/store.js
+++ b/src/features/todos/store.js
@@ -29,10 +29,13 @@ export default class TodoStore extends FeatureStore {
29 return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width; 29 return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width;
30 } 30 }
31 31
32 @computed get isTodosPanelForceHidden() {
33 const { isAnnouncementShown } = this.stores.announcements;
34 return delayAppState.isDelayAppScreenVisible || isAnnouncementShown;
35 }
36
32 @computed get isTodosPanelVisible() { 37 @computed get isTodosPanelVisible() {
33 if (delayAppState.isDelayAppScreenVisible) return false;
34 if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; 38 if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE;
35
36 return this.settings.isTodosPanelVisible; 39 return this.settings.isTodosPanelVisible;
37 } 40 }
38 41
@@ -61,6 +64,7 @@ export default class TodoStore extends FeatureStore {
61 64
62 this._allReactions = createReactions([ 65 this._allReactions = createReactions([
63 this._setFeatureEnabledReaction, 66 this._setFeatureEnabledReaction,
67 this._updateTodosConfig,
64 this._firstLaunchReaction, 68 this._firstLaunchReaction,
65 ]); 69 ]);
66 70
@@ -124,11 +128,16 @@ export default class TodoStore extends FeatureStore {
124 // Todos client message handlers 128 // Todos client message handlers
125 129
126 _onTodosClientInitialized = () => { 130 _onTodosClientInitialized = () => {
131 const { authToken } = this.stores.user;
132 const { isDarkThemeActive } = this.stores.ui;
133 const { locale } = this.stores.app;
134 if (!this.webview) return;
127 this.webview.send(IPC.TODOS_HOST_CHANNEL, { 135 this.webview.send(IPC.TODOS_HOST_CHANNEL, {
128 action: 'todos:configure', 136 action: 'todos:configure',
129 data: { 137 data: {
130 authToken: this.stores.user.authToken, 138 authToken,
131 theme: this.stores.ui.isDarkThemeActive ? ThemeType.dark : ThemeType.default, 139 locale,
140 theme: isDarkThemeActive ? ThemeType.dark : ThemeType.default,
132 }, 141 },
133 }); 142 });
134 }; 143 };
@@ -148,6 +157,11 @@ export default class TodoStore extends FeatureStore {
148 this.isFeatureEnabled = isTodosEnabled; 157 this.isFeatureEnabled = isTodosEnabled;
149 }; 158 };
150 159
160 _updateTodosConfig = () => {
161 // Resend the config if any part changes in Franz:
162 this._onTodosClientInitialized();
163 };
164
151 _firstLaunchReaction = () => { 165 _firstLaunchReaction = () => {
152 const { stats } = this.stores.settings.all; 166 const { stats } = this.stores.settings.all;
153 167
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 6e6f745c7..b652098f9 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -161,11 +161,11 @@ export default class UserStore extends Store {
161 } 161 }
162 162
163 @computed get isPremiumOverride() { 163 @computed get isPremiumOverride() {
164 return (!this.team.plan && this.isPremium) || (this.team.state === 'expired' && this.isPremium); 164 return ((!this.team || !this.team.plan) && this.isPremium) || (this.team.state === 'expired' && this.isPremium);
165 } 165 }
166 166
167 @computed get isPersonal() { 167 @computed get isPersonal() {
168 if (!this.team.plan) return false; 168 if (!this.team || !this.team.plan) return false;
169 const plan = getPlan(this.team.plan); 169 const plan = getPlan(this.team.plan);
170 170
171 return plan === PLANS.PERSONAL; 171 return plan === PLANS.PERSONAL;
@@ -174,7 +174,7 @@ export default class UserStore extends Store {
174 @computed get isPro() { 174 @computed get isPro() {
175 if (this.isPremiumOverride) return true; 175 if (this.isPremiumOverride) return true;
176 176
177 if ((!this.team.plan || this.team.state === 'expired')) return false; 177 if (!this.team || (!this.team.plan || this.team.state === 'expired')) return false;
178 const plan = getPlan(this.team.plan); 178 const plan = getPlan(this.team.plan);
179 179
180 return plan === PLANS.PRO || plan === PLANS.LEGACY; 180 return plan === PLANS.PRO || plan === PLANS.LEGACY;