diff options
-rw-r--r-- | package-lock.json | 5 | ||||
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | src/actions/index.js | 2 | ||||
-rw-r--r-- | src/actions/service.js | 1 | ||||
-rw-r--r-- | src/components/layout/AppLayout.js | 4 | ||||
-rw-r--r-- | src/config.js | 1 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 2 | ||||
-rw-r--r-- | src/features/announcements/Component.js | 77 | ||||
-rw-r--r-- | src/features/announcements/actions.js | 8 | ||||
-rw-r--r-- | src/features/announcements/api.js | 19 | ||||
-rw-r--r-- | src/features/announcements/index.js | 37 | ||||
-rw-r--r-- | src/features/announcements/state.js | 17 | ||||
-rw-r--r-- | src/features/announcements/store.js | 95 | ||||
-rw-r--r-- | src/i18n/locales/defaultMessages.json | 115 | ||||
-rw-r--r-- | src/i18n/locales/en-US.json | 2 | ||||
-rw-r--r-- | src/i18n/messages/src/components/layout/AppLayout.json | 24 | ||||
-rw-r--r-- | src/i18n/messages/src/features/announcements/Component.json | 15 | ||||
-rw-r--r-- | src/i18n/messages/src/lib/Menu.json | 73 | ||||
-rw-r--r-- | src/lib/Menu.js | 10 | ||||
-rw-r--r-- | src/stores/FeaturesStore.js | 2 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 6 |
21 files changed, 432 insertions, 84 deletions
diff --git a/package-lock.json b/package-lock.json index 6b87d2432..600d4b7d7 100644 --- a/package-lock.json +++ b/package-lock.json | |||
@@ -12139,6 +12139,11 @@ | |||
12139 | "object-visit": "^1.0.0" | 12139 | "object-visit": "^1.0.0" |
12140 | } | 12140 | } |
12141 | }, | 12141 | }, |
12142 | "marked": { | ||
12143 | "version": "0.6.1", | ||
12144 | "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.1.tgz", | ||
12145 | "integrity": "sha512-+H0L3ibcWhAZE02SKMqmvYsErLo4EAVJxu5h3bHBBDvvjeWXtl92rGUSBYHL2++5Y+RSNgl8dYOAXcYe7lp1fA==" | ||
12146 | }, | ||
12142 | "matchdep": { | 12147 | "matchdep": { |
12143 | "version": "2.0.0", | 12148 | "version": "2.0.0", |
12144 | "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", | 12149 | "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", |
diff --git a/package.json b/package.json index 8f5c2e8c8..7e926139d 100644 --- a/package.json +++ b/package.json | |||
@@ -54,6 +54,7 @@ | |||
54 | "hex-to-rgba": "1.0.2", | 54 | "hex-to-rgba": "1.0.2", |
55 | "jsonwebtoken": "^7.4.1", | 55 | "jsonwebtoken": "^7.4.1", |
56 | "lodash": "^4.17.4", | 56 | "lodash": "^4.17.4", |
57 | "marked": "0.6.1", | ||
57 | "mdi": "^1.9.33", | 58 | "mdi": "^1.9.33", |
58 | "mime-types": "2.1.21", | 59 | "mime-types": "2.1.21", |
59 | "mobx": "5.7.0", | 60 | "mobx": "5.7.0", |
diff --git a/src/actions/index.js b/src/actions/index.js index 00f843cd6..fc525afeb 100644 --- a/src/actions/index.js +++ b/src/actions/index.js | |||
@@ -11,6 +11,7 @@ import payment from './payment'; | |||
11 | import news from './news'; | 11 | import news from './news'; |
12 | import settings from './settings'; | 12 | import settings from './settings'; |
13 | import requests from './requests'; | 13 | import requests from './requests'; |
14 | import announcements from '../features/announcements/actions'; | ||
14 | import workspaces from '../features/workspaces/actions'; | 15 | import workspaces from '../features/workspaces/actions'; |
15 | 16 | ||
16 | const actions = Object.assign({}, { | 17 | const actions = Object.assign({}, { |
@@ -28,5 +29,6 @@ const actions = Object.assign({}, { | |||
28 | 29 | ||
29 | export default Object.assign( | 30 | export default Object.assign( |
30 | defineActions(actions, PropTypes.checkPropTypes), | 31 | defineActions(actions, PropTypes.checkPropTypes), |
32 | { announcements }, | ||
31 | { workspaces }, | 33 | { workspaces }, |
32 | ); | 34 | ); |
diff --git a/src/actions/service.js b/src/actions/service.js index ceaabc31e..ce62560a9 100644 --- a/src/actions/service.js +++ b/src/actions/service.js | |||
@@ -5,6 +5,7 @@ export default { | |||
5 | setActive: { | 5 | setActive: { |
6 | serviceId: PropTypes.string.isRequired, | 6 | serviceId: PropTypes.string.isRequired, |
7 | }, | 7 | }, |
8 | blurActive: {}, | ||
8 | setActiveNext: {}, | 9 | setActiveNext: {}, |
9 | setActivePrev: {}, | 10 | setActivePrev: {}, |
10 | showAddServiceInterface: { | 11 | showAddServiceInterface: { |
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index b7f7722dd..985475c8d 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -14,6 +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 WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; | 18 | import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator'; |
18 | import { workspaceStore } from '../../features/workspaces'; | 19 | import { workspaceStore } from '../../features/workspaces'; |
19 | 20 | ||
@@ -80,6 +81,7 @@ class AppLayout extends Component { | |||
80 | areRequiredRequestsLoading: PropTypes.bool.isRequired, | 81 | areRequiredRequestsLoading: PropTypes.bool.isRequired, |
81 | darkMode: PropTypes.bool.isRequired, | 82 | darkMode: PropTypes.bool.isRequired, |
82 | isDelayAppScreenVisible: PropTypes.bool.isRequired, | 83 | isDelayAppScreenVisible: PropTypes.bool.isRequired, |
84 | isAnnouncementVisible: PropTypes.bool.isRequired, | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | static defaultProps = { | 87 | static defaultProps = { |
@@ -111,6 +113,7 @@ class AppLayout extends Component { | |||
111 | areRequiredRequestsLoading, | 113 | areRequiredRequestsLoading, |
112 | darkMode, | 114 | darkMode, |
113 | isDelayAppScreenVisible, | 115 | isDelayAppScreenVisible, |
116 | isAnnouncementVisible, | ||
114 | } = this.props; | 117 | } = this.props; |
115 | 118 | ||
116 | const { intl } = this.context; | 119 | const { intl } = this.context; |
@@ -186,6 +189,7 @@ class AppLayout extends Component { | |||
186 | {isDelayAppScreenVisible && (<DelayApp />)} | 189 | {isDelayAppScreenVisible && (<DelayApp />)} |
187 | <BasicAuth /> | 190 | <BasicAuth /> |
188 | <ShareFranz /> | 191 | <ShareFranz /> |
192 | {isAnnouncementVisible && (<AnnouncementScreen />)} | ||
189 | {services} | 193 | {services} |
190 | </div> | 194 | </div> |
191 | </div> | 195 | </div> |
diff --git a/src/config.js b/src/config.js index 242675762..e7745b61d 100644 --- a/src/config.js +++ b/src/config.js | |||
@@ -41,6 +41,7 @@ export const DEFAULT_FEATURES_CONFIG = { | |||
41 | }, | 41 | }, |
42 | isServiceProxyEnabled: false, | 42 | isServiceProxyEnabled: false, |
43 | isServiceProxyPremiumFeature: true, | 43 | isServiceProxyPremiumFeature: true, |
44 | isAnnouncementsEnabled: true, | ||
44 | isWorkspacePremiumFeature: true, | 45 | isWorkspacePremiumFeature: true, |
45 | isWorkspaceEnabled: false, | 46 | isWorkspaceEnabled: false, |
46 | }; | 47 | }; |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 2d855c78f..0357f63bd 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -20,6 +20,7 @@ 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 { workspaceActions } from '../../features/workspaces/actions'; | 24 | import { workspaceActions } from '../../features/workspaces/actions'; |
24 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; | 25 | import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; |
25 | import { workspaceStore } from '../../features/workspaces'; | 26 | import { workspaceStore } from '../../features/workspaces'; |
@@ -149,6 +150,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
149 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} | 150 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} |
150 | darkMode={settings.all.app.darkMode} | 151 | darkMode={settings.all.app.darkMode} |
151 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} | 152 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} |
153 | isAnnouncementVisible={announcementsState.isAnnouncementVisible} | ||
152 | > | 154 | > |
153 | {React.Children.count(children) > 0 ? children : null} | 155 | {React.Children.count(children) > 0 ? children : null} |
154 | </AppLayout> | 156 | </AppLayout> |
diff --git a/src/features/announcements/Component.js b/src/features/announcements/Component.js new file mode 100644 index 000000000..5d95f5d84 --- /dev/null +++ b/src/features/announcements/Component.js | |||
@@ -0,0 +1,77 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import marked from 'marked'; | ||
3 | import PropTypes from 'prop-types'; | ||
4 | import { inject, observer } from 'mobx-react'; | ||
5 | import { defineMessages, intlShape } from 'react-intl'; | ||
6 | import injectSheet from 'react-jss'; | ||
7 | import { themeSidebarWidth } from '@meetfranz/theme/lib/themes/legacy'; | ||
8 | import state from './state'; | ||
9 | |||
10 | const messages = defineMessages({ | ||
11 | headline: { | ||
12 | id: 'feature.announcements.headline', | ||
13 | defaultMessage: '!!!What\'s new in Franz {version}?', | ||
14 | }, | ||
15 | }); | ||
16 | |||
17 | const styles = theme => ({ | ||
18 | container: { | ||
19 | background: theme.colorBackground, | ||
20 | position: 'absolute', | ||
21 | top: 0, | ||
22 | zIndex: 140, | ||
23 | width: `calc(100% - ${themeSidebarWidth})`, | ||
24 | display: 'flex', | ||
25 | 'flex-direction': 'column', | ||
26 | 'align-items': 'center', | ||
27 | 'justify-content': 'center', | ||
28 | }, | ||
29 | headline: { | ||
30 | color: theme.colorHeadline, | ||
31 | margin: [25, 0, 40], | ||
32 | 'max-width': 500, | ||
33 | 'text-align': 'center', | ||
34 | 'line-height': '1.3em', | ||
35 | }, | ||
36 | body: { | ||
37 | '& h3': { | ||
38 | fontSize: '24px', | ||
39 | margin: '1.5em 0 1em 0', | ||
40 | }, | ||
41 | '& li': { | ||
42 | marginBottom: '1em', | ||
43 | }, | ||
44 | }, | ||
45 | }); | ||
46 | |||
47 | |||
48 | @inject('actions') @injectSheet(styles) @observer | ||
49 | class AnnouncementScreen extends Component { | ||
50 | static propTypes = { | ||
51 | classes: PropTypes.object.isRequired, | ||
52 | }; | ||
53 | |||
54 | static contextTypes = { | ||
55 | intl: intlShape, | ||
56 | }; | ||
57 | |||
58 | render() { | ||
59 | const { classes } = this.props; | ||
60 | const { intl } = this.context; | ||
61 | return ( | ||
62 | <div className={`${classes.container}`}> | ||
63 | <h1 className={classes.headline}> | ||
64 | {intl.formatMessage(messages.headline, { version: state.currentVersion })} | ||
65 | </h1> | ||
66 | <div | ||
67 | className={classes.body} | ||
68 | dangerouslySetInnerHTML={{ | ||
69 | __html: marked(state.announcement, { sanitize: true }), | ||
70 | }} | ||
71 | /> | ||
72 | </div> | ||
73 | ); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | export default AnnouncementScreen; | ||
diff --git a/src/features/announcements/actions.js b/src/features/announcements/actions.js new file mode 100644 index 000000000..68b262ded --- /dev/null +++ b/src/features/announcements/actions.js | |||
@@ -0,0 +1,8 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
3 | |||
4 | export const announcementActions = createActionsFromDefinitions({ | ||
5 | show: {}, | ||
6 | }, PropTypes.checkPropTypes); | ||
7 | |||
8 | export default announcementActions; | ||
diff --git a/src/features/announcements/api.js b/src/features/announcements/api.js new file mode 100644 index 000000000..ec16066a6 --- /dev/null +++ b/src/features/announcements/api.js | |||
@@ -0,0 +1,19 @@ | |||
1 | import { remote } from 'electron'; | ||
2 | |||
3 | const debug = require('debug')('Franz:feature:announcements:api'); | ||
4 | |||
5 | export default { | ||
6 | async getCurrentVersion() { | ||
7 | debug('getting current version of electron app'); | ||
8 | return Promise.resolve(remote.app.getVersion()); | ||
9 | }, | ||
10 | |||
11 | async getAnnouncementForVersion(version) { | ||
12 | debug('fetching release announcement from Github'); | ||
13 | const url = `https://api.github.com/repos/meetfranz/franz/releases/tags/v${version}`; | ||
14 | const request = await window.fetch(url, { method: 'GET' }); | ||
15 | if (!request.ok) throw request; | ||
16 | const data = await request.json(); | ||
17 | return data.body; | ||
18 | }, | ||
19 | }; | ||
diff --git a/src/features/announcements/index.js b/src/features/announcements/index.js new file mode 100644 index 000000000..5ea74e0af --- /dev/null +++ b/src/features/announcements/index.js | |||
@@ -0,0 +1,37 @@ | |||
1 | import { reaction, runInAction } from 'mobx'; | ||
2 | import { AnnouncementsStore } from './store'; | ||
3 | import api from './api'; | ||
4 | import state, { resetState } from './state'; | ||
5 | |||
6 | const debug = require('debug')('Franz:feature:announcements'); | ||
7 | |||
8 | let store = null; | ||
9 | |||
10 | export default function initAnnouncements(stores, actions) { | ||
11 | // const { features } = stores; | ||
12 | |||
13 | // Toggle workspace feature | ||
14 | reaction( | ||
15 | () => ( | ||
16 | true | ||
17 | // features.features.isAnnouncementsEnabled | ||
18 | ), | ||
19 | (isEnabled) => { | ||
20 | if (isEnabled) { | ||
21 | debug('Initializing `announcements` feature'); | ||
22 | store = new AnnouncementsStore(stores, api, actions, state); | ||
23 | store.initialize(); | ||
24 | runInAction(() => { state.isFeatureActive = true; }); | ||
25 | } else if (store) { | ||
26 | debug('Disabling `announcements` feature'); | ||
27 | runInAction(() => { state.isFeatureActive = false; }); | ||
28 | store.teardown(); | ||
29 | store = null; | ||
30 | resetState(); // Reset state to default | ||
31 | } | ||
32 | }, | ||
33 | { | ||
34 | fireImmediately: true, | ||
35 | }, | ||
36 | ); | ||
37 | } | ||
diff --git a/src/features/announcements/state.js b/src/features/announcements/state.js new file mode 100644 index 000000000..81b632253 --- /dev/null +++ b/src/features/announcements/state.js | |||
@@ -0,0 +1,17 @@ | |||
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 new file mode 100644 index 000000000..004a44062 --- /dev/null +++ b/src/features/announcements/store.js | |||
@@ -0,0 +1,95 @@ | |||
1 | import { action, observable, reaction } from 'mobx'; | ||
2 | import semver from 'semver'; | ||
3 | |||
4 | import Request from '../../stores/lib/Request'; | ||
5 | import Store from '../../stores/lib/Store'; | ||
6 | |||
7 | const debug = require('debug')('Franz:feature:announcements:store'); | ||
8 | |||
9 | export class AnnouncementsStore extends Store { | ||
10 | @observable getCurrentVersion = new Request(this.api, 'getCurrentVersion'); | ||
11 | |||
12 | @observable getAnnouncement = new Request(this.api, 'getAnnouncementForVersion'); | ||
13 | |||
14 | constructor(stores, api, actions, state) { | ||
15 | super(stores, api, actions); | ||
16 | this.state = state; | ||
17 | } | ||
18 | |||
19 | async setup() { | ||
20 | await this.fetchLastUsedVersion(); | ||
21 | await this.fetchCurrentVersion(); | ||
22 | await this.fetchReleaseAnnouncement(); | ||
23 | this.showAnnouncementIfNotSeenYet(); | ||
24 | |||
25 | this.actions.announcements.show.listen(this._showAnnouncement.bind(this)); | ||
26 | } | ||
27 | |||
28 | // ====== PUBLIC ====== | ||
29 | |||
30 | async fetchLastUsedVersion() { | ||
31 | debug('getting last used version from local storage'); | ||
32 | const lastUsedVersion = window.localStorage.getItem('lastUsedVersion'); | ||
33 | this._setLastUsedVersion(lastUsedVersion == null ? '0.0.0' : lastUsedVersion); | ||
34 | } | ||
35 | |||
36 | async fetchCurrentVersion() { | ||
37 | debug('getting current version from api'); | ||
38 | const version = await this.getCurrentVersion.execute(); | ||
39 | this._setCurrentVersion(version); | ||
40 | } | ||
41 | |||
42 | async fetchReleaseAnnouncement() { | ||
43 | debug('getting release announcement from api'); | ||
44 | try { | ||
45 | const announcement = await this.getAnnouncement.execute(this.state.currentVersion); | ||
46 | this._setAnnouncement(announcement); | ||
47 | } catch (error) { | ||
48 | this._setAnnouncement(null); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | showAnnouncementIfNotSeenYet() { | ||
53 | const { announcement, currentVersion, lastUsedVersion } = this.state; | ||
54 | if (announcement && semver.gt(currentVersion, lastUsedVersion)) { | ||
55 | debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); | ||
56 | this._showAnnouncement(); | ||
57 | } else { | ||
58 | debug(`${currentVersion} >= ${lastUsedVersion}: announcement is hidden`); | ||
59 | this._hideAnnouncement(); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | // ====== PRIVATE ====== | ||
64 | |||
65 | @action _setCurrentVersion(version) { | ||
66 | debug(`setting current version to ${version}`); | ||
67 | this.state.currentVersion = version; | ||
68 | } | ||
69 | |||
70 | @action _setLastUsedVersion(version) { | ||
71 | debug(`setting last used version to ${version}`); | ||
72 | this.state.lastUsedVersion = version; | ||
73 | } | ||
74 | |||
75 | @action _setAnnouncement(announcement) { | ||
76 | debug(`setting announcement to ${announcement}`); | ||
77 | this.state.announcement = announcement; | ||
78 | } | ||
79 | |||
80 | @action _showAnnouncement() { | ||
81 | this.state.isAnnouncementVisible = true; | ||
82 | this.actions.service.blurActive(); | ||
83 | const dispose = reaction( | ||
84 | () => this.stores.services.active, | ||
85 | () => { | ||
86 | this._hideAnnouncement(); | ||
87 | dispose(); | ||
88 | }, | ||
89 | ); | ||
90 | } | ||
91 | |||
92 | @action _hideAnnouncement() { | ||
93 | this.state.isAnnouncementVisible = false; | ||
94 | } | ||
95 | } | ||
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 65799b614..698698515 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json | |||
@@ -625,78 +625,78 @@ | |||
625 | "defaultMessage": "!!!Your services have been updated.", | 625 | "defaultMessage": "!!!Your services have been updated.", |
626 | "end": { | 626 | "end": { |
627 | "column": 3, | 627 | "column": 3, |
628 | "line": 28 | 628 | "line": 29 |
629 | }, | 629 | }, |
630 | "file": "src/components/layout/AppLayout.js", | 630 | "file": "src/components/layout/AppLayout.js", |
631 | "id": "infobar.servicesUpdated", | 631 | "id": "infobar.servicesUpdated", |
632 | "start": { | 632 | "start": { |
633 | "column": 19, | 633 | "column": 19, |
634 | "line": 25 | 634 | "line": 26 |
635 | } | 635 | } |
636 | }, | 636 | }, |
637 | { | 637 | { |
638 | "defaultMessage": "!!!A new update for Franz is available.", | 638 | "defaultMessage": "!!!A new update for Franz is available.", |
639 | "end": { | 639 | "end": { |
640 | "column": 3, | 640 | "column": 3, |
641 | "line": 32 | 641 | "line": 33 |
642 | }, | 642 | }, |
643 | "file": "src/components/layout/AppLayout.js", | 643 | "file": "src/components/layout/AppLayout.js", |
644 | "id": "infobar.updateAvailable", | 644 | "id": "infobar.updateAvailable", |
645 | "start": { | 645 | "start": { |
646 | "column": 19, | 646 | "column": 19, |
647 | "line": 29 | 647 | "line": 30 |
648 | } | 648 | } |
649 | }, | 649 | }, |
650 | { | 650 | { |
651 | "defaultMessage": "!!!Reload services", | 651 | "defaultMessage": "!!!Reload services", |
652 | "end": { | 652 | "end": { |
653 | "column": 3, | 653 | "column": 3, |
654 | "line": 36 | 654 | "line": 37 |
655 | }, | 655 | }, |
656 | "file": "src/components/layout/AppLayout.js", | 656 | "file": "src/components/layout/AppLayout.js", |
657 | "id": "infobar.buttonReloadServices", | 657 | "id": "infobar.buttonReloadServices", |
658 | "start": { | 658 | "start": { |
659 | "column": 24, | 659 | "column": 24, |
660 | "line": 33 | 660 | "line": 34 |
661 | } | 661 | } |
662 | }, | 662 | }, |
663 | { | 663 | { |
664 | "defaultMessage": "!!!Changelog", | 664 | "defaultMessage": "!!!Changelog", |
665 | "end": { | 665 | "end": { |
666 | "column": 3, | 666 | "column": 3, |
667 | "line": 40 | 667 | "line": 41 |
668 | }, | 668 | }, |
669 | "file": "src/components/layout/AppLayout.js", | 669 | "file": "src/components/layout/AppLayout.js", |
670 | "id": "infobar.buttonChangelog", | 670 | "id": "infobar.buttonChangelog", |
671 | "start": { | 671 | "start": { |
672 | "column": 13, | 672 | "column": 13, |
673 | "line": 37 | 673 | "line": 38 |
674 | } | 674 | } |
675 | }, | 675 | }, |
676 | { | 676 | { |
677 | "defaultMessage": "!!!Restart & install update", | 677 | "defaultMessage": "!!!Restart & install update", |
678 | "end": { | 678 | "end": { |
679 | "column": 3, | 679 | "column": 3, |
680 | "line": 44 | 680 | "line": 45 |
681 | }, | 681 | }, |
682 | "file": "src/components/layout/AppLayout.js", | 682 | "file": "src/components/layout/AppLayout.js", |
683 | "id": "infobar.buttonInstallUpdate", | 683 | "id": "infobar.buttonInstallUpdate", |
684 | "start": { | 684 | "start": { |
685 | "column": 23, | 685 | "column": 23, |
686 | "line": 41 | 686 | "line": 42 |
687 | } | 687 | } |
688 | }, | 688 | }, |
689 | { | 689 | { |
690 | "defaultMessage": "!!!Could not load services and user information", | 690 | "defaultMessage": "!!!Could not load services and user information", |
691 | "end": { | 691 | "end": { |
692 | "column": 3, | 692 | "column": 3, |
693 | "line": 48 | 693 | "line": 49 |
694 | }, | 694 | }, |
695 | "file": "src/components/layout/AppLayout.js", | 695 | "file": "src/components/layout/AppLayout.js", |
696 | "id": "infobar.requiredRequestsFailed", | 696 | "id": "infobar.requiredRequestsFailed", |
697 | "start": { | 697 | "start": { |
698 | "column": 26, | 698 | "column": 26, |
699 | "line": 45 | 699 | "line": 46 |
700 | } | 700 | } |
701 | } | 701 | } |
702 | ], | 702 | ], |
@@ -3082,6 +3082,24 @@ | |||
3082 | { | 3082 | { |
3083 | "descriptors": [ | 3083 | "descriptors": [ |
3084 | { | 3084 | { |
3085 | "defaultMessage": "!!!What's new in Franz {version}?", | ||
3086 | "end": { | ||
3087 | "column": 3, | ||
3088 | "line": 14 | ||
3089 | }, | ||
3090 | "file": "src/features/announcements/Component.js", | ||
3091 | "id": "feature.announcements.headline", | ||
3092 | "start": { | ||
3093 | "column": 12, | ||
3094 | "line": 11 | ||
3095 | } | ||
3096 | } | ||
3097 | ], | ||
3098 | "path": "src/features/announcements/Component.json" | ||
3099 | }, | ||
3100 | { | ||
3101 | "descriptors": [ | ||
3102 | { | ||
3085 | "defaultMessage": "!!!Please purchase license to skip waiting", | 3103 | "defaultMessage": "!!!Please purchase license to skip waiting", |
3086 | "end": { | 3104 | "end": { |
3087 | "column": 3, | 3105 | "column": 3, |
@@ -4224,198 +4242,211 @@ | |||
4224 | } | 4242 | } |
4225 | }, | 4243 | }, |
4226 | { | 4244 | { |
4227 | "defaultMessage": "!!!Settings", | 4245 | "defaultMessage": "!!!What's new in Franz?", |
4228 | "end": { | 4246 | "end": { |
4229 | "column": 3, | 4247 | "column": 3, |
4230 | "line": 164 | 4248 | "line": 164 |
4231 | }, | 4249 | }, |
4232 | "file": "src/lib/Menu.js", | 4250 | "file": "src/lib/Menu.js", |
4251 | "id": "menu.app.announcement", | ||
4252 | "start": { | ||
4253 | "column": 16, | ||
4254 | "line": 161 | ||
4255 | } | ||
4256 | }, | ||
4257 | { | ||
4258 | "defaultMessage": "!!!Settings", | ||
4259 | "end": { | ||
4260 | "column": 3, | ||
4261 | "line": 168 | ||
4262 | }, | ||
4263 | "file": "src/lib/Menu.js", | ||
4233 | "id": "menu.app.settings", | 4264 | "id": "menu.app.settings", |
4234 | "start": { | 4265 | "start": { |
4235 | "column": 12, | 4266 | "column": 12, |
4236 | "line": 161 | 4267 | "line": 165 |
4237 | } | 4268 | } |
4238 | }, | 4269 | }, |
4239 | { | 4270 | { |
4240 | "defaultMessage": "!!!Hide", | 4271 | "defaultMessage": "!!!Hide", |
4241 | "end": { | 4272 | "end": { |
4242 | "column": 3, | 4273 | "column": 3, |
4243 | "line": 168 | 4274 | "line": 172 |
4244 | }, | 4275 | }, |
4245 | "file": "src/lib/Menu.js", | 4276 | "file": "src/lib/Menu.js", |
4246 | "id": "menu.app.hide", | 4277 | "id": "menu.app.hide", |
4247 | "start": { | 4278 | "start": { |
4248 | "column": 8, | 4279 | "column": 8, |
4249 | "line": 165 | 4280 | "line": 169 |
4250 | } | 4281 | } |
4251 | }, | 4282 | }, |
4252 | { | 4283 | { |
4253 | "defaultMessage": "!!!Hide Others", | 4284 | "defaultMessage": "!!!Hide Others", |
4254 | "end": { | 4285 | "end": { |
4255 | "column": 3, | 4286 | "column": 3, |
4256 | "line": 172 | 4287 | "line": 176 |
4257 | }, | 4288 | }, |
4258 | "file": "src/lib/Menu.js", | 4289 | "file": "src/lib/Menu.js", |
4259 | "id": "menu.app.hideOthers", | 4290 | "id": "menu.app.hideOthers", |
4260 | "start": { | 4291 | "start": { |
4261 | "column": 14, | 4292 | "column": 14, |
4262 | "line": 169 | 4293 | "line": 173 |
4263 | } | 4294 | } |
4264 | }, | 4295 | }, |
4265 | { | 4296 | { |
4266 | "defaultMessage": "!!!Unhide", | 4297 | "defaultMessage": "!!!Unhide", |
4267 | "end": { | 4298 | "end": { |
4268 | "column": 3, | 4299 | "column": 3, |
4269 | "line": 176 | 4300 | "line": 180 |
4270 | }, | 4301 | }, |
4271 | "file": "src/lib/Menu.js", | 4302 | "file": "src/lib/Menu.js", |
4272 | "id": "menu.app.unhide", | 4303 | "id": "menu.app.unhide", |
4273 | "start": { | 4304 | "start": { |
4274 | "column": 10, | 4305 | "column": 10, |
4275 | "line": 173 | 4306 | "line": 177 |
4276 | } | 4307 | } |
4277 | }, | 4308 | }, |
4278 | { | 4309 | { |
4279 | "defaultMessage": "!!!Quit", | 4310 | "defaultMessage": "!!!Quit", |
4280 | "end": { | 4311 | "end": { |
4281 | "column": 3, | 4312 | "column": 3, |
4282 | "line": 180 | 4313 | "line": 184 |
4283 | }, | 4314 | }, |
4284 | "file": "src/lib/Menu.js", | 4315 | "file": "src/lib/Menu.js", |
4285 | "id": "menu.app.quit", | 4316 | "id": "menu.app.quit", |
4286 | "start": { | 4317 | "start": { |
4287 | "column": 8, | 4318 | "column": 8, |
4288 | "line": 177 | 4319 | "line": 181 |
4289 | } | 4320 | } |
4290 | }, | 4321 | }, |
4291 | { | 4322 | { |
4292 | "defaultMessage": "!!!Add New Service...", | 4323 | "defaultMessage": "!!!Add New Service...", |
4293 | "end": { | 4324 | "end": { |
4294 | "column": 3, | 4325 | "column": 3, |
4295 | "line": 184 | 4326 | "line": 188 |
4296 | }, | 4327 | }, |
4297 | "file": "src/lib/Menu.js", | 4328 | "file": "src/lib/Menu.js", |
4298 | "id": "menu.services.addNewService", | 4329 | "id": "menu.services.addNewService", |
4299 | "start": { | 4330 | "start": { |
4300 | "column": 17, | 4331 | "column": 17, |
4301 | "line": 181 | 4332 | "line": 185 |
4302 | } | 4333 | } |
4303 | }, | 4334 | }, |
4304 | { | 4335 | { |
4305 | "defaultMessage": "!!!Add New Workspace...", | 4336 | "defaultMessage": "!!!Add New Workspace...", |
4306 | "end": { | 4337 | "end": { |
4307 | "column": 3, | 4338 | "column": 3, |
4308 | "line": 188 | 4339 | "line": 192 |
4309 | }, | 4340 | }, |
4310 | "file": "src/lib/Menu.js", | 4341 | "file": "src/lib/Menu.js", |
4311 | "id": "menu.workspaces.addNewWorkspace", | 4342 | "id": "menu.workspaces.addNewWorkspace", |
4312 | "start": { | 4343 | "start": { |
4313 | "column": 19, | 4344 | "column": 19, |
4314 | "line": 185 | 4345 | "line": 189 |
4315 | } | 4346 | } |
4316 | }, | 4347 | }, |
4317 | { | 4348 | { |
4318 | "defaultMessage": "!!!Open workspace drawer", | 4349 | "defaultMessage": "!!!Open workspace drawer", |
4319 | "end": { | 4350 | "end": { |
4320 | "column": 3, | 4351 | "column": 3, |
4321 | "line": 192 | 4352 | "line": 196 |
4322 | }, | 4353 | }, |
4323 | "file": "src/lib/Menu.js", | 4354 | "file": "src/lib/Menu.js", |
4324 | "id": "menu.workspaces.openWorkspaceDrawer", | 4355 | "id": "menu.workspaces.openWorkspaceDrawer", |
4325 | "start": { | 4356 | "start": { |
4326 | "column": 23, | 4357 | "column": 23, |
4327 | "line": 189 | 4358 | "line": 193 |
4328 | } | 4359 | } |
4329 | }, | 4360 | }, |
4330 | { | 4361 | { |
4331 | "defaultMessage": "!!!Close workspace drawer", | 4362 | "defaultMessage": "!!!Close workspace drawer", |
4332 | "end": { | 4363 | "end": { |
4333 | "column": 3, | 4364 | "column": 3, |
4334 | "line": 196 | 4365 | "line": 200 |
4335 | }, | 4366 | }, |
4336 | "file": "src/lib/Menu.js", | 4367 | "file": "src/lib/Menu.js", |
4337 | "id": "menu.workspaces.closeWorkspaceDrawer", | 4368 | "id": "menu.workspaces.closeWorkspaceDrawer", |
4338 | "start": { | 4369 | "start": { |
4339 | "column": 24, | 4370 | "column": 24, |
4340 | "line": 193 | 4371 | "line": 197 |
4341 | } | 4372 | } |
4342 | }, | 4373 | }, |
4343 | { | 4374 | { |
4344 | "defaultMessage": "!!!Activate next service...", | 4375 | "defaultMessage": "!!!Activate next service...", |
4345 | "end": { | 4376 | "end": { |
4346 | "column": 3, | 4377 | "column": 3, |
4347 | "line": 200 | 4378 | "line": 204 |
4348 | }, | 4379 | }, |
4349 | "file": "src/lib/Menu.js", | 4380 | "file": "src/lib/Menu.js", |
4350 | "id": "menu.services.setNextServiceActive", | 4381 | "id": "menu.services.setNextServiceActive", |
4351 | "start": { | 4382 | "start": { |
4352 | "column": 23, | 4383 | "column": 23, |
4353 | "line": 197 | 4384 | "line": 201 |
4354 | } | 4385 | } |
4355 | }, | 4386 | }, |
4356 | { | 4387 | { |
4357 | "defaultMessage": "!!!Activate previous service...", | 4388 | "defaultMessage": "!!!Activate previous service...", |
4358 | "end": { | 4389 | "end": { |
4359 | "column": 3, | 4390 | "column": 3, |
4360 | "line": 204 | 4391 | "line": 208 |
4361 | }, | 4392 | }, |
4362 | "file": "src/lib/Menu.js", | 4393 | "file": "src/lib/Menu.js", |
4363 | "id": "menu.services.activatePreviousService", | 4394 | "id": "menu.services.activatePreviousService", |
4364 | "start": { | 4395 | "start": { |
4365 | "column": 27, | 4396 | "column": 27, |
4366 | "line": 201 | 4397 | "line": 205 |
4367 | } | 4398 | } |
4368 | }, | 4399 | }, |
4369 | { | 4400 | { |
4370 | "defaultMessage": "!!!Disable notifications & audio", | 4401 | "defaultMessage": "!!!Disable notifications & audio", |
4371 | "end": { | 4402 | "end": { |
4372 | "column": 3, | 4403 | "column": 3, |
4373 | "line": 208 | 4404 | "line": 212 |
4374 | }, | 4405 | }, |
4375 | "file": "src/lib/Menu.js", | 4406 | "file": "src/lib/Menu.js", |
4376 | "id": "sidebar.muteApp", | 4407 | "id": "sidebar.muteApp", |
4377 | "start": { | 4408 | "start": { |
4378 | "column": 11, | 4409 | "column": 11, |
4379 | "line": 205 | 4410 | "line": 209 |
4380 | } | 4411 | } |
4381 | }, | 4412 | }, |
4382 | { | 4413 | { |
4383 | "defaultMessage": "!!!Enable notifications & audio", | 4414 | "defaultMessage": "!!!Enable notifications & audio", |
4384 | "end": { | 4415 | "end": { |
4385 | "column": 3, | 4416 | "column": 3, |
4386 | "line": 212 | 4417 | "line": 216 |
4387 | }, | 4418 | }, |
4388 | "file": "src/lib/Menu.js", | 4419 | "file": "src/lib/Menu.js", |
4389 | "id": "sidebar.unmuteApp", | 4420 | "id": "sidebar.unmuteApp", |
4390 | "start": { | 4421 | "start": { |
4391 | "column": 13, | 4422 | "column": 13, |
4392 | "line": 209 | 4423 | "line": 213 |
4393 | } | 4424 | } |
4394 | }, | 4425 | }, |
4395 | { | 4426 | { |
4396 | "defaultMessage": "!!!Workspaces", | 4427 | "defaultMessage": "!!!Workspaces", |
4397 | "end": { | 4428 | "end": { |
4398 | "column": 3, | 4429 | "column": 3, |
4399 | "line": 216 | 4430 | "line": 220 |
4400 | }, | 4431 | }, |
4401 | "file": "src/lib/Menu.js", | 4432 | "file": "src/lib/Menu.js", |
4402 | "id": "menu.workspaces", | 4433 | "id": "menu.workspaces", |
4403 | "start": { | 4434 | "start": { |
4404 | "column": 14, | 4435 | "column": 14, |
4405 | "line": 213 | 4436 | "line": 217 |
4406 | } | 4437 | } |
4407 | }, | 4438 | }, |
4408 | { | 4439 | { |
4409 | "defaultMessage": "!!!Default", | 4440 | "defaultMessage": "!!!Default", |
4410 | "end": { | 4441 | "end": { |
4411 | "column": 3, | 4442 | "column": 3, |
4412 | "line": 220 | 4443 | "line": 224 |
4413 | }, | 4444 | }, |
4414 | "file": "src/lib/Menu.js", | 4445 | "file": "src/lib/Menu.js", |
4415 | "id": "menu.workspaces.defaultWorkspace", | 4446 | "id": "menu.workspaces.defaultWorkspace", |
4416 | "start": { | 4447 | "start": { |
4417 | "column": 20, | 4448 | "column": 20, |
4418 | "line": 217 | 4449 | "line": 221 |
4419 | } | 4450 | } |
4420 | } | 4451 | } |
4421 | ], | 4452 | ], |
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 84a71117a..13775d758 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json | |||
@@ -1,6 +1,7 @@ | |||
1 | { | 1 | { |
2 | "app.errorHandler.action": "Reload", | 2 | "app.errorHandler.action": "Reload", |
3 | "app.errorHandler.headline": "Something went wrong", | 3 | "app.errorHandler.headline": "Something went wrong", |
4 | "feature.announcements.headline": "What's new in Franz {version}?", | ||
4 | "feature.delayApp.action": "Get a Franz Supporter License", | 5 | "feature.delayApp.action": "Get a Franz Supporter License", |
5 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", | 6 | "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", |
6 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", | 7 | "feature.delayApp.text": "Franz will continue in {seconds} seconds.", |
@@ -43,6 +44,7 @@ | |||
43 | "login.submit.label": "Sign in", | 44 | "login.submit.label": "Sign in", |
44 | "login.tokenExpired": "Your session expired, please login again.", | 45 | "login.tokenExpired": "Your session expired, please login again.", |
45 | "menu.app.about": "About Franz", | 46 | "menu.app.about": "About Franz", |
47 | "menu.app.announcement": "What's new in Franz?", | ||
46 | "menu.app.hide": "Hide", | 48 | "menu.app.hide": "Hide", |
47 | "menu.app.hideOthers": "Hide Others", | 49 | "menu.app.hideOthers": "Hide Others", |
48 | "menu.app.quit": "Quit", | 50 | "menu.app.quit": "Quit", |
diff --git a/src/i18n/messages/src/components/layout/AppLayout.json b/src/i18n/messages/src/components/layout/AppLayout.json index 92593ed5c..4dd354afc 100644 --- a/src/i18n/messages/src/components/layout/AppLayout.json +++ b/src/i18n/messages/src/components/layout/AppLayout.json | |||
@@ -4,11 +4,11 @@ | |||
4 | "defaultMessage": "!!!Your services have been updated.", | 4 | "defaultMessage": "!!!Your services have been updated.", |
5 | "file": "src/components/layout/AppLayout.js", | 5 | "file": "src/components/layout/AppLayout.js", |
6 | "start": { | 6 | "start": { |
7 | "line": 25, | 7 | "line": 26, |
8 | "column": 19 | 8 | "column": 19 |
9 | }, | 9 | }, |
10 | "end": { | 10 | "end": { |
11 | "line": 28, | 11 | "line": 29, |
12 | "column": 3 | 12 | "column": 3 |
13 | } | 13 | } |
14 | }, | 14 | }, |
@@ -17,11 +17,11 @@ | |||
17 | "defaultMessage": "!!!A new update for Franz is available.", | 17 | "defaultMessage": "!!!A new update for Franz is available.", |
18 | "file": "src/components/layout/AppLayout.js", | 18 | "file": "src/components/layout/AppLayout.js", |
19 | "start": { | 19 | "start": { |
20 | "line": 29, | 20 | "line": 30, |
21 | "column": 19 | 21 | "column": 19 |
22 | }, | 22 | }, |
23 | "end": { | 23 | "end": { |
24 | "line": 32, | 24 | "line": 33, |
25 | "column": 3 | 25 | "column": 3 |
26 | } | 26 | } |
27 | }, | 27 | }, |
@@ -30,11 +30,11 @@ | |||
30 | "defaultMessage": "!!!Reload services", | 30 | "defaultMessage": "!!!Reload services", |
31 | "file": "src/components/layout/AppLayout.js", | 31 | "file": "src/components/layout/AppLayout.js", |
32 | "start": { | 32 | "start": { |
33 | "line": 33, | 33 | "line": 34, |
34 | "column": 24 | 34 | "column": 24 |
35 | }, | 35 | }, |
36 | "end": { | 36 | "end": { |
37 | "line": 36, | 37 | "line": 37, |
38 | "column": 3 | 38 | "column": 3 |
39 | } | 39 | } |
40 | }, | 40 | }, |
@@ -43,11 +43,11 @@ | |||
43 | "defaultMessage": "!!!Changelog", | 43 | "defaultMessage": "!!!Changelog", |
44 | "file": "src/components/layout/AppLayout.js", | 44 | "file": "src/components/layout/AppLayout.js", |
45 | "start": { | 45 | "start": { |
46 | "line": 37, | 46 | "line": 38, |
47 | "column": 13 | 47 | "column": 13 |
48 | }, | 48 | }, |
49 | "end": { | 49 | "end": { |
50 | "line": 40, | 50 | "line": 41, |
51 | "column": 3 | 51 | "column": 3 |
52 | } | 52 | } |
53 | }, | 53 | }, |
@@ -56,11 +56,11 @@ | |||
56 | "defaultMessage": "!!!Restart & install update", | 56 | "defaultMessage": "!!!Restart & install update", |
57 | "file": "src/components/layout/AppLayout.js", | 57 | "file": "src/components/layout/AppLayout.js", |
58 | "start": { | 58 | "start": { |
59 | "line": 41, | 59 | "line": 42, |
60 | "column": 23 | 60 | "column": 23 |
61 | }, | 61 | }, |
62 | "end": { | 62 | "end": { |
63 | "line": 44, | 63 | "line": 45, |
64 | "column": 3 | 64 | "column": 3 |
65 | } | 65 | } |
66 | }, | 66 | }, |
@@ -69,11 +69,11 @@ | |||
69 | "defaultMessage": "!!!Could not load services and user information", | 69 | "defaultMessage": "!!!Could not load services and user information", |
70 | "file": "src/components/layout/AppLayout.js", | 70 | "file": "src/components/layout/AppLayout.js", |
71 | "start": { | 71 | "start": { |
72 | "line": 45, | 72 | "line": 46, |
73 | "column": 26 | 73 | "column": 26 |
74 | }, | 74 | }, |
75 | "end": { | 75 | "end": { |
76 | "line": 48, | 76 | "line": 49, |
77 | "column": 3 | 77 | "column": 3 |
78 | } | 78 | } |
79 | } | 79 | } |
diff --git a/src/i18n/messages/src/features/announcements/Component.json b/src/i18n/messages/src/features/announcements/Component.json new file mode 100644 index 000000000..18e1b84c5 --- /dev/null +++ b/src/i18n/messages/src/features/announcements/Component.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/Component.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 | ||
diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index 3889d39e0..f4cd35582 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json | |||
@@ -481,15 +481,28 @@ | |||
481 | } | 481 | } |
482 | }, | 482 | }, |
483 | { | 483 | { |
484 | "id": "menu.app.announcement", | ||
485 | "defaultMessage": "!!!What's new in Franz?", | ||
486 | "file": "src/lib/Menu.js", | ||
487 | "start": { | ||
488 | "line": 161, | ||
489 | "column": 16 | ||
490 | }, | ||
491 | "end": { | ||
492 | "line": 164, | ||
493 | "column": 3 | ||
494 | } | ||
495 | }, | ||
496 | { | ||
484 | "id": "menu.app.settings", | 497 | "id": "menu.app.settings", |
485 | "defaultMessage": "!!!Settings", | 498 | "defaultMessage": "!!!Settings", |
486 | "file": "src/lib/Menu.js", | 499 | "file": "src/lib/Menu.js", |
487 | "start": { | 500 | "start": { |
488 | "line": 161, | 501 | "line": 165, |
489 | "column": 12 | 502 | "column": 12 |
490 | }, | 503 | }, |
491 | "end": { | 504 | "end": { |
492 | "line": 164, | 505 | "line": 168, |
493 | "column": 3 | 506 | "column": 3 |
494 | } | 507 | } |
495 | }, | 508 | }, |
@@ -498,11 +511,11 @@ | |||
498 | "defaultMessage": "!!!Hide", | 511 | "defaultMessage": "!!!Hide", |
499 | "file": "src/lib/Menu.js", | 512 | "file": "src/lib/Menu.js", |
500 | "start": { | 513 | "start": { |
501 | "line": 165, | 514 | "line": 169, |
502 | "column": 8 | 515 | "column": 8 |
503 | }, | 516 | }, |
504 | "end": { | 517 | "end": { |
505 | "line": 168, | 518 | "line": 172, |
506 | "column": 3 | 519 | "column": 3 |
507 | } | 520 | } |
508 | }, | 521 | }, |
@@ -511,11 +524,11 @@ | |||
511 | "defaultMessage": "!!!Hide Others", | 524 | "defaultMessage": "!!!Hide Others", |
512 | "file": "src/lib/Menu.js", | 525 | "file": "src/lib/Menu.js", |
513 | "start": { | 526 | "start": { |
514 | "line": 169, | 527 | "line": 173, |
515 | "column": 14 | 528 | "column": 14 |
516 | }, | 529 | }, |
517 | "end": { | 530 | "end": { |
518 | "line": 172, | 531 | "line": 176, |
519 | "column": 3 | 532 | "column": 3 |
520 | } | 533 | } |
521 | }, | 534 | }, |
@@ -524,11 +537,11 @@ | |||
524 | "defaultMessage": "!!!Unhide", | 537 | "defaultMessage": "!!!Unhide", |
525 | "file": "src/lib/Menu.js", | 538 | "file": "src/lib/Menu.js", |
526 | "start": { | 539 | "start": { |
527 | "line": 173, | 540 | "line": 177, |
528 | "column": 10 | 541 | "column": 10 |
529 | }, | 542 | }, |
530 | "end": { | 543 | "end": { |
531 | "line": 176, | 544 | "line": 180, |
532 | "column": 3 | 545 | "column": 3 |
533 | } | 546 | } |
534 | }, | 547 | }, |
@@ -537,11 +550,11 @@ | |||
537 | "defaultMessage": "!!!Quit", | 550 | "defaultMessage": "!!!Quit", |
538 | "file": "src/lib/Menu.js", | 551 | "file": "src/lib/Menu.js", |
539 | "start": { | 552 | "start": { |
540 | "line": 177, | 553 | "line": 181, |
541 | "column": 8 | 554 | "column": 8 |
542 | }, | 555 | }, |
543 | "end": { | 556 | "end": { |
544 | "line": 180, | 557 | "line": 184, |
545 | "column": 3 | 558 | "column": 3 |
546 | } | 559 | } |
547 | }, | 560 | }, |
@@ -550,11 +563,11 @@ | |||
550 | "defaultMessage": "!!!Add New Service...", | 563 | "defaultMessage": "!!!Add New Service...", |
551 | "file": "src/lib/Menu.js", | 564 | "file": "src/lib/Menu.js", |
552 | "start": { | 565 | "start": { |
553 | "line": 181, | 566 | "line": 185, |
554 | "column": 17 | 567 | "column": 17 |
555 | }, | 568 | }, |
556 | "end": { | 569 | "end": { |
557 | "line": 184, | 570 | "line": 188, |
558 | "column": 3 | 571 | "column": 3 |
559 | } | 572 | } |
560 | }, | 573 | }, |
@@ -563,11 +576,11 @@ | |||
563 | "defaultMessage": "!!!Add New Workspace...", | 576 | "defaultMessage": "!!!Add New Workspace...", |
564 | "file": "src/lib/Menu.js", | 577 | "file": "src/lib/Menu.js", |
565 | "start": { | 578 | "start": { |
566 | "line": 185, | 579 | "line": 189, |
567 | "column": 19 | 580 | "column": 19 |
568 | }, | 581 | }, |
569 | "end": { | 582 | "end": { |
570 | "line": 188, | 583 | "line": 192, |
571 | "column": 3 | 584 | "column": 3 |
572 | } | 585 | } |
573 | }, | 586 | }, |
@@ -576,11 +589,11 @@ | |||
576 | "defaultMessage": "!!!Open workspace drawer", | 589 | "defaultMessage": "!!!Open workspace drawer", |
577 | "file": "src/lib/Menu.js", | 590 | "file": "src/lib/Menu.js", |
578 | "start": { | 591 | "start": { |
579 | "line": 189, | 592 | "line": 193, |
580 | "column": 23 | 593 | "column": 23 |
581 | }, | 594 | }, |
582 | "end": { | 595 | "end": { |
583 | "line": 192, | 596 | "line": 196, |
584 | "column": 3 | 597 | "column": 3 |
585 | } | 598 | } |
586 | }, | 599 | }, |
@@ -589,11 +602,11 @@ | |||
589 | "defaultMessage": "!!!Close workspace drawer", | 602 | "defaultMessage": "!!!Close workspace drawer", |
590 | "file": "src/lib/Menu.js", | 603 | "file": "src/lib/Menu.js", |
591 | "start": { | 604 | "start": { |
592 | "line": 193, | 605 | "line": 197, |
593 | "column": 24 | 606 | "column": 24 |
594 | }, | 607 | }, |
595 | "end": { | 608 | "end": { |
596 | "line": 196, | 609 | "line": 200, |
597 | "column": 3 | 610 | "column": 3 |
598 | } | 611 | } |
599 | }, | 612 | }, |
@@ -602,11 +615,11 @@ | |||
602 | "defaultMessage": "!!!Activate next service...", | 615 | "defaultMessage": "!!!Activate next service...", |
603 | "file": "src/lib/Menu.js", | 616 | "file": "src/lib/Menu.js", |
604 | "start": { | 617 | "start": { |
605 | "line": 197, | 618 | "line": 201, |
606 | "column": 23 | 619 | "column": 23 |
607 | }, | 620 | }, |
608 | "end": { | 621 | "end": { |
609 | "line": 200, | 622 | "line": 204, |
610 | "column": 3 | 623 | "column": 3 |
611 | } | 624 | } |
612 | }, | 625 | }, |
@@ -615,11 +628,11 @@ | |||
615 | "defaultMessage": "!!!Activate previous service...", | 628 | "defaultMessage": "!!!Activate previous service...", |
616 | "file": "src/lib/Menu.js", | 629 | "file": "src/lib/Menu.js", |
617 | "start": { | 630 | "start": { |
618 | "line": 201, | 631 | "line": 205, |
619 | "column": 27 | 632 | "column": 27 |
620 | }, | 633 | }, |
621 | "end": { | 634 | "end": { |
622 | "line": 204, | 635 | "line": 208, |
623 | "column": 3 | 636 | "column": 3 |
624 | } | 637 | } |
625 | }, | 638 | }, |
@@ -628,11 +641,11 @@ | |||
628 | "defaultMessage": "!!!Disable notifications & audio", | 641 | "defaultMessage": "!!!Disable notifications & audio", |
629 | "file": "src/lib/Menu.js", | 642 | "file": "src/lib/Menu.js", |
630 | "start": { | 643 | "start": { |
631 | "line": 205, | 644 | "line": 209, |
632 | "column": 11 | 645 | "column": 11 |
633 | }, | 646 | }, |
634 | "end": { | 647 | "end": { |
635 | "line": 208, | 648 | "line": 212, |
636 | "column": 3 | 649 | "column": 3 |
637 | } | 650 | } |
638 | }, | 651 | }, |
@@ -641,11 +654,11 @@ | |||
641 | "defaultMessage": "!!!Enable notifications & audio", | 654 | "defaultMessage": "!!!Enable notifications & audio", |
642 | "file": "src/lib/Menu.js", | 655 | "file": "src/lib/Menu.js", |
643 | "start": { | 656 | "start": { |
644 | "line": 209, | 657 | "line": 213, |
645 | "column": 13 | 658 | "column": 13 |
646 | }, | 659 | }, |
647 | "end": { | 660 | "end": { |
648 | "line": 212, | 661 | "line": 216, |
649 | "column": 3 | 662 | "column": 3 |
650 | } | 663 | } |
651 | }, | 664 | }, |
@@ -654,11 +667,11 @@ | |||
654 | "defaultMessage": "!!!Workspaces", | 667 | "defaultMessage": "!!!Workspaces", |
655 | "file": "src/lib/Menu.js", | 668 | "file": "src/lib/Menu.js", |
656 | "start": { | 669 | "start": { |
657 | "line": 213, | 670 | "line": 217, |
658 | "column": 14 | 671 | "column": 14 |
659 | }, | 672 | }, |
660 | "end": { | 673 | "end": { |
661 | "line": 216, | 674 | "line": 220, |
662 | "column": 3 | 675 | "column": 3 |
663 | } | 676 | } |
664 | }, | 677 | }, |
@@ -667,11 +680,11 @@ | |||
667 | "defaultMessage": "!!!Default", | 680 | "defaultMessage": "!!!Default", |
668 | "file": "src/lib/Menu.js", | 681 | "file": "src/lib/Menu.js", |
669 | "start": { | 682 | "start": { |
670 | "line": 217, | 683 | "line": 221, |
671 | "column": 20 | 684 | "column": 20 |
672 | }, | 685 | }, |
673 | "end": { | 686 | "end": { |
674 | "line": 220, | 687 | "line": 224, |
675 | "column": 3 | 688 | "column": 3 |
676 | } | 689 | } |
677 | } | 690 | } |
diff --git a/src/lib/Menu.js b/src/lib/Menu.js index a4e41c17c..46a347237 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js | |||
@@ -158,6 +158,10 @@ const menuItems = defineMessages({ | |||
158 | id: 'menu.app.about', | 158 | id: 'menu.app.about', |
159 | defaultMessage: '!!!About Franz', | 159 | defaultMessage: '!!!About Franz', |
160 | }, | 160 | }, |
161 | announcement: { | ||
162 | id: 'menu.app.announcement', | ||
163 | defaultMessage: '!!!What\'s new in Franz?', | ||
164 | }, | ||
161 | settings: { | 165 | settings: { |
162 | id: 'menu.app.settings', | 166 | id: 'menu.app.settings', |
163 | defaultMessage: '!!!Settings', | 167 | defaultMessage: '!!!Settings', |
@@ -618,6 +622,12 @@ export default class FranzMenu { | |||
618 | role: 'about', | 622 | role: 'about', |
619 | }, | 623 | }, |
620 | { | 624 | { |
625 | label: intl.formatMessage(menuItems.announcement), | ||
626 | click: () => { | ||
627 | this.actions.announcements.show(); | ||
628 | }, | ||
629 | }, | ||
630 | { | ||
621 | type: 'separator', | 631 | type: 'separator', |
622 | }, | 632 | }, |
623 | { | 633 | { |
diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js index 8fe576813..dcda021c1 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js | |||
@@ -14,6 +14,7 @@ import serviceProxy from '../features/serviceProxy'; | |||
14 | import basicAuth from '../features/basicAuth'; | 14 | import basicAuth from '../features/basicAuth'; |
15 | import workspaces from '../features/workspaces'; | 15 | import workspaces from '../features/workspaces'; |
16 | import shareFranz from '../features/shareFranz'; | 16 | import shareFranz from '../features/shareFranz'; |
17 | import announcements from '../features/announcements'; | ||
17 | 18 | ||
18 | import { DEFAULT_FEATURES_CONFIG } from '../config'; | 19 | import { DEFAULT_FEATURES_CONFIG } from '../config'; |
19 | 20 | ||
@@ -71,5 +72,6 @@ export default class FeaturesStore extends Store { | |||
71 | basicAuth(this.stores, this.actions); | 72 | basicAuth(this.stores, this.actions); |
72 | workspaces(this.stores, this.actions); | 73 | workspaces(this.stores, this.actions); |
73 | shareFranz(this.stores, this.actions); | 74 | shareFranz(this.stores, this.actions); |
75 | announcements(this.stores, this.actions); | ||
74 | } | 76 | } |
75 | } | 77 | } |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 0ec6bf550..d04fdd0c5 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -36,6 +36,7 @@ export default class ServicesStore extends Store { | |||
36 | 36 | ||
37 | // Register action handlers | 37 | // Register action handlers |
38 | this.actions.service.setActive.listen(this._setActive.bind(this)); | 38 | this.actions.service.setActive.listen(this._setActive.bind(this)); |
39 | this.actions.service.blurActive.listen(this._blurActive.bind(this)); | ||
39 | this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); | 40 | this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); |
40 | this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); | 41 | this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); |
41 | this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); | 42 | this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); |
@@ -301,6 +302,11 @@ export default class ServicesStore extends Store { | |||
301 | this._focusActiveService(); | 302 | this._focusActiveService(); |
302 | } | 303 | } |
303 | 304 | ||
305 | @action _blurActive() { | ||
306 | if (!this.active) return; | ||
307 | this.active.isActive = false; | ||
308 | } | ||
309 | |||
304 | @action _setActiveNext() { | 310 | @action _setActiveNext() { |
305 | const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); | 311 | const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); |
306 | 312 | ||