From ca9d5863f9067f2a32498da763cd536e0bcc5c77 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 11 Apr 2019 12:53:16 +0200 Subject: refactor announcements to newest feature pattern --- src/components/layout/AppLayout.js | 2 +- src/containers/layout/AppLayoutContainer.js | 5 +- src/features/announcements/Component.js | 77 --------------------- src/features/announcements/api.js | 6 +- .../announcements/components/AnnouncementScreen.js | 79 ++++++++++++++++++++++ src/features/announcements/index.js | 17 ++--- src/features/announcements/state.js | 17 ----- src/features/announcements/store.js | 49 ++++++++------ src/i18n/locales/defaultMessages.json | 18 +++++ .../components/AnnouncementScreen.json | 15 ++++ 10 files changed, 156 insertions(+), 129 deletions(-) delete mode 100644 src/features/announcements/Component.js create mode 100644 src/features/announcements/components/AnnouncementScreen.js delete mode 100644 src/features/announcements/state.js create mode 100644 src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json (limited to 'src') 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'; // import globalMessages from '../../i18n/globalMessages'; import { isWindows } from '../../environment'; -import AnnouncementScreen from '../../features/announcements/Component'; +import AnnouncementScreen from '../../features/announcements/components/AnnouncementScreen'; import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; import { workspaceStore } from '../../features/workspaces'; 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'; import AppLoader from '../../components/ui/AppLoader'; import { state as delayAppState } from '../../features/delayApp'; -import { announcementsState } from '../../features/announcements/state'; +import { } from '../../features/announcements/store'; import { workspaceActions } from '../../features/workspaces/actions'; import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; import { workspaceStore } from '../../features/workspaces'; +import { announcementsStore } from '../../features/announcements'; export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { static defaultProps = { @@ -150,7 +151,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e areRequiredRequestsLoading={requests.areRequiredRequestsLoading} darkMode={settings.all.app.darkMode} isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} - isAnnouncementVisible={announcementsState.isAnnouncementVisible} + isAnnouncementVisible={announcementsStore.isAnnouncementVisible} > {React.Children.count(children) > 0 ? children : null} diff --git a/src/features/announcements/Component.js b/src/features/announcements/Component.js deleted file mode 100644 index 5d95f5d84..000000000 --- a/src/features/announcements/Component.js +++ /dev/null @@ -1,77 +0,0 @@ -import React, { Component } from 'react'; -import marked from 'marked'; -import PropTypes from 'prop-types'; -import { inject, observer } from 'mobx-react'; -import { defineMessages, intlShape } from 'react-intl'; -import injectSheet from 'react-jss'; -import { themeSidebarWidth } from '@meetfranz/theme/lib/themes/legacy'; -import state from './state'; - -const messages = defineMessages({ - headline: { - id: 'feature.announcements.headline', - defaultMessage: '!!!What\'s new in Franz {version}?', - }, -}); - -const styles = theme => ({ - container: { - background: theme.colorBackground, - position: 'absolute', - top: 0, - zIndex: 140, - width: `calc(100% - ${themeSidebarWidth})`, - display: 'flex', - 'flex-direction': 'column', - 'align-items': 'center', - 'justify-content': 'center', - }, - headline: { - color: theme.colorHeadline, - margin: [25, 0, 40], - 'max-width': 500, - 'text-align': 'center', - 'line-height': '1.3em', - }, - body: { - '& h3': { - fontSize: '24px', - margin: '1.5em 0 1em 0', - }, - '& li': { - marginBottom: '1em', - }, - }, -}); - - -@inject('actions') @injectSheet(styles) @observer -class AnnouncementScreen extends Component { - static propTypes = { - classes: PropTypes.object.isRequired, - }; - - static contextTypes = { - intl: intlShape, - }; - - render() { - const { classes } = this.props; - const { intl } = this.context; - return ( -
-

- {intl.formatMessage(messages.headline, { version: state.currentVersion })} -

-
-
- ); - } -} - -export default AnnouncementScreen; 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 @@ import { remote } from 'electron'; +import Request from '../../stores/lib/Request'; const debug = require('debug')('Franz:feature:announcements:api'); -export default { +export const announcementsApi = { async getCurrentVersion() { debug('getting current version of electron app'); return Promise.resolve(remote.app.getVersion()); @@ -17,3 +18,6 @@ export default { return data.body; }, }; + +export const getCurrentVersionRequest = new Request(announcementsApi, 'getCurrentVersion'); +export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncementForVersion'); diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js new file mode 100644 index 000000000..5b3e7aeaa --- /dev/null +++ b/src/features/announcements/components/AnnouncementScreen.js @@ -0,0 +1,79 @@ +import React, { Component } from 'react'; +import marked from 'marked'; +import PropTypes from 'prop-types'; +import { inject, observer } from 'mobx-react'; +import { defineMessages, intlShape } from 'react-intl'; +import injectSheet from 'react-jss'; +import { themeSidebarWidth } from '../../../../packages/theme/lib/themes/legacy'; +import { announcementsStore } from '../index'; + +const messages = defineMessages({ + headline: { + id: 'feature.announcements.headline', + defaultMessage: '!!!What\'s new in Franz {version}?', + }, +}); + +const styles = theme => ({ + container: { + background: theme.colorBackground, + position: 'absolute', + top: 0, + zIndex: 140, + width: `calc(100% - ${themeSidebarWidth})`, + display: 'flex', + 'flex-direction': 'column', + 'align-items': 'center', + 'justify-content': 'center', + }, + headline: { + color: theme.colorHeadline, + margin: [25, 0, 40], + 'max-width': 500, + 'text-align': 'center', + 'line-height': '1.3em', + }, + body: { + '& h3': { + fontSize: '24px', + margin: '1.5em 0 1em 0', + }, + '& li': { + marginBottom: '1em', + }, + }, +}); + + +@inject('actions') @injectSheet(styles) @observer +class AnnouncementScreen extends Component { + static propTypes = { + classes: PropTypes.object.isRequired, + }; + + static contextTypes = { + intl: intlShape, + }; + + render() { + const { classes } = this.props; + const { intl } = this.context; + return ( +
+

+ {intl.formatMessage(messages.headline, { + version: announcementsStore.currentVersion, + })} +

+
+
+ ); + } +} + +export default AnnouncementScreen; 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 @@ -import { reaction, runInAction } from 'mobx'; +import { reaction } from 'mobx'; import { AnnouncementsStore } from './store'; -import api from './api'; -import state, { resetState } from './state'; const debug = require('debug')('Franz:feature:announcements'); -let store = null; +export const announcementsStore = new AnnouncementsStore(); export default function initAnnouncements(stores, actions) { // const { features } = stores; @@ -19,15 +17,10 @@ export default function initAnnouncements(stores, actions) { (isEnabled) => { if (isEnabled) { debug('Initializing `announcements` feature'); - store = new AnnouncementsStore(stores, api, actions, state); - store.initialize(); - runInAction(() => { state.isFeatureActive = true; }); - } else if (store) { + announcementsStore.start(stores, actions); + } else if (announcementsStore.isFeatureActive) { debug('Disabling `announcements` feature'); - runInAction(() => { state.isFeatureActive = false; }); - store.teardown(); - store = null; - resetState(); // Reset state to default + announcementsStore.stop(); } }, { 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 @@ -import { observable } from 'mobx'; - -const defaultState = { - announcement: null, - currentVersion: null, - lastUsedVersion: null, - isAnnouncementVisible: false, - isFeatureActive: false, -}; - -export const announcementsState = observable(defaultState); - -export function resetState() { - Object.assign(announcementsState, defaultState); -} - -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 @@ import { action, observable, reaction } from 'mobx'; import semver from 'semver'; - -import Request from '../../stores/lib/Request'; -import Store from '../../stores/lib/Store'; +import { FeatureStore } from '../utils/FeatureStore'; +import { getAnnouncementRequest, getCurrentVersionRequest } from './api'; const debug = require('debug')('Franz:feature:announcements:store'); -export class AnnouncementsStore extends Store { - @observable getCurrentVersion = new Request(this.api, 'getCurrentVersion'); +export class AnnouncementsStore extends FeatureStore { - @observable getAnnouncement = new Request(this.api, 'getAnnouncementForVersion'); + @observable announcement = null; - constructor(stores, api, actions, state) { - super(stores, api, actions); - this.state = state; - } + @observable currentVersion = null; + + @observable lastUsedVersion = null; + + @observable isAnnouncementVisible = false; - async setup() { + @observable isFeatureActive = false; + + async start(stores, actions) { + debug('AnnouncementsStore::start'); + this.stores = stores; + this.actions = actions; await this.fetchLastUsedVersion(); await this.fetchCurrentVersion(); await this.fetchReleaseAnnouncement(); this.showAnnouncementIfNotSeenYet(); this.actions.announcements.show.listen(this._showAnnouncement.bind(this)); + this.isFeatureActive = true; + } + + stop() { + debug('AnnouncementsStore::stop'); + this.isFeatureActive = false; + this.isAnnouncementVisible = false; } // ====== PUBLIC ====== @@ -35,14 +46,14 @@ export class AnnouncementsStore extends Store { async fetchCurrentVersion() { debug('getting current version from api'); - const version = await this.getCurrentVersion.execute(); + const version = await getCurrentVersionRequest.execute(); this._setCurrentVersion(version); } async fetchReleaseAnnouncement() { debug('getting release announcement from api'); try { - const announcement = await this.getAnnouncement.execute(this.state.currentVersion); + const announcement = await getAnnouncementRequest.execute(this.currentVersion); this._setAnnouncement(announcement); } catch (error) { this._setAnnouncement(null); @@ -50,7 +61,7 @@ export class AnnouncementsStore extends Store { } showAnnouncementIfNotSeenYet() { - const { announcement, currentVersion, lastUsedVersion } = this.state; + const { announcement, currentVersion, lastUsedVersion } = this; if (announcement && semver.gt(currentVersion, lastUsedVersion)) { debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); this._showAnnouncement(); @@ -64,21 +75,21 @@ export class AnnouncementsStore extends Store { @action _setCurrentVersion(version) { debug(`setting current version to ${version}`); - this.state.currentVersion = version; + this.currentVersion = version; } @action _setLastUsedVersion(version) { debug(`setting last used version to ${version}`); - this.state.lastUsedVersion = version; + this.lastUsedVersion = version; } @action _setAnnouncement(announcement) { debug(`setting announcement to ${announcement}`); - this.state.announcement = announcement; + this.announcement = announcement; } @action _showAnnouncement() { - this.state.isAnnouncementVisible = true; + this.isAnnouncementVisible = true; this.actions.service.blurActive(); const dispose = reaction( () => this.stores.services.active, @@ -90,6 +101,6 @@ export class AnnouncementsStore extends Store { } @action _hideAnnouncement() { - this.state.isAnnouncementVisible = false; + this.isAnnouncementVisible = false; } } 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 @@ -3097,6 +3097,24 @@ ], "path": "src/features/announcements/Component.json" }, + { + "descriptors": [ + { + "defaultMessage": "!!!What's new in Franz {version}?", + "end": { + "column": 3, + "line": 14 + }, + "file": "src/features/announcements/components/AnnouncementScreen.js", + "id": "feature.announcements.headline", + "start": { + "column": 12, + "line": 11 + } + } + ], + "path": "src/features/announcements/components/AnnouncementScreen.json" + }, { "descriptors": [ { 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 @@ +[ + { + "id": "feature.announcements.headline", + "defaultMessage": "!!!What's new in Franz {version}?", + "file": "src/features/announcements/components/AnnouncementScreen.js", + "start": { + "line": 11, + "column": 12 + }, + "end": { + "line": 14, + "column": 3 + } + } +] \ No newline at end of file -- cgit v1.2.3-54-g00ecf