diff options
author | Dominik Guzei <dominik.guzei@gmail.com> | 2019-04-11 12:53:16 +0200 |
---|---|---|
committer | Dominik Guzei <dominik.guzei@gmail.com> | 2019-04-11 12:53:16 +0200 |
commit | ca9d5863f9067f2a32498da763cd536e0bcc5c77 (patch) | |
tree | 30d0f41f9db7c499cc3e1f2f1e39004294be7f80 | |
parent | merge-in workspace feature (diff) | |
download | ferdium-app-ca9d5863f9067f2a32498da763cd536e0bcc5c77.tar.gz ferdium-app-ca9d5863f9067f2a32498da763cd536e0bcc5c77.tar.zst ferdium-app-ca9d5863f9067f2a32498da763cd536e0bcc5c77.zip |
refactor announcements to newest feature pattern
-rw-r--r-- | src/components/layout/AppLayout.js | 2 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 5 | ||||
-rw-r--r-- | src/features/announcements/api.js | 6 | ||||
-rw-r--r-- | src/features/announcements/components/AnnouncementScreen.js (renamed from src/features/announcements/Component.js) | 10 | ||||
-rw-r--r-- | src/features/announcements/index.js | 17 | ||||
-rw-r--r-- | src/features/announcements/state.js | 17 | ||||
-rw-r--r-- | src/features/announcements/store.js | 49 | ||||
-rw-r--r-- | src/i18n/locales/defaultMessages.json | 18 | ||||
-rw-r--r-- | src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json | 15 |
9 files changed, 83 insertions, 56 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 985475c8d..eb3f03f12 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -14,7 +14,7 @@ import ErrorBoundary from '../util/ErrorBoundary'; | |||
14 | // import globalMessages from '../../i18n/globalMessages'; | 14 | // import globalMessages from '../../i18n/globalMessages'; |
15 | 15 | ||
16 | import { isWindows } from '../../environment'; | 16 | import { isWindows } from '../../environment'; |
17 | import AnnouncementScreen from '../../features/announcements/Component'; | 17 | import AnnouncementScreen from '../../features/announcements/components/AnnouncementScreen'; |
18 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; | 18 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; |
19 | import { workspaceStore } from '../../features/workspaces'; | 19 | import { workspaceStore } from '../../features/workspaces'; |
20 | 20 | ||
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 0357f63bd..8a0e105e7 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -20,10 +20,11 @@ import Services from '../../components/services/content/Services'; | |||
20 | import AppLoader from '../../components/ui/AppLoader'; | 20 | import AppLoader from '../../components/ui/AppLoader'; |
21 | 21 | ||
22 | import { state as delayAppState } from '../../features/delayApp'; | 22 | import { state as delayAppState } from '../../features/delayApp'; |
23 | import { announcementsState } from '../../features/announcements/state'; | 23 | import { } from '../../features/announcements/store'; |
24 | import { workspaceActions } from '../../features/workspaces/actions'; | 24 | import { workspaceActions } from '../../features/workspaces/actions'; |
25 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; | 25 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; |
26 | import { workspaceStore } from '../../features/workspaces'; | 26 | import { workspaceStore } from '../../features/workspaces'; |
27 | import { announcementsStore } from '../../features/announcements'; | ||
27 | 28 | ||
28 | export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { | 29 | export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { |
29 | static defaultProps = { | 30 | static defaultProps = { |
@@ -150,7 +151,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
150 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} | 151 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} |
151 | darkMode={settings.all.app.darkMode} | 152 | darkMode={settings.all.app.darkMode} |
152 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} | 153 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} |
153 | isAnnouncementVisible={announcementsState.isAnnouncementVisible} | 154 | isAnnouncementVisible={announcementsStore.isAnnouncementVisible} |
154 | > | 155 | > |
155 | {React.Children.count(children) > 0 ? children : null} | 156 | {React.Children.count(children) > 0 ? children : null} |
156 | </AppLayout> | 157 | </AppLayout> |
diff --git a/src/features/announcements/api.js b/src/features/announcements/api.js index ec16066a6..09fcb8235 100644 --- a/src/features/announcements/api.js +++ b/src/features/announcements/api.js | |||
@@ -1,8 +1,9 @@ | |||
1 | import { remote } from 'electron'; | 1 | import { remote } from 'electron'; |
2 | import Request from '../../stores/lib/Request'; | ||
2 | 3 | ||
3 | const debug = require('debug')('Franz:feature:announcements:api'); | 4 | const debug = require('debug')('Franz:feature:announcements:api'); |
4 | 5 | ||
5 | export default { | 6 | export const announcementsApi = { |
6 | async getCurrentVersion() { | 7 | async getCurrentVersion() { |
7 | debug('getting current version of electron app'); | 8 | debug('getting current version of electron app'); |
8 | return Promise.resolve(remote.app.getVersion()); | 9 | return Promise.resolve(remote.app.getVersion()); |
@@ -17,3 +18,6 @@ export default { | |||
17 | return data.body; | 18 | return data.body; |
18 | }, | 19 | }, |
19 | }; | 20 | }; |
21 | |||
22 | export const getCurrentVersionRequest = new Request(announcementsApi, 'getCurrentVersion'); | ||
23 | export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncementForVersion'); | ||
diff --git a/src/features/announcements/Component.js b/src/features/announcements/components/AnnouncementScreen.js index 5d95f5d84..5b3e7aeaa 100644 --- a/src/features/announcements/Component.js +++ b/src/features/announcements/components/AnnouncementScreen.js | |||
@@ -4,8 +4,8 @@ import PropTypes from 'prop-types'; | |||
4 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 5 | import { defineMessages, intlShape } from 'react-intl'; |
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | import { themeSidebarWidth } from '@meetfranz/theme/lib/themes/legacy'; | 7 | import { themeSidebarWidth } from '../../../../packages/theme/lib/themes/legacy'; |
8 | import state from './state'; | 8 | import { announcementsStore } from '../index'; |
9 | 9 | ||
10 | const messages = defineMessages({ | 10 | const messages = defineMessages({ |
11 | headline: { | 11 | headline: { |
@@ -61,12 +61,14 @@ class AnnouncementScreen extends Component { | |||
61 | return ( | 61 | return ( |
62 | <div className={`${classes.container}`}> | 62 | <div className={`${classes.container}`}> |
63 | <h1 className={classes.headline}> | 63 | <h1 className={classes.headline}> |
64 | {intl.formatMessage(messages.headline, { version: state.currentVersion })} | 64 | {intl.formatMessage(messages.headline, { |
65 | version: announcementsStore.currentVersion, | ||
66 | })} | ||
65 | </h1> | 67 | </h1> |
66 | <div | 68 | <div |
67 | className={classes.body} | 69 | className={classes.body} |
68 | dangerouslySetInnerHTML={{ | 70 | dangerouslySetInnerHTML={{ |
69 | __html: marked(state.announcement, { sanitize: true }), | 71 | __html: marked(announcementsStore.announcement, { sanitize: true }), |
70 | }} | 72 | }} |
71 | /> | 73 | /> |
72 | </div> | 74 | </div> |
diff --git a/src/features/announcements/index.js b/src/features/announcements/index.js index 5ea74e0af..c087689a7 100644 --- a/src/features/announcements/index.js +++ b/src/features/announcements/index.js | |||
@@ -1,11 +1,9 @@ | |||
1 | import { reaction, runInAction } from 'mobx'; | 1 | import { reaction } from 'mobx'; |
2 | import { AnnouncementsStore } from './store'; | 2 | import { AnnouncementsStore } from './store'; |
3 | import api from './api'; | ||
4 | import state, { resetState } from './state'; | ||
5 | 3 | ||
6 | const debug = require('debug')('Franz:feature:announcements'); | 4 | const debug = require('debug')('Franz:feature:announcements'); |
7 | 5 | ||
8 | let store = null; | 6 | export const announcementsStore = new AnnouncementsStore(); |
9 | 7 | ||
10 | export default function initAnnouncements(stores, actions) { | 8 | export default function initAnnouncements(stores, actions) { |
11 | // const { features } = stores; | 9 | // const { features } = stores; |
@@ -19,15 +17,10 @@ export default function initAnnouncements(stores, actions) { | |||
19 | (isEnabled) => { | 17 | (isEnabled) => { |
20 | if (isEnabled) { | 18 | if (isEnabled) { |
21 | debug('Initializing `announcements` feature'); | 19 | debug('Initializing `announcements` feature'); |
22 | store = new AnnouncementsStore(stores, api, actions, state); | 20 | announcementsStore.start(stores, actions); |
23 | store.initialize(); | 21 | } else if (announcementsStore.isFeatureActive) { |
24 | runInAction(() => { state.isFeatureActive = true; }); | ||
25 | } else if (store) { | ||
26 | debug('Disabling `announcements` feature'); | 22 | debug('Disabling `announcements` feature'); |
27 | runInAction(() => { state.isFeatureActive = false; }); | 23 | announcementsStore.stop(); |
28 | store.teardown(); | ||
29 | store = null; | ||
30 | resetState(); // Reset state to default | ||
31 | } | 24 | } |
32 | }, | 25 | }, |
33 | { | 26 | { |
diff --git a/src/features/announcements/state.js b/src/features/announcements/state.js deleted file mode 100644 index 81b632253..000000000 --- a/src/features/announcements/state.js +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | import { observable } from 'mobx'; | ||
2 | |||
3 | const defaultState = { | ||
4 | announcement: null, | ||
5 | currentVersion: null, | ||
6 | lastUsedVersion: null, | ||
7 | isAnnouncementVisible: false, | ||
8 | isFeatureActive: false, | ||
9 | }; | ||
10 | |||
11 | export const announcementsState = observable(defaultState); | ||
12 | |||
13 | export function resetState() { | ||
14 | Object.assign(announcementsState, defaultState); | ||
15 | } | ||
16 | |||
17 | export default announcementsState; | ||
diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js index 004a44062..c59700926 100644 --- a/src/features/announcements/store.js +++ b/src/features/announcements/store.js | |||
@@ -1,28 +1,39 @@ | |||
1 | import { action, observable, reaction } from 'mobx'; | 1 | import { action, observable, reaction } from 'mobx'; |
2 | import semver from 'semver'; | 2 | import semver from 'semver'; |
3 | 3 | import { FeatureStore } from '../utils/FeatureStore'; | |
4 | import Request from '../../stores/lib/Request'; | 4 | import { getAnnouncementRequest, getCurrentVersionRequest } from './api'; |
5 | import Store from '../../stores/lib/Store'; | ||
6 | 5 | ||
7 | const debug = require('debug')('Franz:feature:announcements:store'); | 6 | const debug = require('debug')('Franz:feature:announcements:store'); |
8 | 7 | ||
9 | export class AnnouncementsStore extends Store { | 8 | export class AnnouncementsStore extends FeatureStore { |
10 | @observable getCurrentVersion = new Request(this.api, 'getCurrentVersion'); | ||
11 | 9 | ||
12 | @observable getAnnouncement = new Request(this.api, 'getAnnouncementForVersion'); | 10 | @observable announcement = null; |
13 | 11 | ||
14 | constructor(stores, api, actions, state) { | 12 | @observable currentVersion = null; |
15 | super(stores, api, actions); | 13 | |
16 | this.state = state; | 14 | @observable lastUsedVersion = null; |
17 | } | 15 | |
16 | @observable isAnnouncementVisible = false; | ||
18 | 17 | ||
19 | async setup() { | 18 | @observable isFeatureActive = false; |
19 | |||
20 | async start(stores, actions) { | ||
21 | debug('AnnouncementsStore::start'); | ||
22 | this.stores = stores; | ||
23 | this.actions = actions; | ||
20 | await this.fetchLastUsedVersion(); | 24 | await this.fetchLastUsedVersion(); |
21 | await this.fetchCurrentVersion(); | 25 | await this.fetchCurrentVersion(); |
22 | await this.fetchReleaseAnnouncement(); | 26 | await this.fetchReleaseAnnouncement(); |
23 | this.showAnnouncementIfNotSeenYet(); | 27 | this.showAnnouncementIfNotSeenYet(); |
24 | 28 | ||
25 | this.actions.announcements.show.listen(this._showAnnouncement.bind(this)); | 29 | this.actions.announcements.show.listen(this._showAnnouncement.bind(this)); |
30 | this.isFeatureActive = true; | ||
31 | } | ||
32 | |||
33 | stop() { | ||
34 | debug('AnnouncementsStore::stop'); | ||
35 | this.isFeatureActive = false; | ||
36 | this.isAnnouncementVisible = false; | ||
26 | } | 37 | } |
27 | 38 | ||
28 | // ====== PUBLIC ====== | 39 | // ====== PUBLIC ====== |
@@ -35,14 +46,14 @@ export class AnnouncementsStore extends Store { | |||
35 | 46 | ||
36 | async fetchCurrentVersion() { | 47 | async fetchCurrentVersion() { |
37 | debug('getting current version from api'); | 48 | debug('getting current version from api'); |
38 | const version = await this.getCurrentVersion.execute(); | 49 | const version = await getCurrentVersionRequest.execute(); |
39 | this._setCurrentVersion(version); | 50 | this._setCurrentVersion(version); |
40 | } | 51 | } |
41 | 52 | ||
42 | async fetchReleaseAnnouncement() { | 53 | async fetchReleaseAnnouncement() { |
43 | debug('getting release announcement from api'); | 54 | debug('getting release announcement from api'); |
44 | try { | 55 | try { |
45 | const announcement = await this.getAnnouncement.execute(this.state.currentVersion); | 56 | const announcement = await getAnnouncementRequest.execute(this.currentVersion); |
46 | this._setAnnouncement(announcement); | 57 | this._setAnnouncement(announcement); |
47 | } catch (error) { | 58 | } catch (error) { |
48 | this._setAnnouncement(null); | 59 | this._setAnnouncement(null); |
@@ -50,7 +61,7 @@ export class AnnouncementsStore extends Store { | |||
50 | } | 61 | } |
51 | 62 | ||
52 | showAnnouncementIfNotSeenYet() { | 63 | showAnnouncementIfNotSeenYet() { |
53 | const { announcement, currentVersion, lastUsedVersion } = this.state; | 64 | const { announcement, currentVersion, lastUsedVersion } = this; |
54 | if (announcement && semver.gt(currentVersion, lastUsedVersion)) { | 65 | if (announcement && semver.gt(currentVersion, lastUsedVersion)) { |
55 | debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); | 66 | debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); |
56 | this._showAnnouncement(); | 67 | this._showAnnouncement(); |
@@ -64,21 +75,21 @@ export class AnnouncementsStore extends Store { | |||
64 | 75 | ||
65 | @action _setCurrentVersion(version) { | 76 | @action _setCurrentVersion(version) { |
66 | debug(`setting current version to ${version}`); | 77 | debug(`setting current version to ${version}`); |
67 | this.state.currentVersion = version; | 78 | this.currentVersion = version; |
68 | } | 79 | } |
69 | 80 | ||
70 | @action _setLastUsedVersion(version) { | 81 | @action _setLastUsedVersion(version) { |
71 | debug(`setting last used version to ${version}`); | 82 | debug(`setting last used version to ${version}`); |
72 | this.state.lastUsedVersion = version; | 83 | this.lastUsedVersion = version; |
73 | } | 84 | } |
74 | 85 | ||
75 | @action _setAnnouncement(announcement) { | 86 | @action _setAnnouncement(announcement) { |
76 | debug(`setting announcement to ${announcement}`); | 87 | debug(`setting announcement to ${announcement}`); |
77 | this.state.announcement = announcement; | 88 | this.announcement = announcement; |
78 | } | 89 | } |
79 | 90 | ||
80 | @action _showAnnouncement() { | 91 | @action _showAnnouncement() { |
81 | this.state.isAnnouncementVisible = true; | 92 | this.isAnnouncementVisible = true; |
82 | this.actions.service.blurActive(); | 93 | this.actions.service.blurActive(); |
83 | const dispose = reaction( | 94 | const dispose = reaction( |
84 | () => this.stores.services.active, | 95 | () => this.stores.services.active, |
@@ -90,6 +101,6 @@ export class AnnouncementsStore extends Store { | |||
90 | } | 101 | } |
91 | 102 | ||
92 | @action _hideAnnouncement() { | 103 | @action _hideAnnouncement() { |
93 | this.state.isAnnouncementVisible = false; | 104 | this.isAnnouncementVisible = false; |
94 | } | 105 | } |
95 | } | 106 | } |
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 698698515..1dd31324e 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json | |||
@@ -3100,6 +3100,24 @@ | |||
3100 | { | 3100 | { |
3101 | "descriptors": [ | 3101 | "descriptors": [ |
3102 | { | 3102 | { |
3103 | "defaultMessage": "!!!What's new in Franz {version}?", | ||
3104 | "end": { | ||
3105 | "column": 3, | ||
3106 | "line": 14 | ||
3107 | }, | ||
3108 | "file": "src/features/announcements/components/AnnouncementScreen.js", | ||
3109 | "id": "feature.announcements.headline", | ||
3110 | "start": { | ||
3111 | "column": 12, | ||
3112 | "line": 11 | ||
3113 | } | ||
3114 | } | ||
3115 | ], | ||
3116 | "path": "src/features/announcements/components/AnnouncementScreen.json" | ||
3117 | }, | ||
3118 | { | ||
3119 | "descriptors": [ | ||
3120 | { | ||
3103 | "defaultMessage": "!!!Please purchase license to skip waiting", | 3121 | "defaultMessage": "!!!Please purchase license to skip waiting", |
3104 | "end": { | 3122 | "end": { |
3105 | "column": 3, | 3123 | "column": 3, |
diff --git a/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json new file mode 100644 index 000000000..225670ee2 --- /dev/null +++ b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json | |||
@@ -0,0 +1,15 @@ | |||
1 | [ | ||
2 | { | ||
3 | "id": "feature.announcements.headline", | ||
4 | "defaultMessage": "!!!What's new in Franz {version}?", | ||
5 | "file": "src/features/announcements/components/AnnouncementScreen.js", | ||
6 | "start": { | ||
7 | "line": 11, | ||
8 | "column": 12 | ||
9 | }, | ||
10 | "end": { | ||
11 | "line": 14, | ||
12 | "column": 3 | ||
13 | } | ||
14 | } | ||
15 | ] \ No newline at end of file | ||