From 5d6164973e92fa8a3e3c18a0eb2e29494aea4f48 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Sun, 9 Dec 2018 20:48:25 +0100 Subject: Fix linting issues --- .eslintrc | 20 +++++++++++++++- src/api/server/ServerApi.js | 13 +++++------ src/app.js | 4 +++- src/components/auth/AuthLayout.js | 6 ++--- src/components/auth/Invite.js | 26 ++++++++++++--------- src/components/auth/Login.js | 6 ++--- src/components/auth/Pricing.js | 23 ++++++++++-------- src/components/auth/Signup.js | 3 ++- src/components/layout/AppLayout.js | 6 +++-- src/components/layout/Sidebar.js | 3 +++ .../content/ErrorHandlers/WebviewErrorHandler.js | 9 +++++++- src/components/services/content/ServiceDisabled.js | 1 + src/components/services/content/ServiceWebview.js | 9 ++++---- src/components/services/content/Services.js | 3 +-- .../services/content/WebviewCrashHandler.js | 24 +++++++++++-------- src/components/services/tabs/Tabbar.js | 2 +- src/components/settings/SettingsLayout.js | 2 ++ .../settings/account/AccountDashboard.js | 4 +++- .../settings/navigation/SettingsNavigation.js | 5 ++-- src/components/settings/recipes/RecipeItem.js | 1 + .../settings/recipes/RecipesDashboard.js | 10 ++++++-- .../settings/services/EditServiceForm.js | 1 + src/components/settings/services/ServiceItem.js | 1 + .../settings/settings/EditSettingsForm.js | 8 +++++-- src/components/settings/user/EditUserForm.js | 4 ---- src/components/subscription/SubscriptionForm.js | 3 +-- src/components/subscription/SubscriptionPopup.js | 4 +++- src/components/ui/AppLoader/index.js | 11 ++++----- src/components/ui/Button.js | 3 +++ src/components/ui/FullscreenLoader/index.js | 7 +++--- src/components/ui/ImageUpload.js | 4 ++-- src/components/ui/InfoBar.js | 4 +++- src/components/ui/Infobox.js | 2 ++ src/components/ui/Input.js | 6 ++--- src/components/ui/Link.js | 1 - src/components/ui/PremiumFeatureContainer/index.js | 1 - src/components/ui/Radio.js | 4 ++-- src/components/ui/SearchInput.js | 27 +++++++++++----------- src/components/ui/Select.js | 1 - src/components/ui/StatusBarTargetUrl.js | 3 +-- src/components/util/ErrorBoundary/index.js | 18 ++++++++++----- src/components/util/ErrorBoundary/styles.js | 4 ++-- src/containers/auth/AuthLayoutContainer.js | 4 +++- src/containers/settings/RecipesScreen.js | 10 ++++---- .../subscription/SubscriptionFormScreen.js | 2 +- src/electron/Settings.js | 1 + src/electron/ipc-api/download.js | 2 +- src/features/delayApp/Component.js | 19 ++++++++------- src/features/delayApp/index.js | 1 - src/features/serviceProxy/index.js | 1 - src/helpers/i18n-helpers.js | 4 +++- src/index.js | 8 +++++-- src/lib/Tray.js | 10 +++++--- src/models/News.js | 3 +++ src/models/Order.js | 5 ++++ src/models/Plan.js | 1 + src/models/Recipe.js | 12 ++++++++++ src/models/RecipePreview.js | 6 ++++- src/models/Service.js | 21 +++++++++++++++++ src/models/User.js | 17 +++++++++++++- src/stores/AppStore.js | 16 +++++++++---- src/stores/FeaturesStore.js | 1 + src/stores/GlobalErrorStore.js | 1 + src/stores/NewsStore.js | 1 + src/stores/PaymentStore.js | 3 +++ src/stores/RecipePreviewsStore.js | 2 ++ src/stores/RecipesStore.js | 2 ++ src/stores/RequestStore.js | 3 +++ src/stores/ServicesStore.js | 9 +++++++- src/stores/SettingsStore.js | 2 ++ src/stores/UserStore.js | 23 +++++++++++++++++- src/stores/lib/CachedRequest.js | 1 + src/stores/lib/Reaction.js | 2 ++ src/stores/lib/Request.js | 8 +++++++ src/stores/lib/Store.js | 4 ++++ src/styles/searchInput.scss | 4 ++++ src/theme/dark/index.js | 1 - src/theme/default/index.js | 1 - src/webview/contextMenu.js | 4 +++- src/webview/recipe.js | 3 ++- 80 files changed, 366 insertions(+), 149 deletions(-) diff --git a/.eslintrc b/.eslintrc index 948550306..1843e560e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,6 +14,8 @@ "extensions": [".js", ".jsx"] }], "react/forbid-prop-types": 1, + "react/destructuring-assignment": 1, + "prefer-destructuring": 1, "no-underscore-dangle": 0, "max-len": 0, "class-methods-use-this": 0, @@ -21,7 +23,23 @@ "react/jsx-no-bind": 0, "jsx-a11y/no-static-element-interactions": 0, "react/jsx-no-target-blank": 0, - "no-restricted-syntax": [0, "ForInStatement"] + "no-restricted-syntax": [0, "ForInStatement"], + "jsx-a11y/no-noninteractive-element-interactions": 1, + "jsx-a11y/label-has-for": [ + 2, + { + "components": [ + "Label" + ], + "required": { + "every": [ + "id" + ] + }, + "allowChildren": false + } + ], + "jsx-a11y/click-events-have-key-events": 1 }, "globals": { "window": true, diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index 164419951..2871769a9 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js @@ -42,6 +42,7 @@ const API_VERSION = 'v1'; export default class ServerApi { recipePreviews = []; + recipes = []; // User @@ -522,8 +523,7 @@ export default class ServerApi { const request = await window.fetch(`${SERVER_URL}/${API_VERSION}/recipes/${s.service}`, this._prepareAuthRequest({ method: 'GET', - }), - ); + })); if (request.status === 200) { const data = await request.json(); @@ -549,9 +549,9 @@ export default class ServerApi { await this._bulkRecipeCheck(recipes); - return Promise.all(services - .map(async service => await this._prepareServiceModel(service)) // eslint-disable-line - ); + /* eslint-disable no-return-await */ + return Promise.all(services.map(async service => await this._prepareServiceModel(service))); + /* eslint-enable no-return-await */ } async _prepareServiceModel(service) { @@ -596,8 +596,7 @@ export default class ServerApi { } return recipe; - }), - ).catch(err => console.error('Can\'t load recipe', err)); + })).catch(err => console.error('Can\'t load recipe', err)); } _mapRecipePreviewModel(recipes) { diff --git a/src/app.js b/src/app.js index 43d0cf018..831dd93ce 100644 --- a/src/app.js +++ b/src/app.js @@ -4,7 +4,9 @@ import React from 'react'; import { render } from 'react-dom'; import { Provider } from 'mobx-react'; import { syncHistoryWithStore, RouterStore } from 'mobx-react-router'; -import { Router, Route, hashHistory, IndexRedirect } from 'react-router'; +import { + Router, Route, hashHistory, IndexRedirect, +} from 'react-router'; import '@babel/polyfill'; import smoothScroll from 'smoothscroll-polyfill'; diff --git a/src/components/auth/AuthLayout.js b/src/components/auth/AuthLayout.js index 4e1b0c52e..ac8fdbe5b 100644 --- a/src/components/auth/AuthLayout.js +++ b/src/components/auth/AuthLayout.js @@ -15,7 +15,6 @@ import { isWindows } from '../../environment'; export default @observer class AuthLayout extends Component { static propTypes = { children: oneOrManyChildElements.isRequired, - pathname: PropTypes.string.isRequired, error: globalErrorPropType.isRequired, isOnline: PropTypes.bool.isRequired, isAPIHealthy: PropTypes.bool.isRequired, @@ -32,7 +31,6 @@ export default @observer class AuthLayout extends Component { render() { const { children, - pathname, error, isOnline, isAPIHealthy, @@ -45,8 +43,8 @@ export default @observer class AuthLayout extends Component { return (
- {isWindows && !isFullScreen && } -
+ {isWindows && !isFullScreen && } +
{!isOnline && ( this.submit(e)}> - {!embed && ()} + {!embed && ( + + )}

{intl.formatMessage(messages.headline)}

@@ -164,12 +166,14 @@ export default @observer class Invite extends Component { label={intl.formatMessage(messages.submitButtonLabel)} loaded={!isLoadingInvite} /> - {!embed && ( - {intl.formatMessage(messages.skipButtonLabel)} - )} + {!embed && ( + + {intl.formatMessage(messages.skipButtonLabel)} + + )} ); diff --git a/src/components/auth/Login.js b/src/components/auth/Login.js index 2cf614041..5d21f8b60 100644 --- a/src/components/auth/Login.js +++ b/src/components/auth/Login.js @@ -83,18 +83,18 @@ export default @observer class Login extends Component { }, }, this.context.intl); + emailField = null; + submit(e) { e.preventDefault(); this.form.submit({ onSuccess: (form) => { this.props.onSubmit(form.values()); }, - onError: () => {}, + onError: () => { }, }); } - emailField = null; - render() { const { form } = this; const { intl } = this.context; diff --git a/src/components/auth/Pricing.js b/src/components/auth/Pricing.js index f08129568..7ab14f429 100644 --- a/src/components/auth/Pricing.js +++ b/src/components/auth/Pricing.js @@ -69,18 +69,29 @@ export default @observer class Signup extends Component { donor.amount ? (

- Thank you so much for your previous donation of $ {donor.amount}. + Thank you so much for your previous donation of + {' '} + + $ + {donor.amount} + + .
Your support allowed us to get where we are today.

- As an early supporter, you get a lifetime premium supporter license without any + As an early supporter, you get + {' '} + a lifetime premium supporter license + {' '} + without any additional charges.

However, If you want to keep supporting us, you are more than welcome to subscribe to a plan. -

+
+

) : ( @@ -113,12 +124,6 @@ export default @observer class Signup extends Component { hideInfo={Boolean(donor.amount)} skipButtonLabel={intl.formatMessage(messages.skipPayment)} /> - {/* - {intl.formatMessage(messages.skipPayment)} - */} diff --git a/src/components/auth/Signup.js b/src/components/auth/Signup.js index bbcad8b67..d9b83eeb8 100644 --- a/src/components/auth/Signup.js +++ b/src/components/auth/Signup.js @@ -199,7 +199,8 @@ export default @observer class Signup extends Component { className="link" > {intl.formatMessage(messages.privacy)} - . + + .

diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index e526f6b1f..dbe0bb4b6 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js @@ -99,7 +99,7 @@ export default @observer class AppLayout extends Component {
- {isWindows && !isFullScreen && } + {isWindows && !isFullScreen && }
{sidebar}
@@ -153,7 +153,9 @@ export default @observer class AppLayout extends Component { sticky > - {intl.formatMessage(messages.updateAvailable)} + {intl.formatMessage(messages.updateAvailable)} + {' '} + {intl.formatMessage(messages.changelog)} diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 6ea95bf88..609a3b604 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js @@ -65,6 +65,7 @@ export default @observer class Sidebar extends Component { disableToolTip={() => this.disableToolTip()} />
); } diff --git a/src/components/services/tabs/Tabbar.js b/src/components/services/tabs/Tabbar.js index 27f555428..dd5c2140f 100644 --- a/src/components/services/tabs/Tabbar.js +++ b/src/components/services/tabs/Tabbar.js @@ -1,4 +1,4 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; diff --git a/src/components/settings/SettingsLayout.js b/src/components/settings/SettingsLayout.js index d5d8f0bb0..72ba7b2e3 100644 --- a/src/components/settings/SettingsLayout.js +++ b/src/components/settings/SettingsLayout.js @@ -39,6 +39,7 @@ export default @observer class SettingsLayout extends Component {
{/* )} */} diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js index a7c656acd..fac25c160 100644 --- a/src/components/settings/services/EditServiceForm.js +++ b/src/components/settings/services/EditServiceForm.js @@ -130,6 +130,7 @@ export default @observer class EditServiceForm extends Component { static defaultProps = { service: {}, }; + static contextTypes = { intl: intlShape, }; diff --git a/src/components/settings/services/ServiceItem.js b/src/components/settings/services/ServiceItem.js index 84080519b..ebc618a00 100644 --- a/src/components/settings/services/ServiceItem.js +++ b/src/components/settings/services/ServiceItem.js @@ -27,6 +27,7 @@ export default @observer class ServiceItem extends Component { service: PropTypes.instanceOf(ServiceModel).isRequired, goToServiceForm: PropTypes.func.isRequired, }; + static contextTypes = { intl: intlShape, }; diff --git a/src/components/settings/settings/EditSettingsForm.js b/src/components/settings/settings/EditSettingsForm.js index df3197520..a92e559f3 100644 --- a/src/components/settings/settings/EditSettingsForm.js +++ b/src/components/settings/settings/EditSettingsForm.js @@ -185,7 +185,9 @@ export default @observer class EditSettingsForm extends Component { target="_blank" className="link" > - {intl.formatMessage(messages.translationHelp)} + {intl.formatMessage(messages.translationHelp)} + {' '} + {/* Advanced */} @@ -233,7 +235,9 @@ export default @observer class EditSettingsForm extends Component { )}
- {intl.formatMessage(messages.currentVersion)} {remote.app.getVersion()} + {intl.formatMessage(messages.currentVersion)} + {' '} + {remote.app.getVersion()}
diff --git a/src/components/settings/user/EditUserForm.js b/src/components/settings/user/EditUserForm.js index b825f844a..0e3ac6b10 100644 --- a/src/components/settings/user/EditUserForm.js +++ b/src/components/settings/user/EditUserForm.js @@ -48,10 +48,6 @@ export default @observer class EditServiceForm extends Component { isEnterprise: PropTypes.bool.isRequired, }; - static defaultProps = { - service: {}, - }; - static contextTypes = { intl: intlShape, }; diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js index 6b60c2af0..90da8ddc3 100644 --- a/src/components/subscription/SubscriptionForm.js +++ b/src/components/subscription/SubscriptionForm.js @@ -81,8 +81,7 @@ export default @observer class SubscriptionForm extends Component { hideInfo: PropTypes.bool.isRequired, }; - static defaultProps ={ - content: '', + static defaultProps = { showSkipOption: false, skipAction: () => null, skipButtonLabel: '', diff --git a/src/components/subscription/SubscriptionPopup.js b/src/components/subscription/SubscriptionPopup.js index f3c63e7ee..b5d7c4b2d 100644 --- a/src/components/subscription/SubscriptionPopup.js +++ b/src/components/subscription/SubscriptionPopup.js @@ -46,7 +46,9 @@ export default @observer class SubscriptionPopup extends Component { } render() { - const { url, closeWindow, completeCheck, isCompleted } = this.props; + const { + url, closeWindow, completeCheck, isCompleted, + } = this.props; const { intl } = this.context; return ( diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js index 31db3d52c..1b9d044f4 100644 --- a/src/components/ui/AppLoader/index.js +++ b/src/components/ui/AppLoader/index.js @@ -28,11 +28,13 @@ export default @injectSheet(styles) class AppLoader extends Component { step: 0, } + interval = null; + componentDidMount() { this.interval = setInterval(() => { - this.setState({ - step: this.state.step === textList.length - 1 ? 0 : this.state.step + 1, - }); + this.setState(prevState => ({ + step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, + })); }, 2500); } @@ -40,8 +42,6 @@ export default @injectSheet(styles) class AppLoader extends Component { clearInterval(this.interval); } - interval = null; - render() { const { classes } = this.props; const { step } = this.state; @@ -66,4 +66,3 @@ export default @injectSheet(styles) class AppLoader extends Component { ); } } - diff --git a/src/components/ui/Button.js b/src/components/ui/Button.js index 309e05bb4..ffc7f7051 100644 --- a/src/components/ui/Button.js +++ b/src/components/ui/Button.js @@ -62,6 +62,8 @@ export default @observer class Button extends Component { } return ( + // disabling rule as button has type defined in `buttonProps` + /* eslint-disable react/button-has-type */ + /* eslint-enable react/button-has-type */ ); } } diff --git a/src/components/ui/FullscreenLoader/index.js b/src/components/ui/FullscreenLoader/index.js index 36cd32d2a..e0a24a527 100644 --- a/src/components/ui/FullscreenLoader/index.js +++ b/src/components/ui/FullscreenLoader/index.js @@ -7,7 +7,9 @@ import Loader from '../Loader'; import styles from './styles'; -export default inject('stores')(injectSheet(styles)(({ stores, classes, className, title, children }) => ( +export default inject('stores')(injectSheet(styles)(({ + stores, classes, className, title, children, +}) => (
-), -)); +))); diff --git a/src/components/ui/ImageUpload.js b/src/components/ui/ImageUpload.js index cbe70ac88..83a05554b 100644 --- a/src/components/ui/ImageUpload.js +++ b/src/components/ui/ImageUpload.js @@ -23,6 +23,8 @@ export default @observer class ImageUpload extends Component { path: null, } + dropzoneRef = null; + onDrop(acceptedFiles) { const { field } = this.props; @@ -36,8 +38,6 @@ export default @observer class ImageUpload extends Component { field.set(''); } - dropzoneRef = null; - render() { const { field, diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js index 94a1ddf76..612399e9f 100644 --- a/src/components/ui/InfoBar.js +++ b/src/components/ui/InfoBar.js @@ -5,7 +5,7 @@ import classnames from 'classnames'; import Loader from 'react-loader'; // import { oneOrManyChildElements } from '../../prop-types'; -import Appear from '../ui/effects/Appear'; +import Appear from './effects/Appear'; export default @observer class InfoBar extends Component { static propTypes = { @@ -64,6 +64,7 @@ export default @observer class InfoBar extends Component { {children} {ctaLabel && (
{!sticky && (
); @@ -51,4 +57,4 @@ export default @injectSheet(styles) class ErrorBoundary extends Component { return this.props.children; } -} \ No newline at end of file +} diff --git a/src/components/util/ErrorBoundary/styles.js b/src/components/util/ErrorBoundary/styles.js index 8d62767f6..0960546ff 100644 --- a/src/components/util/ErrorBoundary/styles.js +++ b/src/components/util/ErrorBoundary/styles.js @@ -1,4 +1,4 @@ -export default (theme) => ({ +export default theme => ({ component: { display: 'flex', width: '100%', @@ -9,5 +9,5 @@ export default (theme) => ({ title: { fontSize: 20, color: theme.colorText, - } + }, }); diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js index b73598f3d..762929dc6 100644 --- a/src/containers/auth/AuthLayoutContainer.js +++ b/src/containers/auth/AuthLayoutContainer.js @@ -18,7 +18,9 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer }; render() { - const { stores, actions, children, location } = this.props; + const { + stores, actions, children, location, + } = this.props; const { app, features, globalError } = stores; const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting diff --git a/src/containers/settings/RecipesScreen.js b/src/containers/settings/RecipesScreen.js index 1f05b6510..b3d758c87 100644 --- a/src/containers/settings/RecipesScreen.js +++ b/src/containers/settings/RecipesScreen.js @@ -16,7 +16,7 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend static propTypes = { params: PropTypes.shape({ filter: PropTypes.string, - }).isRequired, + }), }; static defaultProps = { @@ -30,6 +30,8 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend currentFilter: 'featured', }; + autorunDisposer = null; + componentDidMount() { gaPage('Settings/Recipe Dashboard/Featured'); @@ -55,8 +57,6 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend this.autorunDisposer(); } - autorunDisposer = null; - searchRecipes(needle) { if (needle === '') { this.resetSearch(); @@ -72,7 +72,9 @@ export default @inject('stores', 'actions') @observer class RecipesScreen extend } render() { - const { recipePreviews, recipes, services, user } = this.props.stores; + const { + recipePreviews, recipes, services, user, + } = this.props.stores; const { showAddServiceInterface } = this.props.actions.service; const { filter } = this.props.params; diff --git a/src/containers/subscription/SubscriptionFormScreen.js b/src/containers/subscription/SubscriptionFormScreen.js index 50ed19bef..3eb7b6255 100644 --- a/src/containers/subscription/SubscriptionFormScreen.js +++ b/src/containers/subscription/SubscriptionFormScreen.js @@ -12,7 +12,7 @@ const { BrowserWindow } = remote; export default @inject('stores', 'actions') @observer class SubscriptionFormScreen extends Component { static propTypes = { onCloseWindow: PropTypes.func, - content: PropTypes.oneOrManyChildElements, + content: PropTypes.node, showSkipOption: PropTypes.bool, skipAction: PropTypes.func, skipButtonLabel: PropTypes.string, diff --git a/src/electron/Settings.js b/src/electron/Settings.js index ed9733bfe..63f43b6b7 100644 --- a/src/electron/Settings.js +++ b/src/electron/Settings.js @@ -8,6 +8,7 @@ const debug = require('debug')('Franz:Settings'); export default class Settings { type = ''; + @observable store = {}; constructor(type, defaultState = {}) { diff --git a/src/electron/ipc-api/download.js b/src/electron/ipc-api/download.js index 9e504834d..e6703af2d 100644 --- a/src/electron/ipc-api/download.js +++ b/src/electron/ipc-api/download.js @@ -12,7 +12,7 @@ function decodeBase64Image(dataString) { return new Error('Invalid input string'); } - return new Buffer(matches[2], 'base64'); + return Buffer.from(matches[2], 'base64'); } export default (params) => { diff --git a/src/features/delayApp/Component.js b/src/features/delayApp/Component.js index 403340c7b..5c6ceaf86 100644 --- a/src/features/delayApp/Component.js +++ b/src/features/delayApp/Component.js @@ -6,7 +6,7 @@ import injectSheet from 'react-jss'; import Button from '../../components/ui/Button'; -import { config } from './'; +import { config } from '.'; import styles from './styles'; const messages = defineMessages({ @@ -38,10 +38,14 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp countdown: config.delayDuration, } + countdownInterval = null; + + countdownIntervalTimeout = 1000; + componentDidMount() { this.countdownInterval = setInterval(() => { this.setState({ - countdown: this.state.countdown - this.countdownIntervalTimeout, + countdown: prevState => ({ value: prevState.countdown - this.countdownIntervalTimeout }), }); if (this.state.countdown <= 0) { @@ -55,9 +59,6 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp clearInterval(this.countdownInterval); } - countdownInterval = null; - countdownIntervalTimeout = 1000; - render() { const { classes, actions } = this.props; const { intl } = this.context; @@ -71,9 +72,11 @@ export default @inject('actions') @injectSheet(styles) @observer class DelayApp buttonType="inverted" onClick={() => actions.ui.openSettings({ path: 'user' })} /> -

{intl.formatMessage(messages.text, { - seconds: this.state.countdown / 1000, - })}

+

+ {intl.formatMessage(messages.text, { + seconds: this.state.countdown / 1000, + })} +

); } diff --git a/src/features/delayApp/index.js b/src/features/delayApp/index.js index 9ffa1d2fd..d5c544b78 100644 --- a/src/features/delayApp/index.js +++ b/src/features/delayApp/index.js @@ -67,4 +67,3 @@ export default function init(stores) { } export const Component = DelayAppComponent; - diff --git a/src/features/serviceProxy/index.js b/src/features/serviceProxy/index.js index acd8f162f..d46f9e6f1 100644 --- a/src/features/serviceProxy/index.js +++ b/src/features/serviceProxy/index.js @@ -45,4 +45,3 @@ export default function init(stores) { }); }); } - diff --git a/src/helpers/i18n-helpers.js b/src/helpers/i18n-helpers.js index 026a220e0..091b86b06 100644 --- a/src/helpers/i18n-helpers.js +++ b/src/helpers/i18n-helpers.js @@ -1,4 +1,6 @@ -export function getLocale({ locale, locales, defaultLocale, fallbackLocale }) { +export function getLocale({ + locale, locales, defaultLocale, fallbackLocale, +}) { let localeStr = locale; if (locales[locale] === undefined) { let localeFuzzy; diff --git a/src/index.js b/src/index.js index 7f3fe5b44..830166dcf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,14 @@ -import { app, BrowserWindow, shell, ipcMain } from 'electron'; +import { + app, BrowserWindow, shell, ipcMain, +} from 'electron'; import fs from 'fs-extra'; import path from 'path'; import windowStateKeeper from 'electron-window-state'; -import { isDevMode, isMac, isWindows, isLinux } from './environment'; +import { + isDevMode, isMac, isWindows, isLinux, +} from './environment'; // DEV MODE: Save user data into FranzDev if (isDevMode) { diff --git a/src/lib/Tray.js b/src/lib/Tray.js index 588fa75bf..669b02709 100644 --- a/src/lib/Tray.js +++ b/src/lib/Tray.js @@ -1,4 +1,6 @@ -import { app, Tray, Menu, systemPreferences, nativeImage } from 'electron'; +import { + app, Tray, Menu, systemPreferences, nativeImage, +} from 'electron'; import path from 'path'; const FILE_EXTENSION = process.platform === 'win32' ? 'ico' : 'png'; @@ -7,7 +9,9 @@ const INDICATOR_TRAY_UNREAD = 'tray-unread'; export default class TrayIcon { trayIcon = null; + indicator = 0; + themeChangeSubscriberId = null; show() { @@ -79,7 +83,7 @@ export default class TrayIcon { } return nativeImage.createFromPath(path.join( - __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`), - ); + __dirname, '..', 'assets', 'images', type, platform, `${asset}.${FILE_EXTENSION}`, + )); } } diff --git a/src/models/News.js b/src/models/News.js index caf1d70e5..acacb97dd 100644 --- a/src/models/News.js +++ b/src/models/News.js @@ -2,8 +2,11 @@ export default class News { id = ''; + message = ''; + type = 'primary'; + sticky = false; constructor(data) { diff --git a/src/models/Order.js b/src/models/Order.js index 0e10b01d6..f7624c627 100644 --- a/src/models/Order.js +++ b/src/models/Order.js @@ -1,9 +1,14 @@ export default class Order { id = ''; + subscriptionId = ''; + name = ''; + invoiceUrl = ''; + price = ''; + date = ''; constructor(data) { diff --git a/src/models/Plan.js b/src/models/Plan.js index c7b4a0962..3dedf0d5e 100644 --- a/src/models/Plan.js +++ b/src/models/Plan.js @@ -5,6 +5,7 @@ export default class Plan { id: '', price: 0, } + year = { id: '', price: 0, diff --git a/src/models/Recipe.js b/src/models/Recipe.js index 43c44514c..b0d60e75e 100644 --- a/src/models/Recipe.js +++ b/src/models/Recipe.js @@ -5,21 +5,33 @@ import path from 'path'; export default class Recipe { id = ''; + name = ''; + description = ''; + version = ''; + path = ''; serviceURL = ''; hasDirectMessages = true; + hasIndirectMessages = false; + hasNotificationSound = false; + hasTeamId = false; + hasPredefinedUrl = false; + hasCustomUrl = false; + hasHostedOption = false; + urlInputPrefix = ''; + urlInputSuffix = ''; message = ''; diff --git a/src/models/RecipePreview.js b/src/models/RecipePreview.js index 7470d757a..cfb22f860 100644 --- a/src/models/RecipePreview.js +++ b/src/models/RecipePreview.js @@ -2,8 +2,12 @@ export default class RecipePreview { id = ''; + name = ''; - icon = ''; // TODO: check if this isn't replaced by `icons` + + icon = ''; + + // TODO: check if this isn't replaced by `icons` featured = false; constructor(data) { diff --git a/src/models/Service.js b/src/models/Service.js index 5ec42af80..03aec773b 100644 --- a/src/models/Service.js +++ b/src/models/Service.js @@ -6,9 +6,13 @@ const debug = require('debug')('Franz:Service'); export default class Service { id = ''; + recipe = ''; + webview = null; + timer = null; + events = {}; isAttached = false; @@ -16,26 +20,43 @@ export default class Service { @observable isActive = false; // Is current webview active @observable name = ''; + @observable unreadDirectMessageCount = 0; + @observable unreadIndirectMessageCount = 0; @observable order = 99; + @observable isEnabled = true; + @observable isMuted = false; + @observable team = ''; + @observable customUrl = ''; + @observable isNotificationEnabled = true; + @observable isBadgeEnabled = true; + @observable isIndirectMessageBadgeEnabled = true; + @observable iconUrl = ''; + @observable hasCustomUploadedIcon = false; + @observable hasCrashed = false; + @observable isDarkModeEnabled = false; + @observable spellcheckerLanguage = null; @observable isFirstLoad = true; + @observable isLoading = true; + @observable isError = false; + @observable errorMessage = ''; constructor(data, recipe) { diff --git a/src/models/User.js b/src/models/User.js index 3e4aa187d..bec78fc16 100644 --- a/src/models/User.js +++ b/src/models/User.js @@ -2,19 +2,34 @@ import { observable } from 'mobx'; export default class User { id = null; + @observable email = null; + @observable firstname = null; + @observable lastname = null; + @observable organization = null; + @observable accountType = null; - @observable emailIsConfirmed = true; // better assume it's confirmed to avoid noise + + @observable emailIsConfirmed = true; + + // better assume it's confirmed to avoid noise @observable subscription = {}; + @observable isSubscriptionOwner = false; + @observable isPremium = false; + @observable beta = false; + @observable donor = {}; + @observable isDonor = false; + @observable isMiner = false; + @observable locale = false; constructor(data) { diff --git a/src/stores/AppStore.js b/src/stores/AppStore.js index 6f156a96d..dd4642d70 100644 --- a/src/stores/AppStore.js +++ b/src/stores/AppStore.js @@ -38,12 +38,15 @@ export default class AppStore extends Store { }; @observable healthCheckRequest = new Request(this.api.app, 'health'); + @observable getAppCacheSizeRequest = new Request(this.api.local, 'getAppCacheSize'); + @observable clearAppCacheRequest = new Request(this.api.local, 'clearAppCache'); @observable autoLaunchOnStart = true; @observable isOnline = navigator.onLine; + @observable timeOfflineStart; @observable updateStatus = null; @@ -150,19 +153,22 @@ export default class AppStore extends Store { key( '⌘+pagedown, ctrl+pagedown, ⌘+alt+right, ctrl+tab', () => { this.actions.service.setActiveNext(); - }); + }, + ); // Set active the prev service key( '⌘+pageup, ctrl+pageup, ⌘+alt+left, ctrl+shift+tab', () => { this.actions.service.setActivePrev(); - }); + }, + ); // Global Mute key( '⌘+shift+m ctrl+shift+m', () => { this.actions.app.toggleMuteApp(); - }); + }, + ); this.locale = this._getDefaultLocale(); @@ -182,7 +188,9 @@ export default class AppStore extends Store { } // Actions - @action _notify({ title, options, notificationId, serviceId = null }) { + @action _notify({ + title, options, notificationId, serviceId = null, + }) { if (this.stores.settings.all.app.isAppMuted) return; const notification = new window.Notification(title, options); diff --git a/src/stores/FeaturesStore.js b/src/stores/FeaturesStore.js index 10c893d3f..2a0713b6f 100644 --- a/src/stores/FeaturesStore.js +++ b/src/stores/FeaturesStore.js @@ -11,6 +11,7 @@ import { DEFAULT_FEATURES_CONFIG } from '../config'; export default class FeaturesStore extends Store { @observable defaultFeaturesRequest = new CachedRequest(this.api.features, 'default'); + @observable featuresRequest = new CachedRequest(this.api.features, 'features'); async setup() { diff --git a/src/stores/GlobalErrorStore.js b/src/stores/GlobalErrorStore.js index f4b9d7838..90bf751c3 100644 --- a/src/stores/GlobalErrorStore.js +++ b/src/stores/GlobalErrorStore.js @@ -4,6 +4,7 @@ import Request from './lib/Request'; export default class GlobalErrorStore extends Store { @observable error = null; + @observable response = {}; constructor(...args) { diff --git a/src/stores/NewsStore.js b/src/stores/NewsStore.js index e5091834f..6984425df 100644 --- a/src/stores/NewsStore.js +++ b/src/stores/NewsStore.js @@ -8,6 +8,7 @@ import { CHECK_INTERVAL } from '../config'; export default class NewsStore extends Store { @observable latestNewsRequest = new CachedRequest(this.api.news, 'latest'); + @observable hideNewsRequest = new Request(this.api.news, 'hide'); constructor(...args) { diff --git a/src/stores/PaymentStore.js b/src/stores/PaymentStore.js index 9e348d14e..4cabee194 100644 --- a/src/stores/PaymentStore.js +++ b/src/stores/PaymentStore.js @@ -7,8 +7,11 @@ import { gaEvent } from '../lib/analytics'; export default class PaymentStore extends Store { @observable plansRequest = new CachedRequest(this.api.payment, 'plans'); + @observable createHostedPageRequest = new Request(this.api.payment, 'getHostedPage'); + @observable createDashboardUrlRequest = new Request(this.api.payment, 'getDashboardUrl'); + @observable ordersDataRequest = new CachedRequest(this.api.payment, 'getOrders'); constructor(...args) { diff --git a/src/stores/RecipePreviewsStore.js b/src/stores/RecipePreviewsStore.js index e25936f15..10b2928e3 100644 --- a/src/stores/RecipePreviewsStore.js +++ b/src/stores/RecipePreviewsStore.js @@ -8,7 +8,9 @@ import { gaEvent } from '../lib/analytics'; export default class RecipePreviewsStore extends Store { @observable allRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'all'); + @observable featuredRecipePreviewsRequest = new CachedRequest(this.api.recipePreviews, 'featured'); + @observable searchRecipePreviewsRequest = new Request(this.api.recipePreviews, 'search'); constructor(...args) { diff --git a/src/stores/RecipesStore.js b/src/stores/RecipesStore.js index f2480bc8e..ab64bf79c 100644 --- a/src/stores/RecipesStore.js +++ b/src/stores/RecipesStore.js @@ -9,7 +9,9 @@ const debug = require('debug')('Franz:RecipeStore'); export default class RecipesStore extends Store { @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); + @observable installRecipeRequest = new Request(this.api.recipes, 'install'); + @observable getRecipeUpdatesRequest = new Request(this.api.recipes, 'update'); constructor(...args) { diff --git a/src/stores/RequestStore.js b/src/stores/RequestStore.js index bbfe6f6df..2629e0a38 100644 --- a/src/stores/RequestStore.js +++ b/src/stores/RequestStore.js @@ -6,10 +6,13 @@ const debug = require('debug')('Franz:RequestsStore'); export default class RequestStore extends Store { @observable userInfoRequest; + @observable servicesRequest; + @observable showRequiredRequestsError = false; retries = 0; + retryDelay = 2000; constructor(...args) { diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index ccb4eed04..5b70ca271 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -1,4 +1,6 @@ -import { action, reaction, computed, observable } from 'mobx'; +import { + action, reaction, computed, observable, +} from 'mobx'; import { debounce, remove } from 'lodash'; import Store from './lib/Store'; @@ -11,10 +13,15 @@ const debug = require('debug')('Franz:ServiceStore'); export default class ServicesStore extends Store { @observable allServicesRequest = new CachedRequest(this.api.services, 'all'); + @observable createServiceRequest = new Request(this.api.services, 'create'); + @observable updateServiceRequest = new Request(this.api.services, 'update'); + @observable reorderServicesRequest = new Request(this.api.services, 'reorder'); + @observable deleteServiceRequest = new Request(this.api.services, 'delete'); + @observable clearCacheRequest = new Request(this.api.services, 'clearCache'); @observable filterNeedle = null; diff --git a/src/stores/SettingsStore.js b/src/stores/SettingsStore.js index e2211aec6..ee391f5d3 100644 --- a/src/stores/SettingsStore.js +++ b/src/stores/SettingsStore.js @@ -14,11 +14,13 @@ const debug = require('debug')('Franz:SettingsStore'); export default class SettingsStore extends Store { @observable appSettingsRequest = new CachedRequest(this.api.local, 'getAppSettings'); + @observable updateAppSettingsRequest = new Request(this.api.local, 'updateAppSettings'); @observable fileSystemSettingsRequests = []; fileSystemSettingsTypes = FILE_SYSTEM_SETTINGS_TYPES; + @observable _fileSystemSettingsCache = { app: DEFAULT_APP_SETTINGS, proxy: {}, diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index 26ac2c60e..54bbbedae 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js @@ -14,29 +14,47 @@ const debug = require('debug')('Franz:UserStore'); // TODO: split stores into UserStore and AuthStore export default class UserStore extends Store { BASE_ROUTE = '/auth'; + WELCOME_ROUTE = `${this.BASE_ROUTE}/welcome`; + LOGIN_ROUTE = `${this.BASE_ROUTE}/login`; + LOGOUT_ROUTE = `${this.BASE_ROUTE}/logout`; + SIGNUP_ROUTE = `${this.BASE_ROUTE}/signup`; + PRICING_ROUTE = `${this.BASE_ROUTE}/signup/pricing`; + IMPORT_ROUTE = `${this.BASE_ROUTE}/signup/import`; + INVITE_ROUTE = `${this.BASE_ROUTE}/signup/invite`; + PASSWORD_ROUTE = `${this.BASE_ROUTE}/password`; @observable loginRequest = new Request(this.api.user, 'login'); + @observable signupRequest = new Request(this.api.user, 'signup'); + @observable passwordRequest = new Request(this.api.user, 'password'); + @observable inviteRequest = new Request(this.api.user, 'invite'); + @observable getUserInfoRequest = new CachedRequest(this.api.user, 'getInfo'); + @observable updateUserInfoRequest = new Request(this.api.user, 'updateInfo'); + @observable getLegacyServicesRequest = new CachedRequest(this.api.user, 'getLegacyServices'); + @observable deleteAccountRequest = new CachedRequest(this.api.user, 'delete'); @observable isImportLegacyServicesExecuting = false; + @observable isImportLegacyServicesCompleted = false; @observable id; + @observable authToken = localStorage.getItem('authToken') || null; + @observable accountType; @observable hasCompletedSignup = null; @@ -48,6 +66,7 @@ export default class UserStore extends Store { logoutReasonTypes = { SERVER: 'SERVER', }; + @observable logoutReason = null; constructor(...args) { @@ -141,7 +160,9 @@ export default class UserStore extends Store { gaEvent('User', 'login'); } - @action async _signup({ firstname, lastname, email, password, accountType, company }) { + @action async _signup({ + firstname, lastname, email, password, accountType, company, + }) { const authToken = await this.signupRequest.execute({ firstname, lastname, diff --git a/src/stores/lib/CachedRequest.js b/src/stores/lib/CachedRequest.js index c0c3d40a1..ac8b2bd81 100644 --- a/src/stores/lib/CachedRequest.js +++ b/src/stores/lib/CachedRequest.js @@ -5,6 +5,7 @@ import Request from './Request'; export default class CachedRequest extends Request { _apiCalls = []; + _isInvalidated = true; execute(...callArgs) { diff --git a/src/stores/lib/Reaction.js b/src/stores/lib/Reaction.js index e9bc26d81..46aa4dae6 100644 --- a/src/stores/lib/Reaction.js +++ b/src/stores/lib/Reaction.js @@ -3,7 +3,9 @@ import { autorun } from 'mobx'; export default class Reaction { reaction; + hasBeenStarted; + dispose; constructor(reaction) { diff --git a/src/stores/lib/Request.js b/src/stores/lib/Request.js index 4a6925cc5..04f528156 100644 --- a/src/stores/lib/Request.js +++ b/src/stores/lib/Request.js @@ -9,15 +9,23 @@ export default class Request { } @observable result = null; + @observable error = null; + @observable isExecuting = false; + @observable isError = false; + @observable wasExecuted = false; _promise = Promise; + _api = {}; + _method = ''; + _isWaitingForResponse = false; + _currentApiCall = null; constructor(api, method) { diff --git a/src/stores/lib/Store.js b/src/stores/lib/Store.js index 873da7b37..8d2fb4066 100644 --- a/src/stores/lib/Store.js +++ b/src/stores/lib/Store.js @@ -3,16 +3,20 @@ import Reaction from './Reaction'; export default class Store { stores = {}; + api = {}; + actions = {}; _reactions = []; // status implementation @observable _status = null; + @computed get actionStatus() { return this._status || []; } + set actionStatus(status) { this._status = status; } diff --git a/src/styles/searchInput.scss b/src/styles/searchInput.scss index 32b9da065..91453c600 100644 --- a/src/styles/searchInput.scss +++ b/src/styles/searchInput.scss @@ -22,6 +22,10 @@ padding: 5px 10px; width: 100%; + label { + width: 100%; + } + input { background: none; border: 0; diff --git a/src/theme/dark/index.js b/src/theme/dark/index.js index 5aa64a902..76fece134 100644 --- a/src/theme/dark/index.js +++ b/src/theme/dark/index.js @@ -5,4 +5,3 @@ export const colorBackgroundSubscriptionContainer = legacyStyles.themeBrandInfo; export const colorHeadline = legacyStyles.darkThemeTextColor; export const colorText = legacyStyles.darkThemeTextColor; - diff --git a/src/theme/default/index.js b/src/theme/default/index.js index e67f2ba58..cdd9aa5e6 100644 --- a/src/theme/default/index.js +++ b/src/theme/default/index.js @@ -20,4 +20,3 @@ export const colorSubscriptionContainerBorder = [1, 'solid', brandPrimary]; export const colorSubscriptionContainerTitle = brandPrimary; export const colorSubscriptionContainerActionButtonBackground = brandPrimary; export const colorSubscriptionContainerActionButtonColor = '#FFF'; - diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index 0349a5d6c..bd099987d 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -1,7 +1,9 @@ // This is heavily based on https://github.com/sindresorhus/electron-context-menu // ❤ @sindresorhus -import { clipboard, remote, ipcRenderer, shell } from 'electron'; +import { + clipboard, remote, ipcRenderer, shell, +} from 'electron'; import { isDevMode, isMac } from '../environment'; import { SPELLCHECKER_LOCALES } from '../i18n/languages'; diff --git a/src/webview/recipe.js b/src/webview/recipe.js index c9117ac72..944883899 100644 --- a/src/webview/recipe.js +++ b/src/webview/recipe.js @@ -56,7 +56,8 @@ class RecipeController { this.spellcheckingProvider, () => this.settings.app.enableSpellchecking, () => this.settings.app.spellcheckerLanguage, - () => this.spellcheckerLanguage); + () => this.spellcheckerLanguage, + ); autorun(() => this.update()); } -- cgit v1.2.3-54-g00ecf