diff options
Diffstat (limited to 'src/features')
-rw-r--r-- | src/features/appearance/index.js | 11 | ||||
-rw-r--r-- | src/features/todos/components/TodosWebview.js | 96 | ||||
-rw-r--r-- | src/features/todos/containers/TodosScreen.js | 3 | ||||
-rw-r--r-- | src/features/todos/index.js | 1 | ||||
-rw-r--r-- | src/features/todos/store.js | 29 |
5 files changed, 57 insertions, 83 deletions
diff --git a/src/features/appearance/index.js b/src/features/appearance/index.js index 82a0971eb..b5648250e 100644 --- a/src/features/appearance/index.js +++ b/src/features/appearance/index.js | |||
@@ -93,10 +93,10 @@ function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { | |||
93 | } | 93 | } |
94 | ` : ` | 94 | ` : ` |
95 | .sidebar { | 95 | .sidebar { |
96 | width: ${width - 2}px !important; | 96 | width: ${width}px !important; |
97 | } | 97 | } |
98 | .tab-item { | 98 | .tab-item { |
99 | width: ${width - 2}px !important; | 99 | width: ${width}px !important; |
100 | height: ${width - 5 + iconSize}px !important; | 100 | height: ${width - 5 + iconSize}px !important; |
101 | } | 101 | } |
102 | .tab-item .tab-item__icon { | 102 | .tab-item .tab-item__icon { |
@@ -105,6 +105,9 @@ function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { | |||
105 | .sidebar__button { | 105 | .sidebar__button { |
106 | font-size: ${width / 3}px !important; | 106 | font-size: ${width / 3}px !important; |
107 | } | 107 | } |
108 | .todos__todos-panel--expanded { | ||
109 | width: calc(100% - ${300 + width}px) !important; | ||
110 | } | ||
108 | `; | 111 | `; |
109 | } | 112 | } |
110 | 113 | ||
@@ -156,6 +159,10 @@ function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { | |||
156 | .workspaces-drawer { | 159 | .workspaces-drawer { |
157 | maring-top: -${sidebarWidthStr} !important; | 160 | maring-top: -${sidebarWidthStr} !important; |
158 | } | 161 | } |
162 | |||
163 | .todos__todos-panel--expanded { | ||
164 | width: calc(100% - 300px) !important; | ||
165 | } | ||
159 | `; | 166 | `; |
160 | } | 167 | } |
161 | 168 | ||
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 @@ | |||
1 | import React, { Component } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, inject } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import injectSheet from 'react-jss'; | 4 | import injectSheet from 'react-jss'; |
5 | import Webview from 'react-electron-web-view'; | 5 | import Webview from 'react-electron-web-view'; |
6 | import { Icon } from '@meetfranz/ui'; | ||
7 | import { defineMessages, intlShape } from 'react-intl'; | ||
8 | import classnames from 'classnames'; | 6 | import classnames from 'classnames'; |
9 | 7 | ||
10 | import { mdiCheckAll } from '@mdi/js'; | ||
11 | import SettingsStore from '../../../stores/SettingsStore'; | ||
12 | |||
13 | import Appear from '../../../components/ui/effects/Appear'; | ||
14 | import UpgradeButton from '../../../components/ui/UpgradeButton'; | ||
15 | import { TODOS_PARTITION_ID } from '..'; | 8 | import { TODOS_PARTITION_ID } from '..'; |
16 | 9 | ||
17 | // NOTE: https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url | ||
18 | function validURL(str) { | ||
19 | let url; | ||
20 | |||
21 | try { | ||
22 | url = new URL(str); | ||
23 | } catch (_) { | ||
24 | return false; | ||
25 | } | ||
26 | |||
27 | return url.protocol === 'http:' || url.protocol === 'https:'; | ||
28 | } | ||
29 | |||
30 | const messages = defineMessages({ | ||
31 | premiumInfo: { | ||
32 | id: 'feature.todos.premium.info', | ||
33 | defaultMessage: '!!!Franz Todos are available to premium users now!', | ||
34 | }, | ||
35 | upgradeCTA: { | ||
36 | id: 'feature.todos.premium.upgrade', | ||
37 | defaultMessage: '!!!Upgrade Account', | ||
38 | }, | ||
39 | rolloutInfo: { | ||
40 | id: 'feature.todos.premium.rollout', | ||
41 | defaultMessage: '!!!Everyone else will have to wait a little longer.', | ||
42 | }, | ||
43 | }); | ||
44 | |||
45 | const styles = theme => ({ | 10 | const styles = theme => ({ |
46 | root: { | 11 | root: { |
47 | background: theme.colorBackground, | 12 | background: theme.colorBackground, |
@@ -96,10 +61,14 @@ const styles = theme => ({ | |||
96 | position: 'absolute', | 61 | position: 'absolute', |
97 | right: 0, | 62 | right: 0, |
98 | zIndex: 0, | 63 | zIndex: 0, |
64 | borderLeftWidth: 0, | ||
65 | }, | ||
66 | hidden: { | ||
67 | borderLeftWidth: 0, | ||
99 | }, | 68 | }, |
100 | }); | 69 | }); |
101 | 70 | ||
102 | @injectSheet(styles) @inject('stores') @observer | 71 | @injectSheet(styles) @observer |
103 | class TodosWebview extends Component { | 72 | class TodosWebview extends Component { |
104 | static propTypes = { | 73 | static propTypes = { |
105 | classes: PropTypes.object.isRequired, | 74 | classes: PropTypes.object.isRequired, |
@@ -111,10 +80,8 @@ class TodosWebview extends Component { | |||
111 | width: PropTypes.number.isRequired, | 80 | width: PropTypes.number.isRequired, |
112 | minWidth: PropTypes.number.isRequired, | 81 | minWidth: PropTypes.number.isRequired, |
113 | userAgent: PropTypes.string.isRequired, | 82 | userAgent: PropTypes.string.isRequired, |
114 | isTodosIncludedInCurrentPlan: PropTypes.bool.isRequired, | 83 | todoUrl: PropTypes.string.isRequired, |
115 | stores: PropTypes.shape({ | 84 | isTodoUrlValid: PropTypes.bool.isRequired, |
116 | settings: PropTypes.instanceOf(SettingsStore).isRequired, | ||
117 | }).isRequired, | ||
118 | }; | 85 | }; |
119 | 86 | ||
120 | state = { | 87 | state = { |
@@ -122,10 +89,6 @@ class TodosWebview extends Component { | |||
122 | width: 300, | 89 | width: 300, |
123 | }; | 90 | }; |
124 | 91 | ||
125 | static contextTypes = { | ||
126 | intl: intlShape, | ||
127 | }; | ||
128 | |||
129 | componentWillMount() { | 92 | componentWillMount() { |
130 | const { width } = this.props; | 93 | const { width } = this.props; |
131 | 94 | ||
@@ -209,8 +172,8 @@ class TodosWebview extends Component { | |||
209 | isTodosServiceActive, | 172 | isTodosServiceActive, |
210 | isVisible, | 173 | isVisible, |
211 | userAgent, | 174 | userAgent, |
212 | isTodosIncludedInCurrentPlan, | 175 | todoUrl, |
213 | stores, | 176 | isTodoUrlValid, |
214 | } = this.props; | 177 | } = this.props; |
215 | 178 | ||
216 | const { | 179 | const { |
@@ -219,29 +182,20 @@ class TodosWebview extends Component { | |||
219 | isDragging, | 182 | isDragging, |
220 | } = this.state; | 183 | } = this.state; |
221 | 184 | ||
222 | const { intl } = this.context; | 185 | let displayedWidth = isVisible ? width : 0; |
223 | 186 | if (isTodosServiceActive) { | |
224 | const isUsingPredefinedTodoServer = stores.settings.all.app.predefinedTodoServer !== 'isUsingCustomTodoService'; | 187 | displayedWidth = null; |
225 | const todoUrl = isUsingPredefinedTodoServer | ||
226 | ? stores.settings.all.app.predefinedTodoServer | ||
227 | : stores.settings.all.app.customTodoServer; | ||
228 | let isTodoUrlValid = true; | ||
229 | if (isUsingPredefinedTodoServer === false) { | ||
230 | isTodoUrlValid = validURL(todoUrl); | ||
231 | } | 188 | } |
232 | 189 | ||
233 | const todosPanelStyle = { | ||
234 | width: isVisible ? width : 0, | ||
235 | borderLeftWidth: isVisible ? '1px' : 0, | ||
236 | }; | ||
237 | |||
238 | return ( | 190 | return ( |
239 | <div | 191 | <div |
240 | className={classnames({ | 192 | className={classnames({ |
241 | [classes.root]: true, | 193 | [classes.root]: true, |
242 | [classes.isTodosServiceActive]: isTodosServiceActive, | 194 | [classes.isTodosServiceActive]: isTodosServiceActive, |
195 | 'todos__todos-panel--expanded': isTodosServiceActive, | ||
196 | [classes.hidden]: !isVisible, | ||
243 | })} | 197 | })} |
244 | style={todosPanelStyle} | 198 | style={{ width: displayedWidth }} |
245 | onMouseUp={() => this.stopResize()} | 199 | onMouseUp={() => this.stopResize()} |
246 | ref={(node) => { this.node = node; }} | 200 | ref={(node) => { this.node = node; }} |
247 | id="todos-panel" | 201 | id="todos-panel" |
@@ -257,9 +211,7 @@ class TodosWebview extends Component { | |||
257 | style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad | 211 | style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad |
258 | /> | 212 | /> |
259 | )} | 213 | )} |
260 | {isTodosIncludedInCurrentPlan ? ( | 214 | {isTodoUrlValid && ( |
261 | isTodoUrlValid | ||
262 | && ( | ||
263 | <Webview | 215 | <Webview |
264 | className={classes.webview} | 216 | className={classes.webview} |
265 | onDidAttach={() => { | 217 | onDidAttach={() => { |
@@ -273,20 +225,6 @@ class TodosWebview extends Component { | |||
273 | useragent={userAgent} | 225 | useragent={userAgent} |
274 | src={todoUrl} | 226 | src={todoUrl} |
275 | /> | 227 | /> |
276 | ) | ||
277 | ) : ( | ||
278 | <Appear> | ||
279 | <div className={classes.premiumContainer}> | ||
280 | <Icon icon={mdiCheckAll} className={classes.premiumIcon} size={4} /> | ||
281 | <p>{intl.formatMessage(messages.premiumInfo)}</p> | ||
282 | <p>{intl.formatMessage(messages.rolloutInfo)}</p> | ||
283 | <UpgradeButton | ||
284 | className={classes.premiumCTA} | ||
285 | gaEventInfo={{ category: 'Todos', event: 'upgrade' }} | ||
286 | short | ||
287 | /> | ||
288 | </div> | ||
289 | </Appear> | ||
290 | )} | 228 | )} |
291 | </div> | 229 | </div> |
292 | ); | 230 | ); |
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 { | |||
28 | minWidth={TODOS_MIN_WIDTH} | 28 | minWidth={TODOS_MIN_WIDTH} |
29 | resize={width => todoActions.resize({ width })} | 29 | resize={width => todoActions.resize({ width })} |
30 | userAgent={todosStore.userAgent} | 30 | userAgent={todosStore.userAgent} |
31 | isTodosIncludedInCurrentPlan | 31 | todoUrl={todosStore.todoUrl} |
32 | isTodoUrlValid={todosStore.isTodoUrlValid} | ||
32 | /> | 33 | /> |
33 | </ErrorBoundary> | 34 | </ErrorBoundary> |
34 | ); | 35 | ); |
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; | |||
9 | export const TODOS_MIN_WIDTH = 200; | 9 | export const TODOS_MIN_WIDTH = 200; |
10 | export const DEFAULT_TODOS_VISIBLE = true; | 10 | export const DEFAULT_TODOS_VISIBLE = true; |
11 | export const DEFAULT_IS_FEATURE_ENABLED_BY_USER = true; | 11 | export const DEFAULT_IS_FEATURE_ENABLED_BY_USER = true; |
12 | export const TODOS_RECIPE_ID = 'franz-todos'; | ||
13 | export const TODOS_PARTITION_ID = 'persist:todos'; | 12 | export const TODOS_PARTITION_ID = 'persist:todos'; |
14 | 13 | ||
15 | export const TODOS_ROUTES = { | 14 | 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 { | |||
7 | import localStorage from 'mobx-localstorage'; | 7 | import localStorage from 'mobx-localstorage'; |
8 | 8 | ||
9 | import { todoActions } from './actions'; | 9 | import { todoActions } from './actions'; |
10 | import { CUSTOM_TODO_SERVICE, TODO_SERVICE_RECIPE_IDS } from '../../config'; | ||
11 | import { isValidExternalURL } from '../../helpers/url-helpers'; | ||
10 | import { FeatureStore } from '../utils/FeatureStore'; | 12 | import { FeatureStore } from '../utils/FeatureStore'; |
11 | import { createReactions } from '../../stores/lib/Reaction'; | 13 | import { createReactions } from '../../stores/lib/Reaction'; |
12 | import { createActionBindings } from '../utils/ActionBinding'; | 14 | import { createActionBindings } from '../utils/ActionBinding'; |
@@ -21,6 +23,8 @@ import UserAgent from '../../models/UserAgent'; | |||
21 | const debug = require('debug')('Ferdi:feature:todos:store'); | 23 | const debug = require('debug')('Ferdi:feature:todos:store'); |
22 | 24 | ||
23 | export default class TodoStore extends FeatureStore { | 25 | export default class TodoStore extends FeatureStore { |
26 | @observable stores = null; | ||
27 | |||
24 | @observable isFeatureEnabled = false; | 28 | @observable isFeatureEnabled = false; |
25 | 29 | ||
26 | @observable isFeatureActive = false; | 30 | @observable isFeatureActive = false; |
@@ -59,6 +63,31 @@ export default class TodoStore extends FeatureStore { | |||
59 | return this.userAgentModel.userAgent; | 63 | return this.userAgentModel.userAgent; |
60 | } | 64 | } |
61 | 65 | ||
66 | @computed get isUsingPredefinedTodoServer() { | ||
67 | return this.stores && this.stores.settings.app.predefinedTodoServer !== CUSTOM_TODO_SERVICE; | ||
68 | } | ||
69 | |||
70 | @computed get todoUrl() { | ||
71 | if (!this.stores) { | ||
72 | return null; | ||
73 | } | ||
74 | return this.isUsingPredefinedTodoServer | ||
75 | ? this.stores.settings.app.predefinedTodoServer | ||
76 | : this.stores.settings.app.customTodoServer; | ||
77 | } | ||
78 | |||
79 | @computed get isTodoUrlValid() { | ||
80 | return !this.isUsingPredefinedTodoServer || isValidExternalURL(this.todoUrl); | ||
81 | } | ||
82 | |||
83 | @computed get todoRecipeId() { | ||
84 | if (this.isFeatureEnabledByUser && this.isUsingPredefinedTodoServer | ||
85 | && this.todoUrl in TODO_SERVICE_RECIPE_IDS) { | ||
86 | return TODO_SERVICE_RECIPE_IDS[this.todoUrl]; | ||
87 | } | ||
88 | return null; | ||
89 | } | ||
90 | |||
62 | // ========== PUBLIC API ========= // | 91 | // ========== PUBLIC API ========= // |
63 | 92 | ||
64 | @action start(stores, actions) { | 93 | @action start(stores, actions) { |