From b0ecce5eab2a6d0eed3ade7c43e252ca9bac7edb Mon Sep 17 00:00:00 2001 From: kytwb <412895+kytwb@users.noreply.github.com> Date: Sat, 12 Jun 2021 19:51:28 +0200 Subject: Fix active Todos service behaviour (#1481) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Return false instead of null in isTodosServiceAdded * Resolve from TODOS_RECIPES_ID instead of hardcoded TODOS_RECIPE_ID * Fix TodosWebview width toggling when isTodosServiceActive * Add more todo service recipe IDs * Refactor todos state management * Moved todos service URL and recipe ID computation logic to todos/store * Simplified TodosWebview by delegating to the store for the URL and removing the (unused) payment logic * Made the todos service computation logic in the Service model depend on the logic in todos/store * Made ServicesStore depend on the todos service logic from the Service model * Todos appearance fixes * Hide double horizontal rules if todo settings are hidden due to an added todo service * Hide todos panel border when the panel is hidden or expanded * Make expanded todos panel obey sidebar width and vertical style settings * Make todos/store use isValidExternalURL * Harden isValidExternalURL against malformed URLs * Reduce todo URL string duplication in config.js Co-authored-by: Kristóf Marussy --- src/features/todos/components/TodosWebview.js | 96 +++++---------------------- src/features/todos/containers/TodosScreen.js | 3 +- src/features/todos/index.js | 1 - src/features/todos/store.js | 29 ++++++++ 4 files changed, 48 insertions(+), 81 deletions(-) (limited to 'src/features/todos') diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 634ec4caa..03bb5efe8 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -1,47 +1,12 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { observer, inject } from 'mobx-react'; +import { observer } from 'mobx-react'; import injectSheet from 'react-jss'; import Webview from 'react-electron-web-view'; -import { Icon } from '@meetfranz/ui'; -import { defineMessages, intlShape } from 'react-intl'; import classnames from 'classnames'; -import { mdiCheckAll } from '@mdi/js'; -import SettingsStore from '../../../stores/SettingsStore'; - -import Appear from '../../../components/ui/effects/Appear'; -import UpgradeButton from '../../../components/ui/UpgradeButton'; import { TODOS_PARTITION_ID } from '..'; -// NOTE: https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url -function validURL(str) { - let url; - - try { - url = new URL(str); - } catch (_) { - return false; - } - - return url.protocol === 'http:' || url.protocol === 'https:'; -} - -const messages = defineMessages({ - premiumInfo: { - id: 'feature.todos.premium.info', - defaultMessage: '!!!Franz Todos are available to premium users now!', - }, - upgradeCTA: { - id: 'feature.todos.premium.upgrade', - defaultMessage: '!!!Upgrade Account', - }, - rolloutInfo: { - id: 'feature.todos.premium.rollout', - defaultMessage: '!!!Everyone else will have to wait a little longer.', - }, -}); - const styles = theme => ({ root: { background: theme.colorBackground, @@ -96,10 +61,14 @@ const styles = theme => ({ position: 'absolute', right: 0, zIndex: 0, + borderLeftWidth: 0, + }, + hidden: { + borderLeftWidth: 0, }, }); -@injectSheet(styles) @inject('stores') @observer +@injectSheet(styles) @observer class TodosWebview extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -111,10 +80,8 @@ class TodosWebview extends Component { width: PropTypes.number.isRequired, minWidth: PropTypes.number.isRequired, userAgent: PropTypes.string.isRequired, - isTodosIncludedInCurrentPlan: PropTypes.bool.isRequired, - stores: PropTypes.shape({ - settings: PropTypes.instanceOf(SettingsStore).isRequired, - }).isRequired, + todoUrl: PropTypes.string.isRequired, + isTodoUrlValid: PropTypes.bool.isRequired, }; state = { @@ -122,10 +89,6 @@ class TodosWebview extends Component { width: 300, }; - static contextTypes = { - intl: intlShape, - }; - componentWillMount() { const { width } = this.props; @@ -209,8 +172,8 @@ class TodosWebview extends Component { isTodosServiceActive, isVisible, userAgent, - isTodosIncludedInCurrentPlan, - stores, + todoUrl, + isTodoUrlValid, } = this.props; const { @@ -219,29 +182,20 @@ class TodosWebview extends Component { isDragging, } = this.state; - const { intl } = this.context; - - const isUsingPredefinedTodoServer = stores.settings.all.app.predefinedTodoServer !== 'isUsingCustomTodoService'; - const todoUrl = isUsingPredefinedTodoServer - ? stores.settings.all.app.predefinedTodoServer - : stores.settings.all.app.customTodoServer; - let isTodoUrlValid = true; - if (isUsingPredefinedTodoServer === false) { - isTodoUrlValid = validURL(todoUrl); + let displayedWidth = isVisible ? width : 0; + if (isTodosServiceActive) { + displayedWidth = null; } - const todosPanelStyle = { - width: isVisible ? width : 0, - borderLeftWidth: isVisible ? '1px' : 0, - }; - return (
this.stopResize()} ref={(node) => { this.node = node; }} id="todos-panel" @@ -257,9 +211,7 @@ class TodosWebview extends Component { style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad /> )} - {isTodosIncludedInCurrentPlan ? ( - isTodoUrlValid - && ( + {isTodoUrlValid && ( { @@ -273,20 +225,6 @@ class TodosWebview extends Component { useragent={userAgent} src={todoUrl} /> - ) - ) : ( - -
- -

{intl.formatMessage(messages.premiumInfo)}

-

{intl.formatMessage(messages.rolloutInfo)}

- -
-
)}
); diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 631893f93..96147d5ab 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -28,7 +28,8 @@ class TodosScreen extends Component { minWidth={TODOS_MIN_WIDTH} resize={width => todoActions.resize({ width })} userAgent={todosStore.userAgent} - isTodosIncludedInCurrentPlan + todoUrl={todosStore.todoUrl} + isTodoUrlValid={todosStore.isTodoUrlValid} /> ); diff --git a/src/features/todos/index.js b/src/features/todos/index.js index ebd2c60ef..b6d13e5e1 100644 --- a/src/features/todos/index.js +++ b/src/features/todos/index.js @@ -9,7 +9,6 @@ export const DEFAULT_TODOS_WIDTH = 300; export const TODOS_MIN_WIDTH = 200; export const DEFAULT_TODOS_VISIBLE = true; export const DEFAULT_IS_FEATURE_ENABLED_BY_USER = true; -export const TODOS_RECIPE_ID = 'franz-todos'; export const TODOS_PARTITION_ID = 'persist:todos'; export const TODOS_ROUTES = { diff --git a/src/features/todos/store.js b/src/features/todos/store.js index af8519d9c..4febd7bb1 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -7,6 +7,8 @@ import { import localStorage from 'mobx-localstorage'; import { todoActions } from './actions'; +import { CUSTOM_TODO_SERVICE, TODO_SERVICE_RECIPE_IDS } from '../../config'; +import { isValidExternalURL } from '../../helpers/url-helpers'; import { FeatureStore } from '../utils/FeatureStore'; import { createReactions } from '../../stores/lib/Reaction'; import { createActionBindings } from '../utils/ActionBinding'; @@ -21,6 +23,8 @@ import UserAgent from '../../models/UserAgent'; const debug = require('debug')('Ferdi:feature:todos:store'); export default class TodoStore extends FeatureStore { + @observable stores = null; + @observable isFeatureEnabled = false; @observable isFeatureActive = false; @@ -59,6 +63,31 @@ export default class TodoStore extends FeatureStore { return this.userAgentModel.userAgent; } + @computed get isUsingPredefinedTodoServer() { + return this.stores && this.stores.settings.app.predefinedTodoServer !== CUSTOM_TODO_SERVICE; + } + + @computed get todoUrl() { + if (!this.stores) { + return null; + } + return this.isUsingPredefinedTodoServer + ? this.stores.settings.app.predefinedTodoServer + : this.stores.settings.app.customTodoServer; + } + + @computed get isTodoUrlValid() { + return !this.isUsingPredefinedTodoServer || isValidExternalURL(this.todoUrl); + } + + @computed get todoRecipeId() { + if (this.isFeatureEnabledByUser && this.isUsingPredefinedTodoServer + && this.todoUrl in TODO_SERVICE_RECIPE_IDS) { + return TODO_SERVICE_RECIPE_IDS[this.todoUrl]; + } + return null; + } + // ========== PUBLIC API ========= // @action start(stores, actions) { -- cgit v1.2.3-54-g00ecf