From eaf4aff646eed56e65c8dd8e70143ab5634ad4b4 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 11 Apr 2019 16:44:16 +0200 Subject: WIP: announcement feature and workspace fixes --- src/features/announcements/actions.js | 4 +- src/features/announcements/api.js | 18 +- .../announcements/components/AnnouncementScreen.js | 152 ++++++++++++--- src/features/announcements/store.js | 151 +++++++++------ src/features/utils/FeatureStore.js | 29 ++- src/features/workspaces/store.js | 18 +- src/i18n/locales/defaultMessages.json | 6 +- src/i18n/locales/en-US.json | 6 +- .../src/features/announcements/Component.json | 4 +- .../components/AnnouncementScreen.json | 8 +- src/i18n/messages/src/lib/Menu.json | 214 ++++++++++----------- src/lib/Menu.js | 15 +- src/stores/index.js | 4 + 13 files changed, 405 insertions(+), 224 deletions(-) (limited to 'src') diff --git a/src/features/announcements/actions.js b/src/features/announcements/actions.js index 68b262ded..bab496314 100644 --- a/src/features/announcements/actions.js +++ b/src/features/announcements/actions.js @@ -2,7 +2,9 @@ import PropTypes from 'prop-types'; import { createActionsFromDefinitions } from '../../actions/lib/actions'; export const announcementActions = createActionsFromDefinitions({ - show: {}, + show: { + targetVersion: PropTypes.string, + }, }, PropTypes.checkPropTypes); export default announcementActions; diff --git a/src/features/announcements/api.js b/src/features/announcements/api.js index 09fcb8235..a581bd8de 100644 --- a/src/features/announcements/api.js +++ b/src/features/announcements/api.js @@ -1,5 +1,6 @@ import { remote } from 'electron'; import Request from '../../stores/lib/Request'; +import { API, API_VERSION } from '../../environment'; const debug = require('debug')('Franz:feature:announcements:api'); @@ -9,15 +10,24 @@ export const announcementsApi = { return Promise.resolve(remote.app.getVersion()); }, - async getAnnouncementForVersion(version) { - debug('fetching release announcement from Github'); + async getChangelog(version) { + debug('fetching release changelog from Github'); const url = `https://api.github.com/repos/meetfranz/franz/releases/tags/v${version}`; const request = await window.fetch(url, { method: 'GET' }); - if (!request.ok) throw request; + if (!request.ok) return null; const data = await request.json(); return data.body; }, + + async getAnnouncement(version) { + debug('fetching release announcement from api'); + const url = `${API}/${API_VERSION}/announcements/${version}`; + const response = await window.fetch(url, { method: 'GET' }); + if (!response.ok) return null; + return response.json(); + }, }; export const getCurrentVersionRequest = new Request(announcementsApi, 'getCurrentVersion'); -export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncementForVersion'); +export const getChangelogRequest = new Request(announcementsApi, 'getChangelog'); +export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncement'); diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js index 5b3e7aeaa..2d5efc396 100644 --- a/src/features/announcements/components/AnnouncementScreen.js +++ b/src/features/announcements/components/AnnouncementScreen.js @@ -4,27 +4,29 @@ 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 { Button } from '@meetfranz/forms'; + import { announcementsStore } from '../index'; +import UIStore from '../../../stores/UIStore'; const messages = defineMessages({ headline: { - id: 'feature.announcements.headline', - defaultMessage: '!!!What\'s new in Franz {version}?', + id: 'feature.announcements.changelog.headline', + defaultMessage: '!!!Changes in Franz {version}', }, }); +const smallScreen = '1000px'; + 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', + width: '100%', + height: '100%', + overflowY: 'auto', }, headline: { color: theme.colorHeadline, @@ -33,7 +35,76 @@ const styles = theme => ({ 'text-align': 'center', 'line-height': '1.3em', }, - body: { + announcement: { + height: '100vh', + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + }, + main: { + flexGrow: 1, + '& h1': { + marginTop: 40, + fontSize: 50, + color: theme.styleTypes.primary.accent, + textAlign: 'center', + [`@media(min-width: ${smallScreen})`]: { + marginTop: 75, + }, + }, + '& h2': { + fontSize: 24, + fontWeight: 300, + color: theme.colorText, + textAlign: 'center', + }, + }, + mainBody: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: 'calc(100% - 80px)', + height: 'auto', + margin: '0 auto', + [`@media(min-width: ${smallScreen})`]: { + flexDirection: 'row', + justifyContent: 'center', + }, + }, + mainImage: { + minWidth: 250, + maxWidth: 400, + margin: '0 auto', + marginBottom: 40, + '& img': { + width: '100%', + }, + [`@media(min-width: ${smallScreen})`]: { + margin: 0, + }, + }, + mainText: { + height: 'auto', + maxWidth: 600, + textAlign: 'center', + '& p': { + lineHeight: '1.5em', + }, + [`@media(min-width: ${smallScreen})`]: { + textAlign: 'left', + }, + }, + mainCtaButton: { + textAlign: 'center', + marginTop: 40, + [`@media(min-width: ${smallScreen})`]: { + textAlign: 'left', + }, + }, + spotlight: { + height: 'auto', + }, + changelog: { '& h3': { fontSize: '24px', margin: '1.5em 0 1em 0', @@ -45,10 +116,13 @@ const styles = theme => ({ }); -@inject('actions') @injectSheet(styles) @observer +@inject('stores', 'actions') @injectSheet(styles) @observer class AnnouncementScreen extends Component { static propTypes = { classes: PropTypes.object.isRequired, + stores: PropTypes.shape({ + ui: PropTypes.instanceOf(UIStore).isRequired, + }).isRequired, }; static contextTypes = { @@ -56,21 +130,55 @@ class AnnouncementScreen extends Component { }; render() { - const { classes } = this.props; + const { classes, stores } = this.props; const { intl } = this.context; + const { changelog, announcement } = announcementsStore; + const themeImage = stores.ui.isDarkThemeActive ? 'dark' : 'light'; return (
-

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

-
+
+
+

{announcement.main.headline}

+

{announcement.main.subHeadline}

+
+
+ +
+
+

+

+
+
+
+
+ {announcement.spotlight && ( +
+

{announcement.spotlight.title}

+
+ )} +
+ {changelog && ( +
+

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

+
+
+ )}
); } diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js index c59700926..d4fb0a52c 100644 --- a/src/features/announcements/store.js +++ b/src/features/announcements/store.js @@ -1,96 +1,93 @@ -import { action, observable, reaction } from 'mobx'; +import { + action, + computed, + observable, + reaction, +} from 'mobx'; import semver from 'semver'; +import localStorage from 'mobx-localstorage'; + import { FeatureStore } from '../utils/FeatureStore'; -import { getAnnouncementRequest, getCurrentVersionRequest } from './api'; +import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api'; +import { announcementActions } from './actions'; + +const LOCAL_STORAGE_KEY = 'announcements'; const debug = require('debug')('Franz:feature:announcements:store'); export class AnnouncementsStore extends FeatureStore { - - @observable announcement = null; - - @observable currentVersion = null; - - @observable lastUsedVersion = null; + @observable targetVersion = null; @observable isAnnouncementVisible = false; @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; + @computed get changelog() { + return getChangelogRequest.result; } - stop() { - debug('AnnouncementsStore::stop'); - this.isFeatureActive = false; - this.isAnnouncementVisible = false; + @computed get announcement() { + return getAnnouncementRequest.result; } - // ====== PUBLIC ====== - - async fetchLastUsedVersion() { - debug('getting last used version from local storage'); - const lastUsedVersion = window.localStorage.getItem('lastUsedVersion'); - this._setLastUsedVersion(lastUsedVersion == null ? '0.0.0' : lastUsedVersion); + @computed get settings() { + return localStorage.getItem(LOCAL_STORAGE_KEY) || {}; } - async fetchCurrentVersion() { - debug('getting current version from api'); - const version = await getCurrentVersionRequest.execute(); - this._setCurrentVersion(version); + @computed get lastSeenAnnouncementVersion() { + return this.settings.lastSeenAnnouncementVersion || null; } - async fetchReleaseAnnouncement() { - debug('getting release announcement from api'); - try { - const announcement = await getAnnouncementRequest.execute(this.currentVersion); - this._setAnnouncement(announcement); - } catch (error) { - this._setAnnouncement(null); - } + @computed get currentVersion() { + return getCurrentVersionRequest.result; } - showAnnouncementIfNotSeenYet() { - const { announcement, currentVersion, lastUsedVersion } = this; - if (announcement && semver.gt(currentVersion, lastUsedVersion)) { - debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); - this._showAnnouncement(); - } else { - debug(`${currentVersion} >= ${lastUsedVersion}: announcement is hidden`); - this._hideAnnouncement(); - } + @computed get isNewUser() { + return this.stores.settings.stats.appStarts <= 1; } - // ====== PRIVATE ====== + async start(stores, actions) { + debug('AnnouncementsStore::start'); + this.stores = stores; + this.actions = actions; + getCurrentVersionRequest.execute(); - @action _setCurrentVersion(version) { - debug(`setting current version to ${version}`); - this.currentVersion = version; - } + this._registerActions([ + [announcementActions.show, this._showAnnouncement], + ]); - @action _setLastUsedVersion(version) { - debug(`setting last used version to ${version}`); - this.lastUsedVersion = version; + this._registerReactions([ + this._fetchAnnouncements, + this._showAnnouncementToUsersWhoUpdatedApp, + ]); + this.isFeatureActive = true; } - @action _setAnnouncement(announcement) { - debug(`setting announcement to ${announcement}`); - this.announcement = announcement; + stop() { + super.stop(); + debug('AnnouncementsStore::stop'); + this.isFeatureActive = false; + this.isAnnouncementVisible = false; } - @action _showAnnouncement() { + // ======= HELPERS ======= // + + _updateSettings = (changes) => { + localStorage.setItem(LOCAL_STORAGE_KEY, { + ...this.settings, + ...changes, + }); + }; + + // ======= ACTIONS ======= // + + @action _showAnnouncement = ({ targetVersion } = {}) => { + this.targetVersion = targetVersion || this.currentVersion; this.isAnnouncementVisible = true; this.actions.service.blurActive(); + this._updateSettings({ + lastSeenAnnouncementVersion: this.currentVersion, + }); const dispose = reaction( () => this.stores.services.active, () => { @@ -98,9 +95,37 @@ export class AnnouncementsStore extends FeatureStore { dispose(); }, ); - } + }; @action _hideAnnouncement() { this.isAnnouncementVisible = false; } + + // ======= REACTIONS ======== + + _showAnnouncementToUsersWhoUpdatedApp = () => { + const { announcement, isNewUser } = this; + console.log(announcement, isNewUser); + // Check if there is an announcement and on't show announcements to new users + if (!announcement || isNewUser) return; + + this._showAnnouncement(); + + // Check if the user has already used current version (= has seen the announcement) + // const { currentVersion, lastSeenAnnouncementVersion } = this; + // if (semver.gt(currentVersion, lastSeenAnnouncementVersion)) { + // debug(`${currentVersion} < ${lastSeenAnnouncementVersion}: announcement is shown`); + // this._showAnnouncement(); + // } else { + // debug(`${currentVersion} >= ${lastSeenAnnouncementVersion}: announcement is hidden`); + // this._hideAnnouncement(); + // } + }; + + _fetchAnnouncements = () => { + const targetVersion = this.targetVersion || this.currentVersion; + if (!targetVersion) return; + getChangelogRequest.execute('5.0.1'); + getAnnouncementRequest.execute('5.1.0'); + } } diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js index 66b66a104..48962561d 100644 --- a/src/features/utils/FeatureStore.js +++ b/src/features/utils/FeatureStore.js @@ -5,17 +5,38 @@ export class FeatureStore { _reactions = null; - _listenToActions(actions) { - if (this._actions) this._actions.forEach(a => a[0].off(a[1])); + _registerActions(actions) { this._actions = []; actions.forEach(a => this._actions.push(a)); + this._startListeningToActions(); + } + + _startListeningToActions() { + this._stopListeningToActions(); this._actions.forEach(a => a[0].listen(a[1])); } - _startReactions(reactions) { - if (this._reactions) this._reactions.forEach(r => r.stop()); + _stopListeningToActions() { + this._actions.forEach(a => a[0].off(a[1])); + } + + _registerReactions(reactions) { this._reactions = []; reactions.forEach(r => this._reactions.push(new Reaction(r))); + this._startReactions(); + } + + _startReactions() { + this._stopReactions(); this._reactions.forEach(r => r.start()); } + + _stopReactions() { + this._reactions.forEach(r => r.stop()); + } + + stop() { + this._stopListeningToActions(); + this._stopReactions(); + } } diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index ea601700e..4841a4e08 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js @@ -51,12 +51,16 @@ export default class WorkspacesStore extends FeatureStore { return getUserWorkspacesRequest.wasExecuted && this.workspaces.length > 0; } + @computed get isUserAllowedToUseFeature() { + return !this.isPremiumUpgradeRequired; + } + start(stores, actions) { debug('WorkspacesStore::start'); this.stores = stores; this.actions = actions; - this._listenToActions([ + this._registerActions([ [workspaceActions.edit, this._edit], [workspaceActions.create, this._create], [workspaceActions.delete, this._delete], @@ -67,7 +71,7 @@ export default class WorkspacesStore extends FeatureStore { [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings], ]); - this._startReactions([ + this._registerReactions([ this._setWorkspaceBeingEditedReaction, this._setActiveServiceOnWorkspaceSwitchReaction, this._setFeatureEnabledReaction, @@ -75,6 +79,7 @@ export default class WorkspacesStore extends FeatureStore { this._activateLastUsedWorkspaceReaction, this._openDrawerWithSettingsReaction, this._cleanupInvalidServiceReferences, + this._disableActionsForFreeUser, ]); getUserWorkspacesRequest.execute(); @@ -82,6 +87,7 @@ export default class WorkspacesStore extends FeatureStore { } stop() { + super.stop(); debug('WorkspacesStore::stop'); this.isFeatureActive = false; this.activeWorkspace = null; @@ -273,4 +279,12 @@ export default class WorkspacesStore extends FeatureStore { getUserWorkspacesRequest.execute(); } }; + + _disableActionsForFreeUser = () => { + if (!this.isUserAllowedToUseFeature) { + this._stopListeningToActions(); + } else { + this._startListeningToActions(); + } + } } diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 1dd31324e..5ad7a8bd8 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3088,7 +3088,7 @@ "line": 14 }, "file": "src/features/announcements/Component.js", - "id": "feature.announcements.headline", + "id": "feature.announcements.changelog.headline", "start": { "column": 12, "line": 11 @@ -3106,7 +3106,7 @@ "line": 14 }, "file": "src/features/announcements/components/AnnouncementScreen.js", - "id": "feature.announcements.headline", + "id": "feature.announcements.changelog.headline", "start": { "column": 12, "line": 11 @@ -4470,4 +4470,4 @@ ], "path": "src/lib/Menu.json" } -] \ No newline at end of file +] diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 13775d758..958b6fb6a 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -1,7 +1,7 @@ { "app.errorHandler.action": "Reload", "app.errorHandler.headline": "Something went wrong", - "feature.announcements.headline": "What's new in Franz {version}?", + "feature.announcements.changelog.headline": "Changes in Franz {version}", "feature.delayApp.action": "Get a Franz Supporter License", "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", "feature.delayApp.text": "Franz will continue in {seconds} seconds.", @@ -44,7 +44,7 @@ "login.submit.label": "Sign in", "login.tokenExpired": "Your session expired, please login again.", "menu.app.about": "About Franz", - "menu.app.announcement": "What's new in Franz?", + "menu.app.announcement": "What's new?", "menu.app.hide": "Hide", "menu.app.hideOthers": "Hide Others", "menu.app.quit": "Quit", @@ -319,4 +319,4 @@ "workspaceDrawer.workspaceFeatureInfo": "

Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.

You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.

", "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", "workspaces.switchingIndicator.switchingTo": "Switching to" -} \ No newline at end of file +} diff --git a/src/i18n/messages/src/features/announcements/Component.json b/src/i18n/messages/src/features/announcements/Component.json index 18e1b84c5..c31c35fc7 100644 --- a/src/i18n/messages/src/features/announcements/Component.json +++ b/src/i18n/messages/src/features/announcements/Component.json @@ -1,6 +1,6 @@ [ { - "id": "feature.announcements.headline", + "id": "feature.announcements.changelog.headline", "defaultMessage": "!!!What's new in Franz {version}?", "file": "src/features/announcements/Component.js", "start": { @@ -12,4 +12,4 @@ "column": 3 } } -] \ No newline at end of file +] diff --git a/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json index 225670ee2..874c9dd9d 100644 --- a/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json +++ b/src/i18n/messages/src/features/announcements/components/AnnouncementScreen.json @@ -1,14 +1,14 @@ [ { - "id": "feature.announcements.headline", - "defaultMessage": "!!!What's new in Franz {version}?", + "id": "feature.announcements.changelog.headline", + "defaultMessage": "!!!Changes in Franz {version}", "file": "src/features/announcements/components/AnnouncementScreen.js", "start": { - "line": 11, + "line": 13, "column": 12 }, "end": { - "line": 14, + "line": 16, "column": 3 } } diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index f4cd35582..a2ce34cd4 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Edit", "file": "src/lib/Menu.js", "start": { - "line": 13, + "line": 14, "column": 8 }, "end": { - "line": 16, + "line": 17, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Undo", "file": "src/lib/Menu.js", "start": { - "line": 17, + "line": 18, "column": 8 }, "end": { - "line": 20, + "line": 21, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Redo", "file": "src/lib/Menu.js", "start": { - "line": 21, + "line": 22, "column": 8 }, "end": { - "line": 24, + "line": 25, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Cut", "file": "src/lib/Menu.js", "start": { - "line": 25, + "line": 26, "column": 7 }, "end": { - "line": 28, + "line": 29, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Copy", "file": "src/lib/Menu.js", "start": { - "line": 29, + "line": 30, "column": 8 }, "end": { - "line": 32, + "line": 33, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Paste", "file": "src/lib/Menu.js", "start": { - "line": 33, + "line": 34, "column": 9 }, "end": { - "line": 36, + "line": 37, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Paste And Match Style", "file": "src/lib/Menu.js", "start": { - "line": 37, + "line": 38, "column": 22 }, "end": { - "line": 40, + "line": 41, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Delete", "file": "src/lib/Menu.js", "start": { - "line": 41, + "line": 42, "column": 10 }, "end": { - "line": 44, + "line": 45, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Select All", "file": "src/lib/Menu.js", "start": { - "line": 45, + "line": 46, "column": 13 }, "end": { - "line": 48, + "line": 49, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Speech", "file": "src/lib/Menu.js", "start": { - "line": 49, + "line": 50, "column": 10 }, "end": { - "line": 52, + "line": 53, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Start Speaking", "file": "src/lib/Menu.js", "start": { - "line": 53, + "line": 54, "column": 17 }, "end": { - "line": 56, + "line": 57, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Stop Speaking", "file": "src/lib/Menu.js", "start": { - "line": 57, + "line": 58, "column": 16 }, "end": { - "line": 60, + "line": 61, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Start Dictation", "file": "src/lib/Menu.js", "start": { - "line": 61, + "line": 62, "column": 18 }, "end": { - "line": 64, + "line": 65, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Emoji & Symbols", "file": "src/lib/Menu.js", "start": { - "line": 65, + "line": 66, "column": 16 }, "end": { - "line": 68, + "line": 69, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Actual Size", "file": "src/lib/Menu.js", "start": { - "line": 69, + "line": 70, "column": 13 }, "end": { - "line": 72, + "line": 73, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Zoom In", "file": "src/lib/Menu.js", "start": { - "line": 73, + "line": 74, "column": 10 }, "end": { - "line": 76, + "line": 77, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Zoom Out", "file": "src/lib/Menu.js", "start": { - "line": 77, + "line": 78, "column": 11 }, "end": { - "line": 80, + "line": 81, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Enter Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 81, + "line": 82, "column": 19 }, "end": { - "line": 84, + "line": 85, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Exit Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 85, + "line": 86, "column": 18 }, "end": { - "line": 88, + "line": 89, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Toggle Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 89, + "line": 90, "column": 20 }, "end": { - "line": 92, + "line": 93, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Toggle Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 93, + "line": 94, "column": 18 }, "end": { - "line": 96, + "line": 97, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 97, + "line": 98, "column": 25 }, "end": { - "line": 100, + "line": 101, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 101, + "line": 102, "column": 17 }, "end": { - "line": 104, + "line": 105, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 105, + "line": 106, "column": 15 }, "end": { - "line": 108, + "line": 109, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 109, + "line": 110, "column": 12 }, "end": { - "line": 112, + "line": 113, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 113, + "line": 114, "column": 9 }, "end": { - "line": 116, + "line": 117, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 117, + "line": 118, "column": 13 }, "end": { - "line": 120, + "line": 121, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 121, + "line": 122, "column": 13 }, "end": { - "line": 124, + "line": 125, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 125, + "line": 126, "column": 11 }, "end": { - "line": 128, + "line": 129, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 129, + "line": 130, "column": 7 }, "end": { - "line": 132, + "line": 133, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 133, + "line": 134, "column": 11 }, "end": { - "line": 136, + "line": 137, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 137, + "line": 138, "column": 8 }, "end": { - "line": 140, + "line": 141, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 141, + "line": 142, "column": 8 }, "end": { - "line": 144, + "line": 145, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 145, + "line": 146, "column": 12 }, "end": { - "line": 148, + "line": 149, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 149, + "line": 150, "column": 10 }, "end": { - "line": 152, + "line": 153, "column": 3 } }, @@ -459,11 +459,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 153, + "line": 154, "column": 8 }, "end": { - "line": 156, + "line": 157, "column": 3 } }, @@ -472,24 +472,24 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 157, + "line": 158, "column": 9 }, "end": { - "line": 160, + "line": 161, "column": 3 } }, { "id": "menu.app.announcement", - "defaultMessage": "!!!What's new in Franz?", + "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 161, + "line": 162, "column": 16 }, "end": { - "line": 164, + "line": 165, "column": 3 } }, @@ -498,11 +498,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 165, + "line": 166, "column": 12 }, "end": { - "line": 168, + "line": 169, "column": 3 } }, @@ -511,11 +511,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 169, + "line": 170, "column": 8 }, "end": { - "line": 172, + "line": 173, "column": 3 } }, @@ -524,11 +524,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 173, + "line": 174, "column": 14 }, "end": { - "line": 176, + "line": 177, "column": 3 } }, @@ -537,11 +537,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 177, + "line": 178, "column": 10 }, "end": { - "line": 180, + "line": 181, "column": 3 } }, @@ -550,11 +550,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 181, + "line": 182, "column": 8 }, "end": { - "line": 184, + "line": 185, "column": 3 } }, @@ -563,11 +563,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 185, + "line": 186, "column": 17 }, "end": { - "line": 188, + "line": 189, "column": 3 } }, @@ -576,11 +576,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 189, + "line": 190, "column": 19 }, "end": { - "line": 192, + "line": 193, "column": 3 } }, @@ -589,11 +589,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 193, + "line": 194, "column": 23 }, "end": { - "line": 196, + "line": 197, "column": 3 } }, @@ -602,11 +602,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 197, + "line": 198, "column": 24 }, "end": { - "line": 200, + "line": 201, "column": 3 } }, @@ -615,11 +615,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 201, + "line": 202, "column": 23 }, "end": { - "line": 204, + "line": 205, "column": 3 } }, @@ -628,11 +628,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 205, + "line": 206, "column": 27 }, "end": { - "line": 208, + "line": 209, "column": 3 } }, @@ -641,11 +641,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 209, + "line": 210, "column": 11 }, "end": { - "line": 212, + "line": 213, "column": 3 } }, @@ -654,11 +654,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 213, + "line": 214, "column": 13 }, "end": { - "line": 216, + "line": 217, "column": 3 } }, @@ -667,11 +667,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 217, + "line": 218, "column": 14 }, "end": { - "line": 220, + "line": 221, "column": 3 } }, @@ -680,11 +680,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 221, + "line": 222, "column": 20 }, "end": { - "line": 224, + "line": 225, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 46a347237..3df06e05a 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -6,6 +6,7 @@ import { isMac, ctrlKey, cmdKey } from '../environment'; import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../features/workspaces/index'; import { workspaceActions } from '../features/workspaces/actions'; import { gaEvent } from './analytics'; +import announcementActions from '../features/announcements/actions'; const { app, Menu, dialog } = remote; @@ -160,7 +161,7 @@ const menuItems = defineMessages({ }, announcement: { id: 'menu.app.announcement', - defaultMessage: '!!!What\'s new in Franz?', + defaultMessage: '!!!What\'s new?', }, settings: { id: 'menu.app.settings', @@ -352,8 +353,10 @@ const _templateFactory = intl => [ click() { shell.openExternal('https://meetfranz.com'); }, }, { - label: intl.formatMessage(menuItems.changelog), - click() { shell.openExternal('https://github.com/meetfranz/franz/blob/master/CHANGELOG.md'); }, + label: intl.formatMessage(menuItems.announcement), + click: () => { + announcementActions.show(); + }, }, { type: 'separator', @@ -621,12 +624,6 @@ export default class FranzMenu { label: intl.formatMessage(menuItems.about), role: 'about', }, - { - label: intl.formatMessage(menuItems.announcement), - click: () => { - this.actions.announcements.show(); - }, - }, { type: 'separator', }, diff --git a/src/stores/index.js b/src/stores/index.js index 96b844c95..1912418a2 100644 --- a/src/stores/index.js +++ b/src/stores/index.js @@ -10,6 +10,8 @@ import PaymentStore from './PaymentStore'; import NewsStore from './NewsStore'; import RequestStore from './RequestStore'; import GlobalErrorStore from './GlobalErrorStore'; +import { workspaceStore } from '../features/workspaces'; +import { announcementsStore } from '../features/announcements'; export default (api, actions, router) => { const stores = {}; @@ -27,6 +29,8 @@ export default (api, actions, router) => { news: new NewsStore(stores, api, actions), requests: new RequestStore(stores, api, actions), globalError: new GlobalErrorStore(stores, api, actions), + workspaces: workspaceStore, + announcements: announcementsStore, }); // Initialize all stores Object.keys(stores).forEach((name) => { -- cgit v1.2.3-54-g00ecf