From 739ef2e8a2dec94c3e10c3d26d797fe759fac7aa Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Fri, 1 Mar 2019 14:25:44 +0100 Subject: finish workspaces mvp --- src/lib/Menu.js | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) (limited to 'src/lib/Menu.js') diff --git a/src/lib/Menu.js b/src/lib/Menu.js index c378619ad..1560dd285 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -3,6 +3,8 @@ import { observable, autorun, computed } from 'mobx'; import { defineMessages } from 'react-intl'; import { isMac, ctrlKey, cmdKey } from '../environment'; +import { workspacesState } from '../features/workspaces/state'; +import workspaceActions from '../features/workspaces/actions'; const { app, Menu, dialog } = remote; @@ -179,6 +181,18 @@ const menuItems = defineMessages({ id: 'menu.services.addNewService', defaultMessage: '!!!Add New Service...', }, + workspaces: { + id: 'menu.workspaces', + defaultMessage: '!!!Workspaces', + }, + defaultWorkspace: { + id: 'menu.workspaces.defaultWorkspace', + defaultMessage: '!!!Default', + }, + addNewWorkspace: { + id: 'menu.workspaces.addNewWorkspace', + defaultMessage: '!!!Add New Workspace...', + }, }); function getActiveWebview() { @@ -265,6 +279,10 @@ const _templateFactory = intl => [ label: intl.formatMessage(menuItems.services), submenu: [], }, + { + label: intl.formatMessage(menuItems.workspaces), + submenu: [], + }, { label: intl.formatMessage(menuItems.window), role: 'window', @@ -499,7 +517,9 @@ export default class FranzMenu { } _build() { - const serviceTpl = Object.assign([], this.serviceTpl); // need to clone object so we don't modify computed (cached) object + // need to clone object so we don't modify computed (cached) object + const serviceTpl = Object.assign([], this.serviceTpl); + const workspacesMenu = Object.assign([], this.workspacesMenu); if (window.franz === undefined) { return; @@ -632,7 +652,7 @@ export default class FranzMenu { }, ); - tpl[4].submenu.unshift(about, { + tpl[5].submenu.unshift(about, { type: 'separator', }); } else { @@ -678,6 +698,8 @@ export default class FranzMenu { tpl[3].submenu = serviceTpl; } + tpl[4].submenu = workspacesMenu; + this.currentTemplate = tpl; const menu = Menu.buildFromTemplate(tpl); Menu.setApplicationMenu(menu); @@ -701,6 +723,51 @@ export default class FranzMenu { return []; } + @computed get workspacesMenu() { + const { workspaces, activeWorkspace } = workspacesState; + const { intl } = window.franz; + const menu = []; + + // Add new workspace item: + menu.push({ + label: intl.formatMessage(menuItems.addNewWorkspace), + accelerator: `${cmdKey}+Shift+N`, + click: () => { + this.actions.ui.openSettings({ path: 'workspaces' }); + }, + enabled: this.stores.user.isLoggedIn, + }, { + type: 'separator', + }); + + // Default workspace + menu.push({ + label: intl.formatMessage(menuItems.defaultWorkspace), + accelerator: `${cmdKey}+Alt+1`, + type: 'radio', + checked: !activeWorkspace, + click: () => { + workspaceActions.deactivate(); + }, + }); + + // Workspace items + if (this.stores.user.isLoggedIn) { + workspaces.forEach((workspace, i) => menu.push({ + label: workspace.name, + accelerator: i < 9 ? `${cmdKey}+Alt+${i + 2}` : null, + type: 'radio', + checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, + click: () => { + workspaceActions.activate({ workspace }); + }, + })); + } + + console.log(menu); + return menu; + } + _getServiceName(service) { if (service.name) { return service.name; -- cgit v1.2.3-70-g09d2 From 2c67a242c660b925a5c97d7844db1e43347ab6ba Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Mon, 4 Mar 2019 13:05:55 +0100 Subject: remove dev logs --- src/features/workspaces/index.js | 1 - src/lib/Menu.js | 1 - 2 files changed, 2 deletions(-) (limited to 'src/lib/Menu.js') diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js index 79c9b8ac9..26cadea64 100644 --- a/src/features/workspaces/index.js +++ b/src/features/workspaces/index.js @@ -60,7 +60,6 @@ export default function initWorkspaces(stores, actions) { const workspaceServices = filterServicesByActiveWorkspace(services); const isActiveServiceInWorkspace = workspaceServices.includes(activeService); if (!isActiveServiceInWorkspace) { - console.log(workspaceServices[0].id); actions.service.setActive({ serviceId: workspaceServices[0].id }); } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 1560dd285..c572bbb70 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -764,7 +764,6 @@ export default class FranzMenu { })); } - console.log(menu); return menu; } -- cgit v1.2.3-70-g09d2 From 6fb07bcb716af76ec2e96345f37624d12d0d1af0 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Tue, 12 Mar 2019 21:36:10 +0100 Subject: implements basic release announcement feature --- .eslintrc | 2 +- package-lock.json | 5 ++ package.json | 1 + src/actions/index.js | 6 +- src/actions/service.js | 1 + src/components/layout/AppLayout.js | 4 + src/config.js | 1 + src/containers/layout/AppLayoutContainer.js | 2 + src/features/announcements/Component.js | 77 ++++++++++++++++++ src/features/announcements/actions.js | 8 ++ src/features/announcements/api.js | 19 +++++ src/features/announcements/index.js | 37 +++++++++ src/features/announcements/state.js | 17 ++++ src/features/announcements/store.js | 95 ++++++++++++++++++++++ src/i18n/locales/defaultMessages.json | 95 ++++++++++++++-------- src/i18n/locales/en-US.json | 2 + .../messages/src/components/layout/AppLayout.json | 24 +++--- .../src/features/announcements/Component.json | 15 ++++ src/i18n/messages/src/lib/Menu.json | 53 +++++++----- src/lib/Menu.js | 10 +++ src/stores/FeaturesStore.js | 2 + src/stores/ServicesStore.js | 6 ++ 22 files changed, 416 insertions(+), 66 deletions(-) create mode 100644 src/features/announcements/Component.js create mode 100644 src/features/announcements/actions.js create mode 100644 src/features/announcements/api.js create mode 100644 src/features/announcements/index.js create mode 100644 src/features/announcements/state.js create mode 100644 src/features/announcements/store.js create mode 100644 src/i18n/messages/src/features/announcements/Component.json (limited to 'src/lib/Menu.js') diff --git a/.eslintrc b/.eslintrc index 743946d35..a4ffd505c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,7 +14,7 @@ "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], - "react/forbid-prop-types": 1, + "react/forbid-prop-types": 0, "react/destructuring-assignment": 1, "prefer-destructuring": 1, "no-underscore-dangle": 0, diff --git a/package-lock.json b/package-lock.json index 8499abda9..bc333ae50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12094,6 +12094,11 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.1.tgz", + "integrity": "sha512-+H0L3ibcWhAZE02SKMqmvYsErLo4EAVJxu5h3bHBBDvvjeWXtl92rGUSBYHL2++5Y+RSNgl8dYOAXcYe7lp1fA==" + }, "matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", diff --git a/package.json b/package.json index 14e0df7ca..4ddc83777 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "hex-to-rgba": "1.0.2", "jsonwebtoken": "^7.4.1", "lodash": "^4.17.4", + "marked": "0.6.1", "mdi": "^1.9.33", "mime-types": "2.1.21", "mobx": "5.7.0", diff --git a/src/actions/index.js b/src/actions/index.js index 59acabb0b..dc1d3b6b2 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -11,6 +11,7 @@ import payment from './payment'; import news from './news'; import settings from './settings'; import requests from './requests'; +import announcements from '../features/announcements/actions'; const actions = Object.assign({}, { service, @@ -25,4 +26,7 @@ const actions = Object.assign({}, { requests, }); -export default defineActions(actions, PropTypes.checkPropTypes); +export default Object.assign( + defineActions(actions, PropTypes.checkPropTypes), + { announcements }, +); 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 { setActive: { serviceId: PropTypes.string.isRequired, }, + blurActive: {}, setActiveNext: {}, setActivePrev: {}, showAddServiceInterface: { diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 593149e72..2bda91f73 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -13,6 +13,7 @@ import ErrorBoundary from '../util/ErrorBoundary'; // import globalMessages from '../../i18n/globalMessages'; import { isWindows } from '../../environment'; +import AnnouncementScreen from '../../features/announcements/Component'; function createMarkup(HTMLString) { return { __html: HTMLString }; @@ -64,6 +65,7 @@ export default @observer class AppLayout extends Component { areRequiredRequestsLoading: PropTypes.bool.isRequired, darkMode: PropTypes.bool.isRequired, isDelayAppScreenVisible: PropTypes.bool.isRequired, + isAnnouncementVisible: PropTypes.bool.isRequired, }; static defaultProps = { @@ -93,6 +95,7 @@ export default @observer class AppLayout extends Component { areRequiredRequestsLoading, darkMode, isDelayAppScreenVisible, + isAnnouncementVisible, } = this.props; const { intl } = this.context; @@ -166,6 +169,7 @@ export default @observer class AppLayout extends Component { {isDelayAppScreenVisible && ()} + {isAnnouncementVisible && ()} {services} diff --git a/src/config.js b/src/config.js index 479572edb..47d22ca7d 100644 --- a/src/config.js +++ b/src/config.js @@ -41,6 +41,7 @@ export const DEFAULT_FEATURES_CONFIG = { }, isServiceProxyEnabled: false, isServiceProxyPremiumFeature: true, + isAnnouncementsEnabled: true, }; export const DEFAULT_WINDOW_OPTIONS = { diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 5a05ce431..f26e51517 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -20,6 +20,7 @@ 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'; export default @inject('stores', 'actions') @observer class AppLayoutContainer extends Component { static defaultProps = { @@ -134,6 +135,7 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e areRequiredRequestsLoading={requests.areRequiredRequestsLoading} darkMode={settings.all.app.darkMode} isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} + isAnnouncementVisible={announcementsState.isAnnouncementVisible} > {React.Children.count(children) > 0 ? children : null} 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 @@ +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/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 @@ +import PropTypes from 'prop-types'; +import { createActionsFromDefinitions } from '../../actions/lib/actions'; + +export const announcementActions = createActionsFromDefinitions({ + show: {}, +}, PropTypes.checkPropTypes); + +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 @@ +import { remote } from 'electron'; + +const debug = require('debug')('Franz:feature:announcements:api'); + +export default { + async getCurrentVersion() { + debug('getting current version of electron app'); + return Promise.resolve(remote.app.getVersion()); + }, + + async getAnnouncementForVersion(version) { + debug('fetching release announcement 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; + const data = await request.json(); + return data.body; + }, +}; 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 @@ +import { reaction, runInAction } 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 default function initAnnouncements(stores, actions) { + // const { features } = stores; + + // Toggle workspace feature + reaction( + () => ( + true + // features.features.isAnnouncementsEnabled + ), + (isEnabled) => { + if (isEnabled) { + debug('Initializing `announcements` feature'); + store = new AnnouncementsStore(stores, api, actions, state); + store.initialize(); + runInAction(() => { state.isFeatureActive = true; }); + } else if (store) { + debug('Disabling `announcements` feature'); + runInAction(() => { state.isFeatureActive = false; }); + store.teardown(); + store = null; + resetState(); // Reset state to default + } + }, + { + fireImmediately: true, + }, + ); +} 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 @@ +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 new file mode 100644 index 000000000..004a44062 --- /dev/null +++ b/src/features/announcements/store.js @@ -0,0 +1,95 @@ +import { action, observable, reaction } from 'mobx'; +import semver from 'semver'; + +import Request from '../../stores/lib/Request'; +import Store from '../../stores/lib/Store'; + +const debug = require('debug')('Franz:feature:announcements:store'); + +export class AnnouncementsStore extends Store { + @observable getCurrentVersion = new Request(this.api, 'getCurrentVersion'); + + @observable getAnnouncement = new Request(this.api, 'getAnnouncementForVersion'); + + constructor(stores, api, actions, state) { + super(stores, api, actions); + this.state = state; + } + + async setup() { + await this.fetchLastUsedVersion(); + await this.fetchCurrentVersion(); + await this.fetchReleaseAnnouncement(); + this.showAnnouncementIfNotSeenYet(); + + this.actions.announcements.show.listen(this._showAnnouncement.bind(this)); + } + + // ====== 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); + } + + async fetchCurrentVersion() { + debug('getting current version from api'); + const version = await this.getCurrentVersion.execute(); + this._setCurrentVersion(version); + } + + async fetchReleaseAnnouncement() { + debug('getting release announcement from api'); + try { + const announcement = await this.getAnnouncement.execute(this.state.currentVersion); + this._setAnnouncement(announcement); + } catch (error) { + this._setAnnouncement(null); + } + } + + showAnnouncementIfNotSeenYet() { + const { announcement, currentVersion, lastUsedVersion } = this.state; + if (announcement && semver.gt(currentVersion, lastUsedVersion)) { + debug(`${currentVersion} < ${lastUsedVersion}: announcement is shown`); + this._showAnnouncement(); + } else { + debug(`${currentVersion} >= ${lastUsedVersion}: announcement is hidden`); + this._hideAnnouncement(); + } + } + + // ====== PRIVATE ====== + + @action _setCurrentVersion(version) { + debug(`setting current version to ${version}`); + this.state.currentVersion = version; + } + + @action _setLastUsedVersion(version) { + debug(`setting last used version to ${version}`); + this.state.lastUsedVersion = version; + } + + @action _setAnnouncement(announcement) { + debug(`setting announcement to ${announcement}`); + this.state.announcement = announcement; + } + + @action _showAnnouncement() { + this.state.isAnnouncementVisible = true; + this.actions.service.blurActive(); + const dispose = reaction( + () => this.stores.services.active, + () => { + this._hideAnnouncement(); + dispose(); + }, + ); + } + + @action _hideAnnouncement() { + this.state.isAnnouncementVisible = false; + } +} diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 0641c510c..fcd24c7ef 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -625,78 +625,78 @@ "defaultMessage": "!!!Your services have been updated.", "end": { "column": 3, - "line": 25 + "line": 26 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.servicesUpdated", "start": { "column": 19, - "line": 22 + "line": 23 } }, { "defaultMessage": "!!!A new update for Franz is available.", "end": { "column": 3, - "line": 29 + "line": 30 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.updateAvailable", "start": { "column": 19, - "line": 26 + "line": 27 } }, { "defaultMessage": "!!!Reload services", "end": { "column": 3, - "line": 33 + "line": 34 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.buttonReloadServices", "start": { "column": 24, - "line": 30 + "line": 31 } }, { "defaultMessage": "!!!Changelog", "end": { "column": 3, - "line": 37 + "line": 38 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.buttonChangelog", "start": { "column": 13, - "line": 34 + "line": 35 } }, { "defaultMessage": "!!!Restart & install update", "end": { "column": 3, - "line": 41 + "line": 42 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.buttonInstallUpdate", "start": { "column": 23, - "line": 38 + "line": 39 } }, { "defaultMessage": "!!!Could not load services and user information", "end": { "column": 3, - "line": 45 + "line": 46 }, "file": "src/components/layout/AppLayout.js", "id": "infobar.requiredRequestsFailed", "start": { "column": 26, - "line": 42 + "line": 43 } } ], @@ -3022,6 +3022,24 @@ ], "path": "src/containers/settings/EditUserScreen.json" }, + { + "descriptors": [ + { + "defaultMessage": "!!!What's new in Franz {version}?", + "end": { + "column": 3, + "line": 14 + }, + "file": "src/features/announcements/Component.js", + "id": "feature.announcements.headline", + "start": { + "column": 12, + "line": 11 + } + } + ], + "path": "src/features/announcements/Component.json" + }, { "descriptors": [ { @@ -3799,133 +3817,146 @@ } }, { - "defaultMessage": "!!!Settings", + "defaultMessage": "!!!What's new in Franz?", "end": { "column": 3, "line": 161 }, "file": "src/lib/Menu.js", + "id": "menu.app.announcement", + "start": { + "column": 16, + "line": 158 + } + }, + { + "defaultMessage": "!!!Settings", + "end": { + "column": 3, + "line": 165 + }, + "file": "src/lib/Menu.js", "id": "menu.app.settings", "start": { "column": 12, - "line": 158 + "line": 162 } }, { "defaultMessage": "!!!Hide", "end": { "column": 3, - "line": 165 + "line": 169 }, "file": "src/lib/Menu.js", "id": "menu.app.hide", "start": { "column": 8, - "line": 162 + "line": 166 } }, { "defaultMessage": "!!!Hide Others", "end": { "column": 3, - "line": 169 + "line": 173 }, "file": "src/lib/Menu.js", "id": "menu.app.hideOthers", "start": { "column": 14, - "line": 166 + "line": 170 } }, { "defaultMessage": "!!!Unhide", "end": { "column": 3, - "line": 173 + "line": 177 }, "file": "src/lib/Menu.js", "id": "menu.app.unhide", "start": { "column": 10, - "line": 170 + "line": 174 } }, { "defaultMessage": "!!!Quit", "end": { "column": 3, - "line": 177 + "line": 181 }, "file": "src/lib/Menu.js", "id": "menu.app.quit", "start": { "column": 8, - "line": 174 + "line": 178 } }, { "defaultMessage": "!!!Add New Service...", "end": { "column": 3, - "line": 181 + "line": 185 }, "file": "src/lib/Menu.js", "id": "menu.services.addNewService", "start": { "column": 17, - "line": 178 + "line": 182 } }, { "defaultMessage": "!!!Activate next service...", "end": { "column": 3, - "line": 185 + "line": 189 }, "file": "src/lib/Menu.js", "id": "menu.services.setNextServiceActive", "start": { "column": 23, - "line": 182 + "line": 186 } }, { "defaultMessage": "!!!Activate previous service...", "end": { "column": 3, - "line": 189 + "line": 193 }, "file": "src/lib/Menu.js", "id": "menu.services.activatePreviousService", "start": { "column": 27, - "line": 186 + "line": 190 } }, { "defaultMessage": "!!!Disable notifications & audio", "end": { "column": 3, - "line": 193 + "line": 197 }, "file": "src/lib/Menu.js", "id": "sidebar.muteApp", "start": { "column": 11, - "line": 190 + "line": 194 } }, { "defaultMessage": "!!!Enable notifications & audio", "end": { "column": 3, - "line": 197 + "line": 201 }, "file": "src/lib/Menu.js", "id": "sidebar.unmuteApp", "start": { "column": 13, - "line": 194 + "line": 198 } } ], diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 7543d38bd..573231c45 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -1,6 +1,7 @@ { "app.errorHandler.action": "Reload", "app.errorHandler.headline": "Something went wrong", + "feature.announcements.headline": "What's new 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.", @@ -43,6 +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.hide": "Hide", "menu.app.hideOthers": "Hide Others", "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 07603d062..384d4b441 100644 --- a/src/i18n/messages/src/components/layout/AppLayout.json +++ b/src/i18n/messages/src/components/layout/AppLayout.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Your services have been updated.", "file": "src/components/layout/AppLayout.js", "start": { - "line": 22, + "line": 23, "column": 19 }, "end": { - "line": 25, + "line": 26, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!A new update for Franz is available.", "file": "src/components/layout/AppLayout.js", "start": { - "line": 26, + "line": 27, "column": 19 }, "end": { - "line": 29, + "line": 30, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Reload services", "file": "src/components/layout/AppLayout.js", "start": { - "line": 30, + "line": 31, "column": 24 }, "end": { - "line": 33, + "line": 34, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Changelog", "file": "src/components/layout/AppLayout.js", "start": { - "line": 34, + "line": 35, "column": 13 }, "end": { - "line": 37, + "line": 38, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Restart & install update", "file": "src/components/layout/AppLayout.js", "start": { - "line": 38, + "line": 39, "column": 23 }, "end": { - "line": 41, + "line": 42, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Could not load services and user information", "file": "src/components/layout/AppLayout.js", "start": { - "line": 42, + "line": 43, "column": 26 }, "end": { - "line": 45, + "line": 46, "column": 3 } } 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 @@ +[ + { + "id": "feature.announcements.headline", + "defaultMessage": "!!!What's new in Franz {version}?", + "file": "src/features/announcements/Component.js", + "start": { + "line": 11, + "column": 12 + }, + "end": { + "line": 14, + "column": 3 + } + } +] \ 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 9314f5cce..0db994871 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -480,16 +480,29 @@ "column": 3 } }, + { + "id": "menu.app.announcement", + "defaultMessage": "!!!What's new in Franz?", + "file": "src/lib/Menu.js", + "start": { + "line": 158, + "column": 16 + }, + "end": { + "line": 161, + "column": 3 + } + }, { "id": "menu.app.settings", "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 158, + "line": 162, "column": 12 }, "end": { - "line": 161, + "line": 165, "column": 3 } }, @@ -498,11 +511,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 162, + "line": 166, "column": 8 }, "end": { - "line": 165, + "line": 169, "column": 3 } }, @@ -511,11 +524,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 166, + "line": 170, "column": 14 }, "end": { - "line": 169, + "line": 173, "column": 3 } }, @@ -524,11 +537,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 170, + "line": 174, "column": 10 }, "end": { - "line": 173, + "line": 177, "column": 3 } }, @@ -537,11 +550,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 174, + "line": 178, "column": 8 }, "end": { - "line": 177, + "line": 181, "column": 3 } }, @@ -550,11 +563,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 178, + "line": 182, "column": 17 }, "end": { - "line": 181, + "line": 185, "column": 3 } }, @@ -563,11 +576,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 182, + "line": 186, "column": 23 }, "end": { - "line": 185, + "line": 189, "column": 3 } }, @@ -576,11 +589,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 186, + "line": 190, "column": 27 }, "end": { - "line": 189, + "line": 193, "column": 3 } }, @@ -589,11 +602,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 190, + "line": 194, "column": 11 }, "end": { - "line": 193, + "line": 197, "column": 3 } }, @@ -602,11 +615,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 194, + "line": 198, "column": 13 }, "end": { - "line": 197, + "line": 201, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 7a60c448f..70f3b2877 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -155,6 +155,10 @@ const menuItems = defineMessages({ id: 'menu.app.about', defaultMessage: '!!!About Franz', }, + announcement: { + id: 'menu.app.announcement', + defaultMessage: '!!!What\'s new in Franz?', + }, settings: { id: 'menu.app.settings', defaultMessage: '!!!Settings', @@ -589,6 +593,12 @@ 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/FeaturesStore.js b/src/stores/FeaturesStore.js index d2842083c..1c9044b07 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js @@ -8,6 +8,7 @@ import spellchecker from '../features/spellchecker'; import serviceProxy from '../features/serviceProxy'; import basicAuth from '../features/basicAuth'; import shareFranz from '../features/shareFranz'; +import announcements from '../features/announcements'; import { DEFAULT_FEATURES_CONFIG } from '../config'; @@ -58,5 +59,6 @@ export default class FeaturesStore extends Store { serviceProxy(this.stores, this.actions); basicAuth(this.stores, this.actions); shareFranz(this.stores, this.actions); + announcements(this.stores, this.actions); } } diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 69e616f0c..88b0331bf 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -35,6 +35,7 @@ export default class ServicesStore extends Store { // Register action handlers this.actions.service.setActive.listen(this._setActive.bind(this)); + this.actions.service.blurActive.listen(this._blurActive.bind(this)); this.actions.service.setActiveNext.listen(this._setActiveNext.bind(this)); this.actions.service.setActivePrev.listen(this._setActivePrev.bind(this)); this.actions.service.showAddServiceInterface.listen(this._showAddServiceInterface.bind(this)); @@ -298,6 +299,11 @@ export default class ServicesStore extends Store { this._focusActiveService(); } + @action _blurActive() { + if (!this.active) return; + this.active.isActive = false; + } + @action _setActiveNext() { const nextIndex = this._wrapIndex(this.allDisplayed.findIndex(service => service.isActive), 1, this.allDisplayed.length); -- cgit v1.2.3-70-g09d2 From e4f1862644d5921e2ee77078c10e16efa3e58c7b Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Tue, 19 Mar 2019 19:38:56 +0100 Subject: add workspace drawer --- packages/theme/src/themes/dark/index.ts | 9 +++ packages/theme/src/themes/default/index.ts | 10 +++ src/components/layout/AppLayout.js | 24 +++++- src/components/layout/Sidebar.js | 42 +++++++++- src/components/services/content/ServiceView.js | 1 + src/containers/layout/AppLayoutContainer.js | 14 ++++ src/features/workspaces/actions.js | 6 +- .../workspaces/components/WorkspaceDrawer.js | 94 ++++++++++++++++++++++ .../workspaces/components/WorkspaceDrawerItem.js | 88 ++++++++++++++++++++ src/features/workspaces/state.js | 1 + src/features/workspaces/store.js | 12 ++- src/i18n/locales/defaultMessages.json | 57 +++++++++++++ src/i18n/locales/en-US.json | 8 +- .../messages/src/components/layout/AppLayout.json | 24 +++--- .../messages/src/components/layout/Sidebar.json | 26 ++++++ .../workspaces/components/WorkspaceDrawer.json | 28 +++++++ src/lib/Menu.js | 4 +- src/styles/layout.scss | 12 ++- 18 files changed, 435 insertions(+), 25 deletions(-) create mode 100644 src/features/workspaces/components/WorkspaceDrawer.js create mode 100644 src/features/workspaces/components/WorkspaceDrawerItem.js create mode 100644 src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json (limited to 'src/lib/Menu.js') diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts index 3a56719b2..eaa552961 100644 --- a/packages/theme/src/themes/dark/index.ts +++ b/packages/theme/src/themes/dark/index.ts @@ -63,3 +63,12 @@ export const selectSearchColor = inputBackground; // Modal export const colorModalOverlayBackground = color(legacyStyles.darkThemeBlack).alpha(0.8).rgb().string(); + +// Workspace Drawer +export const workspaceDrawerBackground = color(colorBackground).lighten(0.3).hex(); +export const workspaceDrawerItemBorder = color(workspaceDrawerBackground).lighten(0.2).hex(); +export const workspaceDrawerItemActiveBackground = defaultStyles.brandPrimary; +export const workspaceDrawerNameColor = colorText; +export const workspaceDrawerNameActiveColor = 'white'; +export const workspaceDrawerServicesColor = color(colorText).darken(0.5).hex(); +export const workspaceDrawerServicesActiveColor = color(defaultStyles.brandPrimary).lighten(0.5).hex(); diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index 8a71e61cf..fc03b67de 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts @@ -140,3 +140,13 @@ export const badgeBorderRadius = 50; // Modal export const colorModalOverlayBackground = color('#000').alpha(0.5).rgb().string(); + +// Workspace Drawer +export const workspaceDrawerWidth = '220px'; +export const workspaceDrawerBackground = color(colorBackground).lighten(0.1).hex(); +export const workspaceDrawerItemActiveBackground = legacyStyles.themeGrayLightest; +export const workspaceDrawerItemBorder = color(workspaceDrawerBackground).darken(0.05).hex(); +export const workspaceDrawerNameColor = colorText; +export const workspaceDrawerNameActiveColor = colorText; +export const workspaceDrawerServicesColor = color(colorText).lighten(1.5).hex(); +export const workspaceDrawerServicesActiveColor = workspaceDrawerServicesColor; diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 593149e72..e06192f87 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; import { defineMessages, intlShape } from 'react-intl'; import { TitleBar } from 'electron-react-titlebar'; +import injectSheet from 'react-jss'; import InfoBar from '../ui/InfoBar'; import { Component as DelayApp } from '../../features/delayApp'; @@ -13,6 +14,7 @@ import ErrorBoundary from '../util/ErrorBoundary'; // import globalMessages from '../../i18n/globalMessages'; import { isWindows } from '../../environment'; +import { workspacesState } from '../../features/workspaces/state'; function createMarkup(HTMLString) { return { __html: HTMLString }; @@ -45,10 +47,23 @@ const messages = defineMessages({ }, }); -export default @observer class AppLayout extends Component { +const styles = theme => ({ + appContent: { + width: `calc(100% + ${theme.workspaceDrawerWidth})`, + transition: 'transform 0.5s ease', + transform() { + return workspacesState.isWorkspaceDrawerOpen ? 'translateX(0)' : 'translateX(-220px)'; + }, + }, +}); + +@injectSheet(styles) @observer +class AppLayout extends Component { static propTypes = { + classes: PropTypes.object.isRequired, isFullScreen: PropTypes.bool.isRequired, sidebar: PropTypes.element.isRequired, + workspacesDrawer: PropTypes.element.isRequired, services: PropTypes.element.isRequired, children: PropTypes.element, news: MobxPropTypes.arrayOrObservableArray.isRequired, @@ -76,7 +91,9 @@ export default @observer class AppLayout extends Component { render() { const { + classes, isFullScreen, + workspacesDrawer, sidebar, services, children, @@ -102,7 +119,8 @@ export default @observer class AppLayout extends Component {
{isWindows && !isFullScreen && } -
+
+ {workspacesDrawer} {sidebar}
{news.length > 0 && news.map(item => ( @@ -176,3 +194,5 @@ export default @observer class AppLayout extends Component { ); } } + +export default AppLayout; diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index fcc5b0001..de379875e 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js @@ -24,6 +24,14 @@ const messages = defineMessages({ id: 'sidebar.unmuteApp', defaultMessage: '!!!Enable notifications & audio', }, + openWorkspaceDrawer: { + id: 'sidebar.openWorkspaceDrawer', + defaultMessage: '!!!Open workspace drawer', + }, + closeWorkspaceDrawer: { + id: 'sidebar.closeWorkspaceDrawer', + defaultMessage: '!!!Close workspace drawer', + }, }); export default @observer class Sidebar extends Component { @@ -31,6 +39,8 @@ export default @observer class Sidebar extends Component { openSettings: PropTypes.func.isRequired, toggleMuteApp: PropTypes.func.isRequired, isAppMuted: PropTypes.bool.isRequired, + isWorkspaceDrawerOpen: PropTypes.bool.isRequired, + toggleWorkspaceDrawer: PropTypes.func.isRequired, }; static contextTypes = { @@ -53,9 +63,23 @@ export default @observer class Sidebar extends Component { this.setState({ tooltipEnabled: false }); } + updateToolTip() { + this.disableToolTip(); + setTimeout(this.enableToolTip.bind(this)); + } + render() { - const { openSettings, toggleMuteApp, isAppMuted } = this.props; + const { + openSettings, + toggleMuteApp, + isAppMuted, + isWorkspaceDrawerOpen, + toggleWorkspaceDrawer, + } = this.props; const { intl } = this.context; + const workspaceToggleMessage = ( + isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer + ); return (
@@ -66,7 +90,21 @@ export default @observer class Sidebar extends Component { /> + + {workspaceStore.isFeatureActive ? ( + + ) : null}
diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js index 6dc779be9..4d48c45ef 100644 --- a/src/features/workspaces/components/WorkspaceDrawer.js +++ b/src/features/workspaces/components/WorkspaceDrawer.js @@ -8,7 +8,8 @@ import ReactTooltip from 'react-tooltip'; import WorkspaceDrawerItem from './WorkspaceDrawerItem'; import { workspaceActions } from '../actions'; -import { workspaceStore } from '../index'; +import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../index'; +import { gaEvent } from '../../../lib/analytics'; const messages = defineMessages({ headline: { @@ -96,7 +97,10 @@ class WorkspaceDrawer extends Component {
workspaceActions.deactivate()} + onClick={() => { + workspaceActions.deactivate(); + gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'drawer'); + }} services={getServicesForWorkspace(null)} isActive={actualWorkspace == null} /> @@ -105,7 +109,10 @@ class WorkspaceDrawer extends Component { key={workspace.id} name={workspace.name} isActive={actualWorkspace === workspace} - onClick={() => workspaceActions.activate({ workspace })} + onClick={() => { + workspaceActions.activate({ workspace }); + gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'drawer'); + }} services={getServicesForWorkspace(workspace)} /> ))} diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index b31581a5b..52c3afdcf 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js @@ -77,7 +77,6 @@ class WorkspacesDashboard extends Component { workspaces, } = this.props; const { intl } = this.context; - console.log(deleteWorkspaceRequest.result); return (
diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js index 0d30cd19d..89999ab0f 100644 --- a/src/features/workspaces/index.js +++ b/src/features/workspaces/index.js @@ -4,6 +4,8 @@ import { resetApiRequests } from './api'; const debug = require('debug')('Franz:feature:workspaces'); +export const GA_CATEGORY_WORKSPACES = 'workspaces'; + export const workspaceStore = new WorkspacesStore(); export default function initWorkspaces(stores, actions) { diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 4b6a8eca9..659b1b361 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -708,78 +708,78 @@ "defaultMessage": "!!!Settings", "end": { "column": 3, - "line": 15 + "line": 16 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.settings", "start": { "column": 12, - "line": 12 + "line": 13 } }, { "defaultMessage": "!!!Add new service", "end": { "column": 3, - "line": 19 + "line": 20 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.addNewService", "start": { "column": 17, - "line": 16 + "line": 17 } }, { "defaultMessage": "!!!Disable notifications & audio", "end": { "column": 3, - "line": 23 + "line": 24 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.muteApp", "start": { "column": 8, - "line": 20 + "line": 21 } }, { "defaultMessage": "!!!Enable notifications & audio", "end": { "column": 3, - "line": 27 + "line": 28 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.unmuteApp", "start": { "column": 10, - "line": 24 + "line": 25 } }, { "defaultMessage": "!!!Open workspace drawer", "end": { "column": 3, - "line": 31 + "line": 32 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.openWorkspaceDrawer", "start": { "column": 23, - "line": 28 + "line": 29 } }, { "defaultMessage": "!!!Close workspace drawer", "end": { "column": 3, - "line": 35 + "line": 36 }, "file": "src/components/layout/Sidebar.js", "id": "sidebar.closeWorkspaceDrawer", "start": { "column": 24, - "line": 32 + "line": 33 } } ], @@ -3225,26 +3225,26 @@ "defaultMessage": "!!!Create workspace", "end": { "column": 3, - "line": 14 + "line": 16 }, "file": "src/features/workspaces/components/CreateWorkspaceForm.js", "id": "settings.workspace.add.form.submitButton", "start": { "column": 16, - "line": 11 + "line": 13 } }, { "defaultMessage": "!!!Name", "end": { "column": 3, - "line": 18 + "line": 20 }, "file": "src/features/workspaces/components/CreateWorkspaceForm.js", "id": "settings.workspace.add.form.name", "start": { "column": 8, - "line": 15 + "line": 17 } } ], @@ -3256,65 +3256,65 @@ "defaultMessage": "!!!Delete workspace", "end": { "column": 3, - "line": 20 + "line": 22 }, "file": "src/features/workspaces/components/EditWorkspaceForm.js", "id": "settings.workspace.form.buttonDelete", "start": { "column": 16, - "line": 17 + "line": 19 } }, { "defaultMessage": "!!!Save workspace", "end": { "column": 3, - "line": 24 + "line": 26 }, "file": "src/features/workspaces/components/EditWorkspaceForm.js", "id": "settings.workspace.form.buttonSave", "start": { "column": 14, - "line": 21 + "line": 23 } }, { "defaultMessage": "!!!Name", "end": { "column": 3, - "line": 28 + "line": 30 }, "file": "src/features/workspaces/components/EditWorkspaceForm.js", "id": "settings.workspace.form.name", "start": { "column": 8, - "line": 25 + "line": 27 } }, { "defaultMessage": "!!!Your workspaces", "end": { "column": 3, - "line": 32 + "line": 34 }, "file": "src/features/workspaces/components/EditWorkspaceForm.js", "id": "settings.workspace.form.yourWorkspaces", "start": { "column": 18, - "line": 29 + "line": 31 } }, { "defaultMessage": "!!!Services in this Workspace", "end": { "column": 3, - "line": 36 + "line": 38 }, "file": "src/features/workspaces/components/EditWorkspaceForm.js", "id": "settings.workspace.form.servicesInWorkspaceHeadline", "start": { "column": 31, - "line": 33 + "line": 35 } } ], @@ -3326,39 +3326,39 @@ "defaultMessage": "!!!Workspaces", "end": { "column": 3, - "line": 17 + "line": 18 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.headline", "start": { "column": 12, - "line": 14 + "line": 15 } }, { "defaultMessage": "!!!All services", "end": { "column": 3, - "line": 21 + "line": 22 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.allServices", "start": { "column": 15, - "line": 18 + "line": 19 } }, { "defaultMessage": "!!!Add workspace", "end": { "column": 3, - "line": 25 + "line": 26 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.addWorkspaceTooltip", "start": { "column": 23, - "line": 22 + "line": 23 } } ], @@ -3642,676 +3642,676 @@ "defaultMessage": "!!!Edit", "end": { "column": 3, - "line": 15 + "line": 16 }, "file": "src/lib/Menu.js", "id": "menu.edit", "start": { "column": 8, - "line": 12 + "line": 13 } }, { "defaultMessage": "!!!Undo", "end": { "column": 3, - "line": 19 + "line": 20 }, "file": "src/lib/Menu.js", "id": "menu.edit.undo", "start": { "column": 8, - "line": 16 + "line": 17 } }, { "defaultMessage": "!!!Redo", "end": { "column": 3, - "line": 23 + "line": 24 }, "file": "src/lib/Menu.js", "id": "menu.edit.redo", "start": { "column": 8, - "line": 20 + "line": 21 } }, { "defaultMessage": "!!!Cut", "end": { "column": 3, - "line": 27 + "line": 28 }, "file": "src/lib/Menu.js", "id": "menu.edit.cut", "start": { "column": 7, - "line": 24 + "line": 25 } }, { "defaultMessage": "!!!Copy", "end": { "column": 3, - "line": 31 + "line": 32 }, "file": "src/lib/Menu.js", "id": "menu.edit.copy", "start": { "column": 8, - "line": 28 + "line": 29 } }, { "defaultMessage": "!!!Paste", "end": { "column": 3, - "line": 35 + "line": 36 }, "file": "src/lib/Menu.js", "id": "menu.edit.paste", "start": { "column": 9, - "line": 32 + "line": 33 } }, { "defaultMessage": "!!!Paste And Match Style", "end": { "column": 3, - "line": 39 + "line": 40 }, "file": "src/lib/Menu.js", "id": "menu.edit.pasteAndMatchStyle", "start": { "column": 22, - "line": 36 + "line": 37 } }, { "defaultMessage": "!!!Delete", "end": { "column": 3, - "line": 43 + "line": 44 }, "file": "src/lib/Menu.js", "id": "menu.edit.delete", "start": { "column": 10, - "line": 40 + "line": 41 } }, { "defaultMessage": "!!!Select All", "end": { "column": 3, - "line": 47 + "line": 48 }, "file": "src/lib/Menu.js", "id": "menu.edit.selectAll", "start": { "column": 13, - "line": 44 + "line": 45 } }, { "defaultMessage": "!!!Speech", "end": { "column": 3, - "line": 51 + "line": 52 }, "file": "src/lib/Menu.js", "id": "menu.edit.speech", "start": { "column": 10, - "line": 48 + "line": 49 } }, { "defaultMessage": "!!!Start Speaking", "end": { "column": 3, - "line": 55 + "line": 56 }, "file": "src/lib/Menu.js", "id": "menu.edit.startSpeaking", "start": { "column": 17, - "line": 52 + "line": 53 } }, { "defaultMessage": "!!!Stop Speaking", "end": { "column": 3, - "line": 59 + "line": 60 }, "file": "src/lib/Menu.js", "id": "menu.edit.stopSpeaking", "start": { "column": 16, - "line": 56 + "line": 57 } }, { "defaultMessage": "!!!Start Dictation", "end": { "column": 3, - "line": 63 + "line": 64 }, "file": "src/lib/Menu.js", "id": "menu.edit.startDictation", "start": { "column": 18, - "line": 60 + "line": 61 } }, { "defaultMessage": "!!!Emoji & Symbols", "end": { "column": 3, - "line": 67 + "line": 68 }, "file": "src/lib/Menu.js", "id": "menu.edit.emojiSymbols", "start": { "column": 16, - "line": 64 + "line": 65 } }, { "defaultMessage": "!!!Actual Size", "end": { "column": 3, - "line": 71 + "line": 72 }, "file": "src/lib/Menu.js", "id": "menu.view.resetZoom", "start": { "column": 13, - "line": 68 + "line": 69 } }, { "defaultMessage": "!!!Zoom In", "end": { "column": 3, - "line": 75 + "line": 76 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomIn", "start": { "column": 10, - "line": 72 + "line": 73 } }, { "defaultMessage": "!!!Zoom Out", "end": { "column": 3, - "line": 79 + "line": 80 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomOut", "start": { "column": 11, - "line": 76 + "line": 77 } }, { "defaultMessage": "!!!Enter Full Screen", "end": { "column": 3, - "line": 83 + "line": 84 }, "file": "src/lib/Menu.js", "id": "menu.view.enterFullScreen", "start": { "column": 19, - "line": 80 + "line": 81 } }, { "defaultMessage": "!!!Exit Full Screen", "end": { "column": 3, - "line": 87 + "line": 88 }, "file": "src/lib/Menu.js", "id": "menu.view.exitFullScreen", "start": { "column": 18, - "line": 84 + "line": 85 } }, { "defaultMessage": "!!!Toggle Full Screen", "end": { "column": 3, - "line": 91 + "line": 92 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleFullScreen", "start": { "column": 20, - "line": 88 + "line": 89 } }, { "defaultMessage": "!!!Toggle Developer Tools", "end": { "column": 3, - "line": 95 + "line": 96 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleDevTools", "start": { "column": 18, - "line": 92 + "line": 93 } }, { "defaultMessage": "!!!Toggle Service Developer Tools", "end": { "column": 3, - "line": 99 + "line": 100 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleServiceDevTools", "start": { "column": 25, - "line": 96 + "line": 97 } }, { "defaultMessage": "!!!Reload Service", "end": { "column": 3, - "line": 103 + "line": 104 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadService", "start": { "column": 17, - "line": 100 + "line": 101 } }, { "defaultMessage": "!!!Reload Franz", "end": { "column": 3, - "line": 107 + "line": 108 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadFranz", "start": { "column": 15, - "line": 104 + "line": 105 } }, { "defaultMessage": "!!!Minimize", "end": { "column": 3, - "line": 111 + "line": 112 }, "file": "src/lib/Menu.js", "id": "menu.window.minimize", "start": { "column": 12, - "line": 108 + "line": 109 } }, { "defaultMessage": "!!!Close", "end": { "column": 3, - "line": 115 + "line": 116 }, "file": "src/lib/Menu.js", "id": "menu.window.close", "start": { "column": 9, - "line": 112 + "line": 113 } }, { "defaultMessage": "!!!Learn More", "end": { "column": 3, - "line": 119 + "line": 120 }, "file": "src/lib/Menu.js", "id": "menu.help.learnMore", "start": { "column": 13, - "line": 116 + "line": 117 } }, { "defaultMessage": "!!!Changelog", "end": { "column": 3, - "line": 123 + "line": 124 }, "file": "src/lib/Menu.js", "id": "menu.help.changelog", "start": { "column": 13, - "line": 120 + "line": 121 } }, { "defaultMessage": "!!!Support", "end": { "column": 3, - "line": 127 + "line": 128 }, "file": "src/lib/Menu.js", "id": "menu.help.support", "start": { "column": 11, - "line": 124 + "line": 125 } }, { "defaultMessage": "!!!Terms of Service", "end": { "column": 3, - "line": 131 + "line": 132 }, "file": "src/lib/Menu.js", "id": "menu.help.tos", "start": { "column": 7, - "line": 128 + "line": 129 } }, { "defaultMessage": "!!!Privacy Statement", "end": { "column": 3, - "line": 135 + "line": 136 }, "file": "src/lib/Menu.js", "id": "menu.help.privacy", "start": { "column": 11, - "line": 132 + "line": 133 } }, { "defaultMessage": "!!!File", "end": { "column": 3, - "line": 139 + "line": 140 }, "file": "src/lib/Menu.js", "id": "menu.file", "start": { "column": 8, - "line": 136 + "line": 137 } }, { "defaultMessage": "!!!View", "end": { "column": 3, - "line": 143 + "line": 144 }, "file": "src/lib/Menu.js", "id": "menu.view", "start": { "column": 8, - "line": 140 + "line": 141 } }, { "defaultMessage": "!!!Services", "end": { "column": 3, - "line": 147 + "line": 148 }, "file": "src/lib/Menu.js", "id": "menu.services", "start": { "column": 12, - "line": 144 + "line": 145 } }, { "defaultMessage": "!!!Window", "end": { "column": 3, - "line": 151 + "line": 152 }, "file": "src/lib/Menu.js", "id": "menu.window", "start": { "column": 10, - "line": 148 + "line": 149 } }, { "defaultMessage": "!!!Help", "end": { "column": 3, - "line": 155 + "line": 156 }, "file": "src/lib/Menu.js", "id": "menu.help", "start": { "column": 8, - "line": 152 + "line": 153 } }, { "defaultMessage": "!!!About Franz", "end": { "column": 3, - "line": 159 + "line": 160 }, "file": "src/lib/Menu.js", "id": "menu.app.about", "start": { "column": 9, - "line": 156 + "line": 157 } }, { "defaultMessage": "!!!Settings", "end": { "column": 3, - "line": 163 + "line": 164 }, "file": "src/lib/Menu.js", "id": "menu.app.settings", "start": { "column": 12, - "line": 160 + "line": 161 } }, { "defaultMessage": "!!!Hide", "end": { "column": 3, - "line": 167 + "line": 168 }, "file": "src/lib/Menu.js", "id": "menu.app.hide", "start": { "column": 8, - "line": 164 + "line": 165 } }, { "defaultMessage": "!!!Hide Others", "end": { "column": 3, - "line": 171 + "line": 172 }, "file": "src/lib/Menu.js", "id": "menu.app.hideOthers", "start": { "column": 14, - "line": 168 + "line": 169 } }, { "defaultMessage": "!!!Unhide", "end": { "column": 3, - "line": 175 + "line": 176 }, "file": "src/lib/Menu.js", "id": "menu.app.unhide", "start": { "column": 10, - "line": 172 + "line": 173 } }, { "defaultMessage": "!!!Quit", "end": { "column": 3, - "line": 179 + "line": 180 }, "file": "src/lib/Menu.js", "id": "menu.app.quit", "start": { "column": 8, - "line": 176 + "line": 177 } }, { "defaultMessage": "!!!Add New Service...", "end": { "column": 3, - "line": 183 + "line": 184 }, "file": "src/lib/Menu.js", "id": "menu.services.addNewService", "start": { "column": 17, - "line": 180 + "line": 181 } }, { "defaultMessage": "!!!Add New Workspace...", "end": { "column": 3, - "line": 187 + "line": 188 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.addNewWorkspace", "start": { "column": 19, - "line": 184 + "line": 185 } }, { "defaultMessage": "!!!Open workspace drawer", "end": { "column": 3, - "line": 191 + "line": 192 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.openWorkspaceDrawer", "start": { "column": 23, - "line": 188 + "line": 189 } }, { "defaultMessage": "!!!Close workspace drawer", "end": { "column": 3, - "line": 195 + "line": 196 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.closeWorkspaceDrawer", "start": { "column": 24, - "line": 192 + "line": 193 } }, { "defaultMessage": "!!!Activate next service...", "end": { "column": 3, - "line": 199 + "line": 200 }, "file": "src/lib/Menu.js", "id": "menu.services.setNextServiceActive", "start": { "column": 23, - "line": 196 + "line": 197 } }, { "defaultMessage": "!!!Activate previous service...", "end": { "column": 3, - "line": 203 + "line": 204 }, "file": "src/lib/Menu.js", "id": "menu.services.activatePreviousService", "start": { "column": 27, - "line": 200 + "line": 201 } }, { "defaultMessage": "!!!Disable notifications & audio", "end": { "column": 3, - "line": 207 + "line": 208 }, "file": "src/lib/Menu.js", "id": "sidebar.muteApp", "start": { "column": 11, - "line": 204 + "line": 205 } }, { "defaultMessage": "!!!Enable notifications & audio", "end": { "column": 3, - "line": 211 + "line": 212 }, "file": "src/lib/Menu.js", "id": "sidebar.unmuteApp", "start": { "column": 13, - "line": 208 + "line": 209 } }, { "defaultMessage": "!!!Workspaces", "end": { "column": 3, - "line": 215 + "line": 216 }, "file": "src/lib/Menu.js", "id": "menu.workspaces", "start": { "column": 14, - "line": 212 + "line": 213 } }, { "defaultMessage": "!!!Default", "end": { "column": 3, - "line": 219 + "line": 220 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.defaultWorkspace", "start": { "column": 20, - "line": 216 + "line": 217 } } ], diff --git a/src/i18n/messages/src/components/layout/Sidebar.json b/src/i18n/messages/src/components/layout/Sidebar.json index 8fc508f71..d67adc96e 100644 --- a/src/i18n/messages/src/components/layout/Sidebar.json +++ b/src/i18n/messages/src/components/layout/Sidebar.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Settings", "file": "src/components/layout/Sidebar.js", "start": { - "line": 12, + "line": 13, "column": 12 }, "end": { - "line": 15, + "line": 16, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Add new service", "file": "src/components/layout/Sidebar.js", "start": { - "line": 16, + "line": 17, "column": 17 }, "end": { - "line": 19, + "line": 20, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/components/layout/Sidebar.js", "start": { - "line": 20, + "line": 21, "column": 8 }, "end": { - "line": 23, + "line": 24, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/components/layout/Sidebar.js", "start": { - "line": 24, + "line": 25, "column": 10 }, "end": { - "line": 27, + "line": 28, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/components/layout/Sidebar.js", "start": { - "line": 28, + "line": 29, "column": 23 }, "end": { - "line": 31, + "line": 32, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/components/layout/Sidebar.js", "start": { - "line": 32, + "line": 33, "column": 24 }, "end": { - "line": 35, + "line": 36, "column": 3 } } diff --git a/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json index 7cc1a374f..f62bac42c 100644 --- a/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json +++ b/src/i18n/messages/src/features/workspaces/components/CreateWorkspaceForm.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Create workspace", "file": "src/features/workspaces/components/CreateWorkspaceForm.js", "start": { - "line": 11, + "line": 13, "column": 16 }, "end": { - "line": 14, + "line": 16, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Name", "file": "src/features/workspaces/components/CreateWorkspaceForm.js", "start": { - "line": 15, + "line": 17, "column": 8 }, "end": { - "line": 18, + "line": 20, "column": 3 } } diff --git a/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json b/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json index 8a26bf45a..7b0c3e1ce 100644 --- a/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json +++ b/src/i18n/messages/src/features/workspaces/components/EditWorkspaceForm.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Delete workspace", "file": "src/features/workspaces/components/EditWorkspaceForm.js", "start": { - "line": 17, + "line": 19, "column": 16 }, "end": { - "line": 20, + "line": 22, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Save workspace", "file": "src/features/workspaces/components/EditWorkspaceForm.js", "start": { - "line": 21, + "line": 23, "column": 14 }, "end": { - "line": 24, + "line": 26, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Name", "file": "src/features/workspaces/components/EditWorkspaceForm.js", "start": { - "line": 25, + "line": 27, "column": 8 }, "end": { - "line": 28, + "line": 30, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Your workspaces", "file": "src/features/workspaces/components/EditWorkspaceForm.js", "start": { - "line": 29, + "line": 31, "column": 18 }, "end": { - "line": 32, + "line": 34, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Services in this Workspace", "file": "src/features/workspaces/components/EditWorkspaceForm.js", "start": { - "line": 33, + "line": 35, "column": 31 }, "end": { - "line": 36, + "line": 38, "column": 3 } } diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json index 4e3237164..7026708e2 100644 --- a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json +++ b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 14, + "line": 15, "column": 12 }, "end": { - "line": 17, + "line": 18, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!All services", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 18, + "line": 19, "column": 15 }, "end": { - "line": 21, + "line": 22, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Add workspace", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 22, + "line": 23, "column": 23 }, "end": { - "line": 25, + "line": 26, "column": 3 } } diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index adbbd2638..3889d39e0 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": 12, + "line": 13, "column": 8 }, "end": { - "line": 15, + "line": 16, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Undo", "file": "src/lib/Menu.js", "start": { - "line": 16, + "line": 17, "column": 8 }, "end": { - "line": 19, + "line": 20, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Redo", "file": "src/lib/Menu.js", "start": { - "line": 20, + "line": 21, "column": 8 }, "end": { - "line": 23, + "line": 24, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Cut", "file": "src/lib/Menu.js", "start": { - "line": 24, + "line": 25, "column": 7 }, "end": { - "line": 27, + "line": 28, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Copy", "file": "src/lib/Menu.js", "start": { - "line": 28, + "line": 29, "column": 8 }, "end": { - "line": 31, + "line": 32, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Paste", "file": "src/lib/Menu.js", "start": { - "line": 32, + "line": 33, "column": 9 }, "end": { - "line": 35, + "line": 36, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Paste And Match Style", "file": "src/lib/Menu.js", "start": { - "line": 36, + "line": 37, "column": 22 }, "end": { - "line": 39, + "line": 40, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Delete", "file": "src/lib/Menu.js", "start": { - "line": 40, + "line": 41, "column": 10 }, "end": { - "line": 43, + "line": 44, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Select All", "file": "src/lib/Menu.js", "start": { - "line": 44, + "line": 45, "column": 13 }, "end": { - "line": 47, + "line": 48, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Speech", "file": "src/lib/Menu.js", "start": { - "line": 48, + "line": 49, "column": 10 }, "end": { - "line": 51, + "line": 52, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Start Speaking", "file": "src/lib/Menu.js", "start": { - "line": 52, + "line": 53, "column": 17 }, "end": { - "line": 55, + "line": 56, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Stop Speaking", "file": "src/lib/Menu.js", "start": { - "line": 56, + "line": 57, "column": 16 }, "end": { - "line": 59, + "line": 60, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Start Dictation", "file": "src/lib/Menu.js", "start": { - "line": 60, + "line": 61, "column": 18 }, "end": { - "line": 63, + "line": 64, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Emoji & Symbols", "file": "src/lib/Menu.js", "start": { - "line": 64, + "line": 65, "column": 16 }, "end": { - "line": 67, + "line": 68, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Actual Size", "file": "src/lib/Menu.js", "start": { - "line": 68, + "line": 69, "column": 13 }, "end": { - "line": 71, + "line": 72, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Zoom In", "file": "src/lib/Menu.js", "start": { - "line": 72, + "line": 73, "column": 10 }, "end": { - "line": 75, + "line": 76, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Zoom Out", "file": "src/lib/Menu.js", "start": { - "line": 76, + "line": 77, "column": 11 }, "end": { - "line": 79, + "line": 80, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Enter Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 80, + "line": 81, "column": 19 }, "end": { - "line": 83, + "line": 84, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Exit Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 84, + "line": 85, "column": 18 }, "end": { - "line": 87, + "line": 88, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Toggle Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 88, + "line": 89, "column": 20 }, "end": { - "line": 91, + "line": 92, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Toggle Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 92, + "line": 93, "column": 18 }, "end": { - "line": 95, + "line": 96, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 96, + "line": 97, "column": 25 }, "end": { - "line": 99, + "line": 100, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 100, + "line": 101, "column": 17 }, "end": { - "line": 103, + "line": 104, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 104, + "line": 105, "column": 15 }, "end": { - "line": 107, + "line": 108, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 108, + "line": 109, "column": 12 }, "end": { - "line": 111, + "line": 112, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 112, + "line": 113, "column": 9 }, "end": { - "line": 115, + "line": 116, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 116, + "line": 117, "column": 13 }, "end": { - "line": 119, + "line": 120, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 120, + "line": 121, "column": 13 }, "end": { - "line": 123, + "line": 124, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 124, + "line": 125, "column": 11 }, "end": { - "line": 127, + "line": 128, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 128, + "line": 129, "column": 7 }, "end": { - "line": 131, + "line": 132, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 132, + "line": 133, "column": 11 }, "end": { - "line": 135, + "line": 136, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 136, + "line": 137, "column": 8 }, "end": { - "line": 139, + "line": 140, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 140, + "line": 141, "column": 8 }, "end": { - "line": 143, + "line": 144, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 144, + "line": 145, "column": 12 }, "end": { - "line": 147, + "line": 148, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 148, + "line": 149, "column": 10 }, "end": { - "line": 151, + "line": 152, "column": 3 } }, @@ -459,11 +459,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 152, + "line": 153, "column": 8 }, "end": { - "line": 155, + "line": 156, "column": 3 } }, @@ -472,11 +472,11 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 156, + "line": 157, "column": 9 }, "end": { - "line": 159, + "line": 160, "column": 3 } }, @@ -485,11 +485,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 160, + "line": 161, "column": 12 }, "end": { - "line": 163, + "line": 164, "column": 3 } }, @@ -498,11 +498,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 164, + "line": 165, "column": 8 }, "end": { - "line": 167, + "line": 168, "column": 3 } }, @@ -511,11 +511,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 168, + "line": 169, "column": 14 }, "end": { - "line": 171, + "line": 172, "column": 3 } }, @@ -524,11 +524,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 172, + "line": 173, "column": 10 }, "end": { - "line": 175, + "line": 176, "column": 3 } }, @@ -537,11 +537,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 176, + "line": 177, "column": 8 }, "end": { - "line": 179, + "line": 180, "column": 3 } }, @@ -550,11 +550,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 180, + "line": 181, "column": 17 }, "end": { - "line": 183, + "line": 184, "column": 3 } }, @@ -563,11 +563,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 184, + "line": 185, "column": 19 }, "end": { - "line": 187, + "line": 188, "column": 3 } }, @@ -576,11 +576,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 188, + "line": 189, "column": 23 }, "end": { - "line": 191, + "line": 192, "column": 3 } }, @@ -589,11 +589,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 192, + "line": 193, "column": 24 }, "end": { - "line": 195, + "line": 196, "column": 3 } }, @@ -602,11 +602,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 196, + "line": 197, "column": 23 }, "end": { - "line": 199, + "line": 200, "column": 3 } }, @@ -615,11 +615,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 200, + "line": 201, "column": 27 }, "end": { - "line": 203, + "line": 204, "column": 3 } }, @@ -628,11 +628,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 204, + "line": 205, "column": 11 }, "end": { - "line": 207, + "line": 208, "column": 3 } }, @@ -641,11 +641,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 208, + "line": 209, "column": 13 }, "end": { - "line": 211, + "line": 212, "column": 3 } }, @@ -654,11 +654,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 212, + "line": 213, "column": 14 }, "end": { - "line": 215, + "line": 216, "column": 3 } }, @@ -667,11 +667,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 216, + "line": 217, "column": 20 }, "end": { - "line": 219, + "line": 220, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 3d6b6c824..d19aa9d6e 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -3,8 +3,9 @@ import { observable, autorun } from 'mobx'; import { defineMessages } from 'react-intl'; import { isMac, ctrlKey, cmdKey } from '../environment'; -import { workspaceStore } from '../features/workspaces/index'; +import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../features/workspaces/index'; import { workspaceActions } from '../features/workspaces/actions'; +import { gaEvent } from './analytics'; const { app, Menu, dialog } = remote; @@ -809,6 +810,7 @@ export default class FranzMenu { accelerator: `${cmdKey}+D`, click: () => { workspaceActions.toggleWorkspaceDrawer(); + gaEvent(GA_CATEGORY_WORKSPACES, 'toggleDrawer', 'menu'); }, enabled: this.stores.user.isLoggedIn, }, { @@ -823,6 +825,7 @@ export default class FranzMenu { checked: !activeWorkspace, click: () => { workspaceActions.deactivate(); + gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'menu'); }, }); @@ -835,6 +838,7 @@ export default class FranzMenu { checked: activeWorkspace ? workspace.id === activeWorkspace.id : false, click: () => { workspaceActions.activate({ workspace }); + gaEvent(GA_CATEGORY_WORKSPACES, 'switch', 'menu'); }, })); } diff --git a/src/lib/analytics.js b/src/lib/analytics.js index 0519192d1..e7daa9d06 100644 --- a/src/lib/analytics.js +++ b/src/lib/analytics.js @@ -28,12 +28,10 @@ ga('send', 'App'); export function gaPage(page) { ga('send', 'pageview', page); - debug('GA track page', page); } export function gaEvent(category, action, label) { ga('send', 'event', category, action, label); - - debug('GA track event', category, action); + debug('GA track event', category, action, label); } -- cgit v1.2.3-70-g09d2 From 7941831bf773b49944001c095a1949a1bdec2cf2 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 28 Mar 2019 16:23:17 +0100 Subject: add workspace premium notice to dashboard --- src/actions/lib/actions.js | 4 ++ src/components/layout/Sidebar.js | 2 +- .../settings/navigation/SettingsNavigation.js | 2 +- .../settings/services/EditServiceForm.js | 10 +++- .../settings/settings/EditSettingsForm.js | 1 + src/components/ui/PremiumFeatureContainer/index.js | 21 ++++++- .../ui/PremiumFeatureContainer/styles.js | 3 +- src/features/delayApp/index.js | 2 +- src/features/utils/FeatureStore.js | 21 +++++++ .../workspaces/components/CreateWorkspaceForm.js | 1 - .../workspaces/components/WorkspacesDashboard.js | 42 ++++++++++--- src/features/workspaces/index.js | 3 +- src/features/workspaces/store.js | 69 +++++++++++++--------- src/i18n/locales/defaultMessages.json | 54 ++++++++++++----- src/i18n/locales/en-US.json | 2 + .../ui/PremiumFeatureContainer/index.json | 4 +- .../workspaces/components/WorkspacesDashboard.json | 50 ++++++++++++---- src/lib/Menu.js | 4 +- src/stores/FeaturesStore.js | 18 ++++-- 19 files changed, 230 insertions(+), 83 deletions(-) create mode 100644 src/features/utils/FeatureStore.js (limited to 'src/lib/Menu.js') diff --git a/src/actions/lib/actions.js b/src/actions/lib/actions.js index 6571e9441..2bc7d2711 100644 --- a/src/actions/lib/actions.js +++ b/src/actions/lib/actions.js @@ -9,6 +9,10 @@ export const createActionsFromDefinitions = (actionDefinitions, validate) => { actions[actionName] = action; action.listeners = []; action.listen = listener => action.listeners.push(listener); + action.off = (listener) => { + const { listeners } = action; + listeners.splice(listeners.indexOf(listener), 1); + }; action.notify = params => action.listeners.forEach(listener => listener(params)); }); return actions; diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 4fa5e79de..327f76392 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js @@ -90,7 +90,7 @@ export default @observer class Sidebar extends Component { enableToolTip={() => this.enableToolTip()} disableToolTip={() => this.disableToolTip()} /> - {workspaceStore.isFeatureActive ? ( + {workspaceStore.isFeatureEnabled ? (
- +
actions.ui.openSettings({ path: 'user' })} + onClick={() => { + actions.ui.openSettings({ path: 'user' }); + if (gaEventInfo) { + const { category, event, label } = gaEventInfo; + gaEvent(category, event, label); + } + }} > {intl.formatMessage(messages.action)} @@ -73,3 +88,5 @@ PremiumFeatureContainer.wrappedComponent.propTypes = { }).isRequired, }).isRequired, }; + +export default PremiumFeatureContainer; diff --git a/src/components/ui/PremiumFeatureContainer/styles.js b/src/components/ui/PremiumFeatureContainer/styles.js index 81d6666c6..615ed0a79 100644 --- a/src/components/ui/PremiumFeatureContainer/styles.js +++ b/src/components/ui/PremiumFeatureContainer/styles.js @@ -6,6 +6,7 @@ export default theme => ({ padding: 20, 'border-radius': theme.borderRadius, pointerEvents: 'none', + height: 'auto', }, titleContainer: { display: 'flex', @@ -26,7 +27,7 @@ export default theme => ({ content: { opacity: 0.5, 'margin-top': 20, - '& :last-child': { + '& > :last-child': { 'margin-bottom': 0, }, }, diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js index abc8274cf..67f0fc5e6 100644 --- a/src/features/delayApp/index.js +++ b/src/features/delayApp/index.js @@ -55,7 +55,7 @@ export default function init(stores) { setVisibility(true); gaPage('/delayApp'); - gaEvent('delayApp', 'show', 'Delay App Feature'); + gaEvent('DelayApp', 'show', 'Delay App Feature'); timeLastDelay = moment(); shownAfterLaunch = true; diff --git a/src/features/utils/FeatureStore.js b/src/features/utils/FeatureStore.js new file mode 100644 index 000000000..66b66a104 --- /dev/null +++ b/src/features/utils/FeatureStore.js @@ -0,0 +1,21 @@ +import Reaction from '../../stores/lib/Reaction'; + +export class FeatureStore { + _actions = null; + + _reactions = null; + + _listenToActions(actions) { + if (this._actions) this._actions.forEach(a => a[0].off(a[1])); + this._actions = []; + actions.forEach(a => this._actions.push(a)); + this._actions.forEach(a => a[0].listen(a[1])); + } + + _startReactions(reactions) { + if (this._reactions) this._reactions.forEach(r => r.stop()); + this._reactions = []; + reactions.forEach(r => this._reactions.push(new Reaction(r))); + this._reactions.forEach(r => r.start()); + } +} diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js index a8f07d0d5..0be2d528f 100644 --- a/src/features/workspaces/components/CreateWorkspaceForm.js +++ b/src/features/workspaces/components/CreateWorkspaceForm.js @@ -30,7 +30,6 @@ const styles = () => ({ }, submitButton: { height: 'inherit', - marginTop: '3px', }, }); diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 52c3afdcf..1fad1f71d 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js @@ -10,6 +10,8 @@ import WorkspaceItem from './WorkspaceItem'; import CreateWorkspaceForm from './CreateWorkspaceForm'; import Request from '../../../stores/lib/Request'; import Appear from '../../../components/ui/effects/Appear'; +import { workspaceStore } from '../index'; +import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer'; const messages = defineMessages({ headline: { @@ -36,6 +38,14 @@ const messages = defineMessages({ id: 'settings.workspaces.deletedInfo', defaultMessage: '!!!Workspace has been deleted', }, + workspaceFeatureInfo: { + id: 'settings.workspaces.workspaceFeatureInfo', + defaultMessage: '!!!Info about workspace feature', + }, + workspaceFeatureHeadline: { + id: 'settings.workspaces.workspaceFeatureHeadline', + defaultMessage: '!!!Less is More: Introducing Franz Workspaces', + }, }); const styles = () => ({ @@ -46,6 +56,12 @@ const styles = () => ({ appear: { height: 'auto', }, + premiumAnnouncement: { + padding: '20px', + backgroundColor: '#3498db', + marginLeft: '-20px', + height: 'auto', + }, }); @injectSheet(styles) @observer @@ -112,14 +128,24 @@ class WorkspacesDashboard extends Component { )} - {/* ===== Create workspace form ===== */} -
- -
- + + {/* ===== Create workspace form ===== */} +
+ +
+
+ {workspaceStore.isUpgradeToPremiumRequired && ( +
+

{intl.formatMessage(messages.workspaceFeatureHeadline)}

+

{intl.formatMessage(messages.workspaceFeatureInfo)}

+
+ )} {getUserWorkspacesRequest.isExecuting ? ( ) : ( diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js index 89999ab0f..524a83e3c 100644 --- a/src/features/workspaces/index.js +++ b/src/features/workspaces/index.js @@ -4,11 +4,12 @@ import { resetApiRequests } from './api'; const debug = require('debug')('Franz:feature:workspaces'); -export const GA_CATEGORY_WORKSPACES = 'workspaces'; +export const GA_CATEGORY_WORKSPACES = 'Workspaces'; export const workspaceStore = new WorkspacesStore(); export default function initWorkspaces(stores, actions) { + stores.workspaces = workspaceStore; const { features, user } = stores; // Toggle workspace feature diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index f7df7b29c..62bf3efb4 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js @@ -3,9 +3,9 @@ import { observable, action, } from 'mobx'; -import Reaction from '../../stores/lib/Reaction'; import { matchRoute } from '../../helpers/routing-helpers'; import { workspaceActions } from './actions'; +import { FeatureStore } from '../utils/FeatureStore'; import { createWorkspaceRequest, deleteWorkspaceRequest, @@ -15,7 +15,11 @@ import { const debug = require('debug')('Franz:feature:workspaces:store'); -export default class WorkspacesStore { +export default class WorkspacesStore extends FeatureStore { + @observable isFeatureEnabled = false; + + @observable isPremiumFeature = true; + @observable isFeatureActive = false; @observable activeWorkspace = null; @@ -33,36 +37,39 @@ export default class WorkspacesStore { return getUserWorkspacesRequest.result || []; } - constructor() { - // Wire-up action handlers - workspaceActions.edit.listen(this._edit); - workspaceActions.create.listen(this._create); - workspaceActions.delete.listen(this._delete); - workspaceActions.update.listen(this._update); - workspaceActions.activate.listen(this._setActiveWorkspace); - workspaceActions.deactivate.listen(this._deactivateActiveWorkspace); - workspaceActions.toggleWorkspaceDrawer.listen(this._toggleWorkspaceDrawer); - workspaceActions.openWorkspaceSettings.listen(this._openWorkspaceSettings); - - // Register and start reactions - this._registerReactions([ - this._updateWorkspaceBeingEdited, - this._updateActiveServiceOnWorkspaceSwitch, - ]); + @computed get isUpgradeToPremiumRequired() { + return this.isFeatureEnabled && !this.isFeatureActive; } start(stores, actions) { debug('WorkspacesStore::start'); this.stores = stores; this.actions = actions; - this._reactions.forEach(r => r.start()); - this.isFeatureActive = true; + + this._listenToActions([ + [workspaceActions.edit, this._edit], + [workspaceActions.create, this._create], + [workspaceActions.delete, this._delete], + [workspaceActions.update, this._update], + [workspaceActions.activate, this._setActiveWorkspace], + [workspaceActions.deactivate, this._deactivateActiveWorkspace], + [workspaceActions.toggleWorkspaceDrawer, this._toggleWorkspaceDrawer], + [workspaceActions.openWorkspaceSettings, this._openWorkspaceSettings], + ]); + + this._startReactions([ + this._setWorkspaceBeingEditedReaction, + this._setActiveServiceOnWorkspaceSwitchReaction, + this._setFeatureEnabledReaction, + this._setIsPremiumFeatureReaction, + ]); + getUserWorkspacesRequest.execute(); + this.isFeatureActive = true; } stop() { debug('WorkspacesStore::stop'); - this._reactions.forEach(r => r.stop()); this.isFeatureActive = false; this.activeWorkspace = null; this.nextWorkspace = null; @@ -85,12 +92,6 @@ export default class WorkspacesStore { // ========== PRIVATE ========= // - _reactions = []; - - _registerReactions(reactions) { - reactions.forEach(r => this._reactions.push(new Reaction(r))); - } - _getWorkspaceById = id => this.workspaces.find(w => w.id === id); // Actions @@ -164,7 +165,17 @@ export default class WorkspacesStore { // Reactions - _updateWorkspaceBeingEdited = () => { + _setFeatureEnabledReaction = () => { + const { isWorkspaceEnabled } = this.stores.features.features; + this.isFeatureEnabled = isWorkspaceEnabled; + }; + + _setIsPremiumFeatureReaction = () => { + const { isWorkspacePremiumFeature } = this.stores.features.features; + this.isPremiumFeature = isWorkspacePremiumFeature; + }; + + _setWorkspaceBeingEditedReaction = () => { const { pathname } = this.stores.router.location; const match = matchRoute('/settings/workspaces/edit/:id', pathname); if (match) { @@ -172,7 +183,7 @@ export default class WorkspacesStore { } }; - _updateActiveServiceOnWorkspaceSwitch = () => { + _setActiveServiceOnWorkspaceSwitchReaction = () => { if (!this.isFeatureActive) return; if (this.activeWorkspace) { const services = this.stores.services.allDisplayed; diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 659b1b361..1747e1976 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -2535,13 +2535,13 @@ "defaultMessage": "!!!Upgrade account", "end": { "column": 3, - "line": 17 + "line": 18 }, "file": "src/components/ui/PremiumFeatureContainer/index.js", "id": "premiumFeature.button.upgradeAccount", "start": { "column": 10, - "line": 14 + "line": 15 } } ], @@ -3388,78 +3388,104 @@ "defaultMessage": "!!!Your workspaces", "end": { "column": 3, - "line": 18 + "line": 20 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.headline", "start": { "column": 12, - "line": 15 + "line": 17 } }, { "defaultMessage": "!!!You haven't added any workspaces yet.", "end": { "column": 3, - "line": 22 + "line": 24 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.noWorkspacesAdded", "start": { "column": 19, - "line": 19 + "line": 21 } }, { "defaultMessage": "!!!Could not load your workspaces", "end": { "column": 3, - "line": 26 + "line": 28 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.workspacesRequestFailed", "start": { "column": 27, - "line": 23 + "line": 25 } }, { "defaultMessage": "!!!Try again", "end": { "column": 3, - "line": 30 + "line": 32 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.tryReloadWorkspaces", "start": { "column": 23, - "line": 27 + "line": 29 } }, { "defaultMessage": "!!!Your changes have been saved", "end": { "column": 3, - "line": 34 + "line": 36 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.updatedInfo", "start": { "column": 15, - "line": 31 + "line": 33 } }, { "defaultMessage": "!!!Workspace has been deleted", "end": { "column": 3, - "line": 38 + "line": 40 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.deletedInfo", "start": { "column": 15, - "line": 35 + "line": 37 + } + }, + { + "defaultMessage": "!!!Info about workspace feature", + "end": { + "column": 3, + "line": 44 + }, + "file": "src/features/workspaces/components/WorkspacesDashboard.js", + "id": "settings.workspaces.workspaceFeatureInfo", + "start": { + "column": 24, + "line": 41 + } + }, + { + "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", + "end": { + "column": 3, + "line": 48 + }, + "file": "src/features/workspaces/components/WorkspacesDashboard.js", + "id": "settings.workspaces.workspaceFeatureHeadline", + "start": { + "column": 28, + "line": 45 } } ], diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 5f7254317..987262c35 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -254,6 +254,8 @@ "settings.workspaces.noWorkspacesAdded": "You haven't added any workspaces yet.", "settings.workspaces.tryReloadWorkspaces": "Try again", "settings.workspaces.updatedInfo": "Your changes have been saved", + "settings.workspaces.workspaceFeatureHeadline": "Less is More: Introducing Franz Workspaces", + "settings.workspaces.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.", "settings.workspaces.workspacesRequestFailed": "Could not load your workspaces", "sidebar.addNewService": "Add new service", "sidebar.closeWorkspaceDrawer": "Close workspace drawer", diff --git a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json index 582d546fa..320d3ca3e 100644 --- a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json +++ b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Upgrade account", "file": "src/components/ui/PremiumFeatureContainer/index.js", "start": { - "line": 14, + "line": 15, "column": 10 }, "end": { - "line": 17, + "line": 18, "column": 3 } } diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json index a957358c8..ef8f1bebc 100644 --- a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json +++ b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Your workspaces", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 15, + "line": 17, "column": 12 }, "end": { - "line": 18, + "line": 20, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!You haven't added any workspaces yet.", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 19, + "line": 21, "column": 19 }, "end": { - "line": 22, + "line": 24, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Could not load your workspaces", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 23, + "line": 25, "column": 27 }, "end": { - "line": 26, + "line": 28, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Try again", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 27, + "line": 29, "column": 23 }, "end": { - "line": 30, + "line": 32, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Your changes have been saved", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 31, + "line": 33, "column": 15 }, "end": { - "line": 34, + "line": 36, "column": 3 } }, @@ -69,11 +69,37 @@ "defaultMessage": "!!!Workspace has been deleted", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 35, + "line": 37, "column": 15 }, "end": { - "line": 38, + "line": 40, + "column": 3 + } + }, + { + "id": "settings.workspaces.workspaceFeatureInfo", + "defaultMessage": "!!!Info about workspace feature", + "file": "src/features/workspaces/components/WorkspacesDashboard.js", + "start": { + "line": 41, + "column": 24 + }, + "end": { + "line": 44, + "column": 3 + } + }, + { + "id": "settings.workspaces.workspaceFeatureHeadline", + "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", + "file": "src/features/workspaces/components/WorkspacesDashboard.js", + "start": { + "line": 45, + "column": 28 + }, + "end": { + "line": 48, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index d19aa9d6e..a4e41c17c 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -323,7 +323,7 @@ const _templateFactory = intl => [ { label: intl.formatMessage(menuItems.workspaces), submenu: [], - visible: workspaceStore.isFeatureActive, + visible: workspaceStore.isFeatureEnabled, }, { label: intl.formatMessage(menuItems.window), @@ -732,7 +732,7 @@ export default class FranzMenu { tpl[3].submenu = serviceTpl; } - if (workspaceStore.isFeatureActive) { + if (workspaceStore.isFeatureEnabled) { tpl[4].submenu = this.workspacesMenu(); } diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js index 2bda82e17..52e38ad96 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js @@ -1,4 +1,4 @@ -import { computed, observable, reaction } from 'mobx'; +import { computed, observable, reaction, runInAction } from 'mobx'; import Store from './lib/Store'; import CachedRequest from './lib/CachedRequest'; @@ -17,8 +17,11 @@ export default class FeaturesStore extends Store { @observable featuresRequest = new CachedRequest(this.api.features, 'features'); + @observable features = Object.assign({}, DEFAULT_FEATURES_CONFIG); + async setup() { this.registerReactions([ + this._updateFeatures, this._monitorLoginStatus.bind(this), ]); @@ -37,13 +40,16 @@ export default class FeaturesStore extends Store { return this.defaultFeaturesRequest.execute().result || DEFAULT_FEATURES_CONFIG; } - @computed get features() { + _updateFeatures = () => { + const features = Object.assign({}, DEFAULT_FEATURES_CONFIG); if (this.stores.user.isLoggedIn) { - return Object.assign({}, DEFAULT_FEATURES_CONFIG, this.featuresRequest.execute().result); + const requestResult = this.featuresRequest.execute().result; + Object.assign(features, requestResult); } - - return DEFAULT_FEATURES_CONFIG; - } + runInAction('FeaturesStore::_updateFeatures', () => { + this.features = features; + }); + }; _monitorLoginStatus() { if (this.stores.user.isLoggedIn) { -- cgit v1.2.3-70-g09d2 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 --- packages/theme/src/themes/dark/index.ts | 19 -- packages/theme/src/themes/default/index.ts | 20 -- 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 + 15 files changed, 405 insertions(+), 263 deletions(-) (limited to 'src/lib/Menu.js') diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts index fd04b106c..b17dc8965 100644 --- a/packages/theme/src/themes/dark/index.ts +++ b/packages/theme/src/themes/dark/index.ts @@ -111,22 +111,3 @@ export const workspaces = merge({}, defaultStyles.workspaces, { }, }, }); - -// // Workspace settings -// export const workspaceSettings = merge({}, defaultStyles.workspaceSettings, { -// listItemBorderColor: legacyStyles.darkThemeGrayDarker, -// listItemHoverBgColor: legacyStyles.darkThemeGrayDarker, -// }); -// -// // Workspace Drawer -// export const workspaceDrawerBackground = color(colorBackground).lighten(0.3).hex(); -// export const workspaceDrawerAddButtonColor = legacyStyles.darkThemeGrayLighter; -// export const workspaceDrawerAddButtonHoverColor = legacyStyles.darkThemeGraySmoke; -// export const workspaceDrawerItemBorder = color(workspaceDrawerBackground).lighten(0.2).hex(); -// export const workspaceDrawerItemHoverBackground = color(workspaceDrawerBackground).lighten(0.2).hex(); -// export const workspaceDrawerItemActiveBackground = defaultStyles.brandPrimary; -// export const workspaceDrawerItemNameColor = colorText; -// export const workspaceDrawerItemNameActiveColor = 'white'; -// export const workspaceDrawerServicesColor = color(colorText).darken(0.5).hex(); -// export const workspaceDrawerServicesActiveColor = color(defaultStyles.brandPrimary).lighten(0.5).hex(); -// diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index d0493b82f..46d29f593 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts @@ -200,23 +200,3 @@ export const workspaces = { spinnerColor: 'white', }, }; - -// export const workspaceSettings = { -// listItemHeight: 57, -// listItemBorderColor: legacyStyles.themeGrayLightest, -// listItemHoverBgColor: legacyStyles.themeGrayLightest, -// }; -// -// // Workspace Drawer -// export const workspaceDrawerWidth = 300; -// export const workspaceDrawerPadding = 20; -// export const workspaceDrawerBackground = color(colorBackground).lighten(0.1).hex(); -// export const workspaceDrawerAddButtonColor = legacyStyles.themeGrayLight; -// export const workspaceDrawerAddButtonHoverColor = color(legacyStyles.themeGrayLight).lighten(0.1).hex(); -// export const workspaceDrawerItemHoverBackground = color(workspaceDrawerBackground).darken(0.01).hex(); -// export const workspaceDrawerItemActiveBackground = legacyStyles.themeGrayLightest; -// export const workspaceDrawerItemBorder = color(workspaceDrawerBackground).darken(0.05).hex(); -// export const workspaceDrawerItemNameColor = colorText; -// export const workspaceDrawerItemNameActiveColor = colorText; -// export const workspaceDrawerServicesColor = color(colorText).lighten(1.5).hex(); -// export const workspaceDrawerServicesActiveColor = workspaceDrawerServicesColor; 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-70-g09d2 From 2af294e00cd14e7ba26ab36bc1b8fe7680661739 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 11 Apr 2019 16:47:28 +0200 Subject: fix lint issues --- src/containers/layout/AppLayoutContainer.js | 1 - .../announcements/components/AnnouncementScreen.js | 2 +- src/features/announcements/store.js | 16 ++++++++-------- src/lib/Menu.js | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) (limited to 'src/lib/Menu.js') diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index 8a0e105e7..8c1d2dfc1 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js @@ -20,7 +20,6 @@ import Services from '../../components/services/content/Services'; import AppLoader from '../../components/ui/AppLoader'; import { state as delayAppState } from '../../features/delayApp'; -import { } from '../../features/announcements/store'; import { workspaceActions } from '../../features/workspaces/actions'; import WorkspaceDrawer from '../../features/workspaces/components/WorkspaceDrawer'; import { workspaceStore } from '../../features/workspaces'; diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js index 2d5efc396..2682b7890 100644 --- a/src/features/announcements/components/AnnouncementScreen.js +++ b/src/features/announcements/components/AnnouncementScreen.js @@ -150,7 +150,7 @@ class AnnouncementScreen extends Component {

diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js index d4fb0a52c..3c46828bb 100644 --- a/src/features/announcements/store.js +++ b/src/features/announcements/store.js @@ -112,14 +112,14 @@ export class AnnouncementsStore extends FeatureStore { 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(); - // } + 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 = () => { diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 3df06e05a..6bea67860 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -6,7 +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'; +import { announcementActions } from '../features/announcements/actions'; const { app, Menu, dialog } = remote; -- cgit v1.2.3-70-g09d2 From 8f0a4518ea896e2c55e9a52306203ea4840e055b Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Tue, 16 Apr 2019 16:26:50 +0200 Subject: hide news menu item when there are no news --- src/features/announcements/store.js | 7 ++ src/i18n/locales/defaultMessages.json | 212 +++++++++++++++++----------------- src/i18n/messages/src/lib/Menu.json | 212 +++++++++++++++++----------------- src/lib/Menu.js | 2 + 4 files changed, 221 insertions(+), 212 deletions(-) (limited to 'src/lib/Menu.js') diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js index aa98d3bd1..7ecc0e346 100644 --- a/src/features/announcements/store.js +++ b/src/features/announcements/store.js @@ -34,6 +34,12 @@ export class AnnouncementsStore extends FeatureStore { return getAnnouncementRequest.result; } + @computed get areNewsAvailable() { + const isChangelogAvailable = getChangelogRequest.wasExecuted && !!this.changelog; + const isAnnouncementAvailable = getAnnouncementRequest.wasExecuted && !!this.announcement; + return isChangelogAvailable || isAnnouncementAvailable; + } + @computed get settings() { return localStorage.getItem(LOCAL_STORAGE_KEY) || {}; } @@ -87,6 +93,7 @@ export class AnnouncementsStore extends FeatureStore { // ======= ACTIONS ======= // @action _showAnnouncement = ({ targetVersion } = {}) => { + if (!this.areNewsAvailable) return; this.targetVersion = targetVersion || this.currentVersion; this.isAnnouncementVisible = true; this.actions.service.blurActive(); diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 03435fd09..632eb38fd 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3912,689 +3912,689 @@ "defaultMessage": "!!!Edit", "end": { "column": 3, - "line": 17 + "line": 18 }, "file": "src/lib/Menu.js", "id": "menu.edit", "start": { "column": 8, - "line": 14 + "line": 15 } }, { "defaultMessage": "!!!Undo", "end": { "column": 3, - "line": 21 + "line": 22 }, "file": "src/lib/Menu.js", "id": "menu.edit.undo", "start": { "column": 8, - "line": 18 + "line": 19 } }, { "defaultMessage": "!!!Redo", "end": { "column": 3, - "line": 25 + "line": 26 }, "file": "src/lib/Menu.js", "id": "menu.edit.redo", "start": { "column": 8, - "line": 22 + "line": 23 } }, { "defaultMessage": "!!!Cut", "end": { "column": 3, - "line": 29 + "line": 30 }, "file": "src/lib/Menu.js", "id": "menu.edit.cut", "start": { "column": 7, - "line": 26 + "line": 27 } }, { "defaultMessage": "!!!Copy", "end": { "column": 3, - "line": 33 + "line": 34 }, "file": "src/lib/Menu.js", "id": "menu.edit.copy", "start": { "column": 8, - "line": 30 + "line": 31 } }, { "defaultMessage": "!!!Paste", "end": { "column": 3, - "line": 37 + "line": 38 }, "file": "src/lib/Menu.js", "id": "menu.edit.paste", "start": { "column": 9, - "line": 34 + "line": 35 } }, { "defaultMessage": "!!!Paste And Match Style", "end": { "column": 3, - "line": 41 + "line": 42 }, "file": "src/lib/Menu.js", "id": "menu.edit.pasteAndMatchStyle", "start": { "column": 22, - "line": 38 + "line": 39 } }, { "defaultMessage": "!!!Delete", "end": { "column": 3, - "line": 45 + "line": 46 }, "file": "src/lib/Menu.js", "id": "menu.edit.delete", "start": { "column": 10, - "line": 42 + "line": 43 } }, { "defaultMessage": "!!!Select All", "end": { "column": 3, - "line": 49 + "line": 50 }, "file": "src/lib/Menu.js", "id": "menu.edit.selectAll", "start": { "column": 13, - "line": 46 + "line": 47 } }, { "defaultMessage": "!!!Speech", "end": { "column": 3, - "line": 53 + "line": 54 }, "file": "src/lib/Menu.js", "id": "menu.edit.speech", "start": { "column": 10, - "line": 50 + "line": 51 } }, { "defaultMessage": "!!!Start Speaking", "end": { "column": 3, - "line": 57 + "line": 58 }, "file": "src/lib/Menu.js", "id": "menu.edit.startSpeaking", "start": { "column": 17, - "line": 54 + "line": 55 } }, { "defaultMessage": "!!!Stop Speaking", "end": { "column": 3, - "line": 61 + "line": 62 }, "file": "src/lib/Menu.js", "id": "menu.edit.stopSpeaking", "start": { "column": 16, - "line": 58 + "line": 59 } }, { "defaultMessage": "!!!Start Dictation", "end": { "column": 3, - "line": 65 + "line": 66 }, "file": "src/lib/Menu.js", "id": "menu.edit.startDictation", "start": { "column": 18, - "line": 62 + "line": 63 } }, { "defaultMessage": "!!!Emoji & Symbols", "end": { "column": 3, - "line": 69 + "line": 70 }, "file": "src/lib/Menu.js", "id": "menu.edit.emojiSymbols", "start": { "column": 16, - "line": 66 + "line": 67 } }, { "defaultMessage": "!!!Actual Size", "end": { "column": 3, - "line": 73 + "line": 74 }, "file": "src/lib/Menu.js", "id": "menu.view.resetZoom", "start": { "column": 13, - "line": 70 + "line": 71 } }, { "defaultMessage": "!!!Zoom In", "end": { "column": 3, - "line": 77 + "line": 78 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomIn", "start": { "column": 10, - "line": 74 + "line": 75 } }, { "defaultMessage": "!!!Zoom Out", "end": { "column": 3, - "line": 81 + "line": 82 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomOut", "start": { "column": 11, - "line": 78 + "line": 79 } }, { "defaultMessage": "!!!Enter Full Screen", "end": { "column": 3, - "line": 85 + "line": 86 }, "file": "src/lib/Menu.js", "id": "menu.view.enterFullScreen", "start": { "column": 19, - "line": 82 + "line": 83 } }, { "defaultMessage": "!!!Exit Full Screen", "end": { "column": 3, - "line": 89 + "line": 90 }, "file": "src/lib/Menu.js", "id": "menu.view.exitFullScreen", "start": { "column": 18, - "line": 86 + "line": 87 } }, { "defaultMessage": "!!!Toggle Full Screen", "end": { "column": 3, - "line": 93 + "line": 94 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleFullScreen", "start": { "column": 20, - "line": 90 + "line": 91 } }, { "defaultMessage": "!!!Toggle Developer Tools", "end": { "column": 3, - "line": 97 + "line": 98 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleDevTools", "start": { "column": 18, - "line": 94 + "line": 95 } }, { "defaultMessage": "!!!Toggle Service Developer Tools", "end": { "column": 3, - "line": 101 + "line": 102 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleServiceDevTools", "start": { "column": 25, - "line": 98 + "line": 99 } }, { "defaultMessage": "!!!Reload Service", "end": { "column": 3, - "line": 105 + "line": 106 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadService", "start": { "column": 17, - "line": 102 + "line": 103 } }, { "defaultMessage": "!!!Reload Franz", "end": { "column": 3, - "line": 109 + "line": 110 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadFranz", "start": { "column": 15, - "line": 106 + "line": 107 } }, { "defaultMessage": "!!!Minimize", "end": { "column": 3, - "line": 113 + "line": 114 }, "file": "src/lib/Menu.js", "id": "menu.window.minimize", "start": { "column": 12, - "line": 110 + "line": 111 } }, { "defaultMessage": "!!!Close", "end": { "column": 3, - "line": 117 + "line": 118 }, "file": "src/lib/Menu.js", "id": "menu.window.close", "start": { "column": 9, - "line": 114 + "line": 115 } }, { "defaultMessage": "!!!Learn More", "end": { "column": 3, - "line": 121 + "line": 122 }, "file": "src/lib/Menu.js", "id": "menu.help.learnMore", "start": { "column": 13, - "line": 118 + "line": 119 } }, { "defaultMessage": "!!!Changelog", "end": { "column": 3, - "line": 125 + "line": 126 }, "file": "src/lib/Menu.js", "id": "menu.help.changelog", "start": { "column": 13, - "line": 122 + "line": 123 } }, { "defaultMessage": "!!!Support", "end": { "column": 3, - "line": 129 + "line": 130 }, "file": "src/lib/Menu.js", "id": "menu.help.support", "start": { "column": 11, - "line": 126 + "line": 127 } }, { "defaultMessage": "!!!Terms of Service", "end": { "column": 3, - "line": 133 + "line": 134 }, "file": "src/lib/Menu.js", "id": "menu.help.tos", "start": { "column": 7, - "line": 130 + "line": 131 } }, { "defaultMessage": "!!!Privacy Statement", "end": { "column": 3, - "line": 137 + "line": 138 }, "file": "src/lib/Menu.js", "id": "menu.help.privacy", "start": { "column": 11, - "line": 134 + "line": 135 } }, { "defaultMessage": "!!!File", "end": { "column": 3, - "line": 141 + "line": 142 }, "file": "src/lib/Menu.js", "id": "menu.file", "start": { "column": 8, - "line": 138 + "line": 139 } }, { "defaultMessage": "!!!View", "end": { "column": 3, - "line": 145 + "line": 146 }, "file": "src/lib/Menu.js", "id": "menu.view", "start": { "column": 8, - "line": 142 + "line": 143 } }, { "defaultMessage": "!!!Services", "end": { "column": 3, - "line": 149 + "line": 150 }, "file": "src/lib/Menu.js", "id": "menu.services", "start": { "column": 12, - "line": 146 + "line": 147 } }, { "defaultMessage": "!!!Window", "end": { "column": 3, - "line": 153 + "line": 154 }, "file": "src/lib/Menu.js", "id": "menu.window", "start": { "column": 10, - "line": 150 + "line": 151 } }, { "defaultMessage": "!!!Help", "end": { "column": 3, - "line": 157 + "line": 158 }, "file": "src/lib/Menu.js", "id": "menu.help", "start": { "column": 8, - "line": 154 + "line": 155 } }, { "defaultMessage": "!!!About Franz", "end": { "column": 3, - "line": 161 + "line": 162 }, "file": "src/lib/Menu.js", "id": "menu.app.about", "start": { "column": 9, - "line": 158 + "line": 159 } }, { "defaultMessage": "!!!What's new?", "end": { "column": 3, - "line": 165 + "line": 166 }, "file": "src/lib/Menu.js", "id": "menu.app.announcement", "start": { "column": 16, - "line": 162 + "line": 163 } }, { "defaultMessage": "!!!Settings", "end": { "column": 3, - "line": 169 + "line": 170 }, "file": "src/lib/Menu.js", "id": "menu.app.settings", "start": { "column": 12, - "line": 166 + "line": 167 } }, { "defaultMessage": "!!!Hide", "end": { "column": 3, - "line": 173 + "line": 174 }, "file": "src/lib/Menu.js", "id": "menu.app.hide", "start": { "column": 8, - "line": 170 + "line": 171 } }, { "defaultMessage": "!!!Hide Others", "end": { "column": 3, - "line": 177 + "line": 178 }, "file": "src/lib/Menu.js", "id": "menu.app.hideOthers", "start": { "column": 14, - "line": 174 + "line": 175 } }, { "defaultMessage": "!!!Unhide", "end": { "column": 3, - "line": 181 + "line": 182 }, "file": "src/lib/Menu.js", "id": "menu.app.unhide", "start": { "column": 10, - "line": 178 + "line": 179 } }, { "defaultMessage": "!!!Quit", "end": { "column": 3, - "line": 185 + "line": 186 }, "file": "src/lib/Menu.js", "id": "menu.app.quit", "start": { "column": 8, - "line": 182 + "line": 183 } }, { "defaultMessage": "!!!Add New Service...", "end": { "column": 3, - "line": 189 + "line": 190 }, "file": "src/lib/Menu.js", "id": "menu.services.addNewService", "start": { "column": 17, - "line": 186 + "line": 187 } }, { "defaultMessage": "!!!Add New Workspace...", "end": { "column": 3, - "line": 193 + "line": 194 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.addNewWorkspace", "start": { "column": 19, - "line": 190 + "line": 191 } }, { "defaultMessage": "!!!Open workspace drawer", "end": { "column": 3, - "line": 197 + "line": 198 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.openWorkspaceDrawer", "start": { "column": 23, - "line": 194 + "line": 195 } }, { "defaultMessage": "!!!Close workspace drawer", "end": { "column": 3, - "line": 201 + "line": 202 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.closeWorkspaceDrawer", "start": { "column": 24, - "line": 198 + "line": 199 } }, { "defaultMessage": "!!!Activate next service...", "end": { "column": 3, - "line": 205 + "line": 206 }, "file": "src/lib/Menu.js", "id": "menu.services.setNextServiceActive", "start": { "column": 23, - "line": 202 + "line": 203 } }, { "defaultMessage": "!!!Activate previous service...", "end": { "column": 3, - "line": 209 + "line": 210 }, "file": "src/lib/Menu.js", "id": "menu.services.activatePreviousService", "start": { "column": 27, - "line": 206 + "line": 207 } }, { "defaultMessage": "!!!Disable notifications & audio", "end": { "column": 3, - "line": 213 + "line": 214 }, "file": "src/lib/Menu.js", "id": "sidebar.muteApp", "start": { "column": 11, - "line": 210 + "line": 211 } }, { "defaultMessage": "!!!Enable notifications & audio", "end": { "column": 3, - "line": 217 + "line": 218 }, "file": "src/lib/Menu.js", "id": "sidebar.unmuteApp", "start": { "column": 13, - "line": 214 + "line": 215 } }, { "defaultMessage": "!!!Workspaces", "end": { "column": 3, - "line": 221 + "line": 222 }, "file": "src/lib/Menu.js", "id": "menu.workspaces", "start": { "column": 14, - "line": 218 + "line": 219 } }, { "defaultMessage": "!!!Default", "end": { "column": 3, - "line": 225 + "line": 226 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.defaultWorkspace", "start": { "column": 20, - "line": 222 + "line": 223 } } ], diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index a2ce34cd4..2adf5b787 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": 14, + "line": 15, "column": 8 }, "end": { - "line": 17, + "line": 18, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Undo", "file": "src/lib/Menu.js", "start": { - "line": 18, + "line": 19, "column": 8 }, "end": { - "line": 21, + "line": 22, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Redo", "file": "src/lib/Menu.js", "start": { - "line": 22, + "line": 23, "column": 8 }, "end": { - "line": 25, + "line": 26, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Cut", "file": "src/lib/Menu.js", "start": { - "line": 26, + "line": 27, "column": 7 }, "end": { - "line": 29, + "line": 30, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Copy", "file": "src/lib/Menu.js", "start": { - "line": 30, + "line": 31, "column": 8 }, "end": { - "line": 33, + "line": 34, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Paste", "file": "src/lib/Menu.js", "start": { - "line": 34, + "line": 35, "column": 9 }, "end": { - "line": 37, + "line": 38, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Paste And Match Style", "file": "src/lib/Menu.js", "start": { - "line": 38, + "line": 39, "column": 22 }, "end": { - "line": 41, + "line": 42, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Delete", "file": "src/lib/Menu.js", "start": { - "line": 42, + "line": 43, "column": 10 }, "end": { - "line": 45, + "line": 46, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Select All", "file": "src/lib/Menu.js", "start": { - "line": 46, + "line": 47, "column": 13 }, "end": { - "line": 49, + "line": 50, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Speech", "file": "src/lib/Menu.js", "start": { - "line": 50, + "line": 51, "column": 10 }, "end": { - "line": 53, + "line": 54, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Start Speaking", "file": "src/lib/Menu.js", "start": { - "line": 54, + "line": 55, "column": 17 }, "end": { - "line": 57, + "line": 58, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Stop Speaking", "file": "src/lib/Menu.js", "start": { - "line": 58, + "line": 59, "column": 16 }, "end": { - "line": 61, + "line": 62, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Start Dictation", "file": "src/lib/Menu.js", "start": { - "line": 62, + "line": 63, "column": 18 }, "end": { - "line": 65, + "line": 66, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Emoji & Symbols", "file": "src/lib/Menu.js", "start": { - "line": 66, + "line": 67, "column": 16 }, "end": { - "line": 69, + "line": 70, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Actual Size", "file": "src/lib/Menu.js", "start": { - "line": 70, + "line": 71, "column": 13 }, "end": { - "line": 73, + "line": 74, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Zoom In", "file": "src/lib/Menu.js", "start": { - "line": 74, + "line": 75, "column": 10 }, "end": { - "line": 77, + "line": 78, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Zoom Out", "file": "src/lib/Menu.js", "start": { - "line": 78, + "line": 79, "column": 11 }, "end": { - "line": 81, + "line": 82, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Enter Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 82, + "line": 83, "column": 19 }, "end": { - "line": 85, + "line": 86, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Exit Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 86, + "line": 87, "column": 18 }, "end": { - "line": 89, + "line": 90, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Toggle Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 90, + "line": 91, "column": 20 }, "end": { - "line": 93, + "line": 94, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Toggle Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 94, + "line": 95, "column": 18 }, "end": { - "line": 97, + "line": 98, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 98, + "line": 99, "column": 25 }, "end": { - "line": 101, + "line": 102, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 102, + "line": 103, "column": 17 }, "end": { - "line": 105, + "line": 106, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 106, + "line": 107, "column": 15 }, "end": { - "line": 109, + "line": 110, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 110, + "line": 111, "column": 12 }, "end": { - "line": 113, + "line": 114, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 114, + "line": 115, "column": 9 }, "end": { - "line": 117, + "line": 118, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 118, + "line": 119, "column": 13 }, "end": { - "line": 121, + "line": 122, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 122, + "line": 123, "column": 13 }, "end": { - "line": 125, + "line": 126, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 126, + "line": 127, "column": 11 }, "end": { - "line": 129, + "line": 130, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 130, + "line": 131, "column": 7 }, "end": { - "line": 133, + "line": 134, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 134, + "line": 135, "column": 11 }, "end": { - "line": 137, + "line": 138, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 138, + "line": 139, "column": 8 }, "end": { - "line": 141, + "line": 142, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 142, + "line": 143, "column": 8 }, "end": { - "line": 145, + "line": 146, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 146, + "line": 147, "column": 12 }, "end": { - "line": 149, + "line": 150, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 150, + "line": 151, "column": 10 }, "end": { - "line": 153, + "line": 154, "column": 3 } }, @@ -459,11 +459,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 154, + "line": 155, "column": 8 }, "end": { - "line": 157, + "line": 158, "column": 3 } }, @@ -472,11 +472,11 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 158, + "line": 159, "column": 9 }, "end": { - "line": 161, + "line": 162, "column": 3 } }, @@ -485,11 +485,11 @@ "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 162, + "line": 163, "column": 16 }, "end": { - "line": 165, + "line": 166, "column": 3 } }, @@ -498,11 +498,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 166, + "line": 167, "column": 12 }, "end": { - "line": 169, + "line": 170, "column": 3 } }, @@ -511,11 +511,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 170, + "line": 171, "column": 8 }, "end": { - "line": 173, + "line": 174, "column": 3 } }, @@ -524,11 +524,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 174, + "line": 175, "column": 14 }, "end": { - "line": 177, + "line": 178, "column": 3 } }, @@ -537,11 +537,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 178, + "line": 179, "column": 10 }, "end": { - "line": 181, + "line": 182, "column": 3 } }, @@ -550,11 +550,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 182, + "line": 183, "column": 8 }, "end": { - "line": 185, + "line": 186, "column": 3 } }, @@ -563,11 +563,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 186, + "line": 187, "column": 17 }, "end": { - "line": 189, + "line": 190, "column": 3 } }, @@ -576,11 +576,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 190, + "line": 191, "column": 19 }, "end": { - "line": 193, + "line": 194, "column": 3 } }, @@ -589,11 +589,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 194, + "line": 195, "column": 23 }, "end": { - "line": 197, + "line": 198, "column": 3 } }, @@ -602,11 +602,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 198, + "line": 199, "column": 24 }, "end": { - "line": 201, + "line": 202, "column": 3 } }, @@ -615,11 +615,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 202, + "line": 203, "column": 23 }, "end": { - "line": 205, + "line": 206, "column": 3 } }, @@ -628,11 +628,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 206, + "line": 207, "column": 27 }, "end": { - "line": 209, + "line": 210, "column": 3 } }, @@ -641,11 +641,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 210, + "line": 211, "column": 11 }, "end": { - "line": 213, + "line": 214, "column": 3 } }, @@ -654,11 +654,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 214, + "line": 215, "column": 13 }, "end": { - "line": 217, + "line": 218, "column": 3 } }, @@ -667,11 +667,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 218, + "line": 219, "column": 14 }, "end": { - "line": 221, + "line": 222, "column": 3 } }, @@ -680,11 +680,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 222, + "line": 223, "column": 20 }, "end": { - "line": 225, + "line": 226, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 6bea67860..da2540274 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -7,6 +7,7 @@ import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../features/workspaces/i import { workspaceActions } from '../features/workspaces/actions'; import { gaEvent } from './analytics'; import { announcementActions } from '../features/announcements/actions'; +import { announcementsStore } from '../features/announcements'; const { app, Menu, dialog } = remote; @@ -357,6 +358,7 @@ const _templateFactory = intl => [ click: () => { announcementActions.show(); }, + visible: window.franz.stores.user.isLoggedIn && announcementsStore.areNewsAvailable, }, { type: 'separator', -- cgit v1.2.3-70-g09d2