diff options
-rw-r--r-- | src/@types/stores.types.ts | 2 | ||||
-rw-r--r-- | src/actions/lib/actions.ts | 6 | ||||
-rw-r--r-- | src/components/layout/Sidebar.tsx (renamed from src/components/layout/Sidebar.jsx) | 101 | ||||
-rw-r--r-- | src/features/todos/actions.ts | 17 | ||||
-rw-r--r-- | src/stores/ServicesStore.ts | 6 |
5 files changed, 74 insertions, 58 deletions
diff --git a/src/@types/stores.types.ts b/src/@types/stores.types.ts index 6730242c1..30898a8a7 100644 --- a/src/@types/stores.types.ts +++ b/src/@types/stores.types.ts | |||
@@ -343,7 +343,7 @@ export interface WorkspacesStore extends TypedStore { | |||
343 | create: ({ workspace }) => void; | 343 | create: ({ workspace }) => void; |
344 | edit: ({ workspace }) => void; | 344 | edit: ({ workspace }) => void; |
345 | saving: boolean; | 345 | saving: boolean; |
346 | filterServicesByActiveWorkspace: () => void; | 346 | filterServicesByActiveWorkspace: (services: Service[]) => Service[]; |
347 | isFeatureActive: () => void; | 347 | isFeatureActive: () => void; |
348 | isAnyWorkspaceActive: boolean; | 348 | isAnyWorkspaceActive: boolean; |
349 | isSettingsRouteActive: () => void; | 349 | isSettingsRouteActive: () => void; |
diff --git a/src/actions/lib/actions.ts b/src/actions/lib/actions.ts index ea9a8fe46..da27c2e2b 100644 --- a/src/actions/lib/actions.ts +++ b/src/actions/lib/actions.ts | |||
@@ -18,10 +18,10 @@ export interface Actions { | |||
18 | }; | 18 | }; |
19 | } | 19 | } |
20 | 20 | ||
21 | export const createActionsFromDefinitions = ( | 21 | export const createActionsFromDefinitions = <T extends {}>( |
22 | actionDefinitions: ActionDefinitions, | 22 | actionDefinitions: ActionDefinitions, |
23 | validate: any, | 23 | validate: any, |
24 | ) => { | 24 | ): T => { |
25 | const actions = {}; | 25 | const actions = {}; |
26 | // eslint-disable-next-line unicorn/no-array-for-each | 26 | // eslint-disable-next-line unicorn/no-array-for-each |
27 | Object.keys(actionDefinitions).forEach(actionName => { | 27 | Object.keys(actionDefinitions).forEach(actionName => { |
@@ -41,7 +41,7 @@ export const createActionsFromDefinitions = ( | |||
41 | // eslint-disable-next-line unicorn/no-array-for-each | 41 | // eslint-disable-next-line unicorn/no-array-for-each |
42 | action.listeners.forEach(listener => listener(params)); | 42 | action.listeners.forEach(listener => listener(params)); |
43 | }); | 43 | }); |
44 | return actions; | 44 | return actions as T; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | export default (definitions, validate) => { | 47 | export default (definitions, validate) => { |
diff --git a/src/components/layout/Sidebar.jsx b/src/components/layout/Sidebar.tsx index fef5baf64..a81229dca 100644 --- a/src/components/layout/Sidebar.jsx +++ b/src/components/layout/Sidebar.tsx | |||
@@ -1,7 +1,6 @@ | |||
1 | import { Component } from 'react'; | 1 | import { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | ||
3 | import ReactTooltip from 'react-tooltip'; | 2 | import ReactTooltip from 'react-tooltip'; |
4 | import { defineMessages, injectIntl } from 'react-intl'; | 3 | import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; |
5 | import { inject, observer } from 'mobx-react'; | 4 | import { inject, observer } from 'mobx-react'; |
6 | import { | 5 | import { |
7 | mdiCheckAll, | 6 | mdiCheckAll, |
@@ -29,10 +28,11 @@ import { | |||
29 | } from '../../environment'; | 28 | } from '../../environment'; |
30 | import { todosStore } from '../../features/todos'; | 29 | import { todosStore } from '../../features/todos'; |
31 | import { todoActions } from '../../features/todos/actions'; | 30 | import { todoActions } from '../../features/todos/actions'; |
32 | import AppStore from '../../stores/AppStore'; | ||
33 | import SettingsStore from '../../stores/SettingsStore'; | ||
34 | import globalMessages from '../../i18n/globalMessages'; | 31 | import globalMessages from '../../i18n/globalMessages'; |
35 | import Icon from '../ui/icon'; | 32 | import Icon from '../ui/icon'; |
33 | import { Actions } from '../../actions/lib/actions'; | ||
34 | import { RealStores } from '../../stores'; | ||
35 | import Service from '../../models/Service'; | ||
36 | 36 | ||
37 | const messages = defineMessages({ | 37 | const messages = defineMessages({ |
38 | addNewService: { | 38 | addNewService: { |
@@ -73,40 +73,43 @@ const messages = defineMessages({ | |||
73 | }, | 73 | }, |
74 | }); | 74 | }); |
75 | 75 | ||
76 | class Sidebar extends Component { | 76 | interface IProps extends WrappedComponentProps { |
77 | static propTypes = { | 77 | services: Service[]; |
78 | openSettings: PropTypes.func.isRequired, | 78 | showServicesUpdatedInfoBar: boolean; |
79 | closeSettings: PropTypes.func.isRequired, | 79 | showMessageBadgeWhenMutedSetting: boolean; |
80 | setActive: PropTypes.func.isRequired, | 80 | showServiceNameSetting: boolean; |
81 | reorder: PropTypes.func.isRequired, | 81 | showMessageBadgesEvenWhenMuted: boolean; |
82 | reload: PropTypes.func.isRequired, | 82 | isAppMuted: boolean; |
83 | toggleNotifications: PropTypes.func.isRequired, | 83 | isMenuCollapsed: boolean; |
84 | toggleAudio: PropTypes.func.isRequired, | 84 | isWorkspaceDrawerOpen: boolean; |
85 | toggleDarkMode: PropTypes.func.isRequired, | 85 | isTodosServiceActive: boolean; |
86 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, | 86 | actions?: Actions; |
87 | showMessageBadgeWhenMutedSetting: PropTypes.bool.isRequired, | 87 | stores?: RealStores; |
88 | showServiceNameSetting: PropTypes.bool.isRequired, | ||
89 | showMessageBadgesEvenWhenMuted: PropTypes.bool.isRequired, | ||
90 | deleteService: PropTypes.func.isRequired, | ||
91 | updateService: PropTypes.func.isRequired, | ||
92 | hibernateService: PropTypes.func.isRequired, | ||
93 | wakeUpService: PropTypes.func.isRequired, | ||
94 | toggleMuteApp: PropTypes.func.isRequired, | ||
95 | isAppMuted: PropTypes.bool.isRequired, | ||
96 | toggleCollapseMenu: PropTypes.func.isRequired, | ||
97 | isMenuCollapsed: PropTypes.bool.isRequired, | ||
98 | isWorkspaceDrawerOpen: PropTypes.bool.isRequired, | ||
99 | toggleWorkspaceDrawer: PropTypes.func.isRequired, | ||
100 | isTodosServiceActive: PropTypes.bool.isRequired, | ||
101 | stores: PropTypes.shape({ | ||
102 | app: PropTypes.instanceOf(AppStore).isRequired, | ||
103 | settings: PropTypes.instanceOf(SettingsStore).isRequired, | ||
104 | }).isRequired, | ||
105 | actions: PropTypes.shape({ | ||
106 | settings: PropTypes.instanceOf(SettingsStore).isRequired, | ||
107 | }).isRequired, | ||
108 | }; | ||
109 | 88 | ||
89 | deleteService: () => void; | ||
90 | updateService: () => void; | ||
91 | hibernateService: () => void; | ||
92 | wakeUpService: () => void; | ||
93 | toggleMuteApp: () => void; | ||
94 | toggleCollapseMenu: () => void; | ||
95 | toggleWorkspaceDrawer: () => void; | ||
96 | openSettings: (arg: { path: string }) => void; | ||
97 | closeSettings: () => void; | ||
98 | setActive: () => void; | ||
99 | reorder: () => void; | ||
100 | reload: () => void; | ||
101 | toggleNotifications: () => void; | ||
102 | toggleAudio: () => void; | ||
103 | toggleDarkMode: () => void; | ||
104 | } | ||
105 | |||
106 | interface IState { | ||
107 | tooltipEnabled: boolean; | ||
108 | } | ||
109 | |||
110 | @observer | ||
111 | @inject('stores', 'actions') | ||
112 | class Sidebar extends Component<IProps, IState> { | ||
110 | constructor(props) { | 113 | constructor(props) { |
111 | super(props); | 114 | super(props); |
112 | 115 | ||
@@ -153,7 +156,7 @@ class Sidebar extends Component { | |||
153 | hideSplitModeButton, | 156 | hideSplitModeButton, |
154 | useHorizontalStyle, | 157 | useHorizontalStyle, |
155 | splitMode, | 158 | splitMode, |
156 | } = stores.settings.app; | 159 | } = stores!.settings.app; |
157 | const { intl } = this.props; | 160 | const { intl } = this.props; |
158 | const todosToggleMessage = todosStore.isTodosPanelVisible | 161 | const todosToggleMessage = todosStore.isTodosPanelVisible |
159 | ? messages.closeTodosDrawer | 162 | ? messages.closeTodosDrawer |
@@ -172,7 +175,7 @@ class Sidebar extends Component { | |||
172 | todosStore.isFeatureEnabledByUser, | 175 | todosStore.isFeatureEnabledByUser, |
173 | ].filter(Boolean).length; | 176 | ].filter(Boolean).length; |
174 | 177 | ||
175 | const { isMenuCollapsed } = stores.settings.all.app; | 178 | const { isMenuCollapsed } = stores!.settings.all.app; |
176 | 179 | ||
177 | return ( | 180 | return ( |
178 | <div className="sidebar"> | 181 | <div className="sidebar"> |
@@ -180,7 +183,7 @@ class Sidebar extends Component { | |||
180 | {...this.props} | 183 | {...this.props} |
181 | enableToolTip={() => this.enableToolTip()} | 184 | enableToolTip={() => this.enableToolTip()} |
182 | disableToolTip={() => this.disableToolTip()} | 185 | disableToolTip={() => this.disableToolTip()} |
183 | useHorizontalStyle={stores.settings.all.app.useHorizontalStyle} | 186 | useHorizontalStyle={stores!.settings.all.app.useHorizontalStyle} |
184 | /> | 187 | /> |
185 | <> | 188 | <> |
186 | {numberActiveButtons <= 1 || hideCollapseButton ? null : ( | 189 | {numberActiveButtons <= 1 || hideCollapseButton ? null : ( |
@@ -216,7 +219,7 @@ class Sidebar extends Component { | |||
216 | <button | 219 | <button |
217 | type="button" | 220 | type="button" |
218 | onClick={() => { | 221 | onClick={() => { |
219 | actions.settings.update({ | 222 | actions!.settings.update({ |
220 | type: 'app', | 223 | type: 'app', |
221 | data: { | 224 | data: { |
222 | splitMode: !splitMode, | 225 | splitMode: !splitMode, |
@@ -283,12 +286,12 @@ class Sidebar extends Component { | |||
283 | <Icon icon={mdiCheckAll} size={1.5} /> | 286 | <Icon icon={mdiCheckAll} size={1.5} /> |
284 | </button> | 287 | </button> |
285 | ) : null} | 288 | ) : null} |
286 | {stores.settings.all.app.lockingFeatureEnabled ? ( | 289 | {stores!.settings.all.app.lockingFeatureEnabled ? ( |
287 | <button | 290 | <button |
288 | type="button" | 291 | type="button" |
289 | className="sidebar__button" | 292 | className="sidebar__button" |
290 | onClick={() => { | 293 | onClick={() => { |
291 | actions.settings.update({ | 294 | actions!.settings.update({ |
292 | type: 'app', | 295 | type: 'app', |
293 | data: { | 296 | data: { |
294 | locked: true, | 297 | locked: true, |
@@ -316,11 +319,11 @@ class Sidebar extends Component { | |||
316 | )} (${settingsShortcutKey(false)})`} | 319 | )} (${settingsShortcutKey(false)})`} |
317 | > | 320 | > |
318 | <Icon icon={mdiCog} size={1.5} /> | 321 | <Icon icon={mdiCog} size={1.5} /> |
319 | {this.props.stores.settings.app.automaticUpdates && | 322 | {stores!.settings.app.automaticUpdates && |
320 | (this.props.stores.app.updateStatus === | 323 | (stores!.app.updateStatus === |
321 | this.props.stores.app.updateStatusTypes.AVAILABLE || | 324 | stores!.app.updateStatusTypes.AVAILABLE || |
322 | this.props.stores.app.updateStatus === | 325 | stores!.app.updateStatus === |
323 | this.props.stores.app.updateStatusTypes.DOWNLOADED || | 326 | stores!.app.updateStatusTypes.DOWNLOADED || |
324 | this.props.showServicesUpdatedInfoBar) && ( | 327 | this.props.showServicesUpdatedInfoBar) && ( |
325 | <span className="update-available">•</span> | 328 | <span className="update-available">•</span> |
326 | )} | 329 | )} |
@@ -331,4 +334,4 @@ class Sidebar extends Component { | |||
331 | } | 334 | } |
332 | } | 335 | } |
333 | 336 | ||
334 | export default injectIntl(inject('stores', 'actions')(observer(Sidebar))); | 337 | export default injectIntl(Sidebar); |
diff --git a/src/features/todos/actions.ts b/src/features/todos/actions.ts index 04e299e71..b47a076b9 100644 --- a/src/features/todos/actions.ts +++ b/src/features/todos/actions.ts | |||
@@ -1,7 +1,22 @@ | |||
1 | import PropTypes from 'prop-types'; | 1 | import PropTypes from 'prop-types'; |
2 | import { ReactElement } from 'react'; | ||
2 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | 3 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; |
3 | 4 | ||
4 | export const todoActions = createActionsFromDefinitions( | 5 | interface TodoActionsType { |
6 | resize: (width: number) => void; | ||
7 | toggleTodosPanel: () => void; | ||
8 | toggleTodosFeatureVisibility: () => void; | ||
9 | setTodosWebview: (webview: ReactElement) => void; | ||
10 | handleHostMessage: (action: string, data: object) => void; | ||
11 | handleClientMessage: ( | ||
12 | channel: string, | ||
13 | message: { action: string; data: object }, | ||
14 | ) => void; | ||
15 | openDevTools: () => void; | ||
16 | reload: () => void; | ||
17 | } | ||
18 | |||
19 | export const todoActions = createActionsFromDefinitions<TodoActionsType>( | ||
5 | { | 20 | { |
6 | resize: { | 21 | resize: { |
7 | width: PropTypes.number.isRequired, | 22 | width: PropTypes.number.isRequired, |
diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index c8faf2e5c..74810b81f 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts | |||
@@ -337,7 +337,7 @@ export default class ServicesStore extends TypedStore { | |||
337 | return this.all.filter(service => service.isEnabled); | 337 | return this.all.filter(service => service.isEnabled); |
338 | } | 338 | } |
339 | 339 | ||
340 | @computed get allDisplayed() { | 340 | @computed get allDisplayed(): Service[] { |
341 | const services = this.stores.settings.all.app.showDisabledServices | 341 | const services = this.stores.settings.all.app.showDisabledServices |
342 | ? this.all | 342 | ? this.all |
343 | : this.enabled; | 343 | : this.enabled; |
@@ -1031,9 +1031,7 @@ export default class ServicesStore extends TypedStore { | |||
1031 | this.reorderServicesRequest.execute(services); | 1031 | this.reorderServicesRequest.execute(services); |
1032 | this.allServicesRequest.patch(data => { | 1032 | this.allServicesRequest.patch(data => { |
1033 | for (const s of data) { | 1033 | for (const s of data) { |
1034 | const service = s; | 1034 | s.order = services[s.id]; |
1035 | |||
1036 | service.order = services[s.id]; | ||
1037 | } | 1035 | } |
1038 | }); | 1036 | }); |
1039 | } | 1037 | } |