aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/layout/Sidebar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/layout/Sidebar.tsx')
-rw-r--r--src/components/layout/Sidebar.tsx337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx
new file mode 100644
index 000000000..a81229dca
--- /dev/null
+++ b/src/components/layout/Sidebar.tsx
@@ -0,0 +1,337 @@
1import { Component } from 'react';
2import ReactTooltip from 'react-tooltip';
3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { inject, observer } from 'mobx-react';
5import {
6 mdiCheckAll,
7 mdiViewGrid,
8 mdiPlusBox,
9 mdiCog,
10 mdiBellOff,
11 mdiBell,
12 mdiLock,
13 mdiMenu,
14 mdiChevronDown,
15 mdiChevronRight,
16 mdiViewSplitVertical,
17} from '@mdi/js';
18
19import Tabbar from '../services/tabs/Tabbar';
20import {
21 settingsShortcutKey,
22 lockFerdiumShortcutKey,
23 todosToggleShortcutKey,
24 workspaceToggleShortcutKey,
25 addNewServiceShortcutKey,
26 splitModeToggleShortcutKey,
27 muteFerdiumShortcutKey,
28} from '../../environment';
29import { todosStore } from '../../features/todos';
30import { todoActions } from '../../features/todos/actions';
31import globalMessages from '../../i18n/globalMessages';
32import Icon from '../ui/icon';
33import { Actions } from '../../actions/lib/actions';
34import { RealStores } from '../../stores';
35import Service from '../../models/Service';
36
37const messages = defineMessages({
38 addNewService: {
39 id: 'sidebar.addNewService',
40 defaultMessage: 'Add new service',
41 },
42 splitModeToggle: {
43 id: 'sidebar.splitModeToggle',
44 defaultMessage: 'Split Mode Toggle',
45 },
46 mute: {
47 id: 'sidebar.muteApp',
48 defaultMessage: 'Disable notifications & audio',
49 },
50 unmute: {
51 id: 'sidebar.unmuteApp',
52 defaultMessage: 'Enable notifications & audio',
53 },
54 openWorkspaceDrawer: {
55 id: 'sidebar.openWorkspaceDrawer',
56 defaultMessage: 'Open workspace drawer',
57 },
58 closeWorkspaceDrawer: {
59 id: 'sidebar.closeWorkspaceDrawer',
60 defaultMessage: 'Close workspace drawer',
61 },
62 openTodosDrawer: {
63 id: 'sidebar.openTodosDrawer',
64 defaultMessage: 'Open Ferdium Todos',
65 },
66 closeTodosDrawer: {
67 id: 'sidebar.closeTodosDrawer',
68 defaultMessage: 'Close Ferdium Todos',
69 },
70 lockFerdium: {
71 id: 'sidebar.lockFerdium',
72 defaultMessage: 'Lock Ferdium',
73 },
74});
75
76interface IProps extends WrappedComponentProps {
77 services: Service[];
78 showServicesUpdatedInfoBar: boolean;
79 showMessageBadgeWhenMutedSetting: boolean;
80 showServiceNameSetting: boolean;
81 showMessageBadgesEvenWhenMuted: boolean;
82 isAppMuted: boolean;
83 isMenuCollapsed: boolean;
84 isWorkspaceDrawerOpen: boolean;
85 isTodosServiceActive: boolean;
86 actions?: Actions;
87 stores?: RealStores;
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
106interface IState {
107 tooltipEnabled: boolean;
108}
109
110@observer
111@inject('stores', 'actions')
112class Sidebar extends Component<IProps, IState> {
113 constructor(props) {
114 super(props);
115
116 this.state = {
117 tooltipEnabled: true,
118 };
119 }
120
121 componentDidUpdate() {
122 ReactTooltip.rebuild();
123 }
124
125 enableToolTip() {
126 this.setState({ tooltipEnabled: true });
127 }
128
129 disableToolTip() {
130 this.setState({ tooltipEnabled: false });
131 }
132
133 updateToolTip() {
134 this.disableToolTip();
135 setTimeout(this.enableToolTip.bind(this));
136 }
137
138 render() {
139 const {
140 openSettings,
141 toggleMuteApp,
142 toggleCollapseMenu,
143 isAppMuted,
144 isWorkspaceDrawerOpen,
145 toggleWorkspaceDrawer,
146 stores,
147 actions,
148 isTodosServiceActive,
149 } = this.props;
150 const {
151 hideCollapseButton,
152 hideRecipesButton,
153 hideWorkspacesButton,
154 hideNotificationsButton,
155 hideSettingsButton,
156 hideSplitModeButton,
157 useHorizontalStyle,
158 splitMode,
159 } = stores!.settings.app;
160 const { intl } = this.props;
161 const todosToggleMessage = todosStore.isTodosPanelVisible
162 ? messages.closeTodosDrawer
163 : messages.openTodosDrawer;
164
165 const workspaceToggleMessage = isWorkspaceDrawerOpen
166 ? messages.closeWorkspaceDrawer
167 : messages.openWorkspaceDrawer;
168
169 const numberActiveButtons = [
170 !hideRecipesButton,
171 !hideWorkspacesButton,
172 !hideNotificationsButton,
173 !hideSettingsButton,
174 !hideSplitModeButton,
175 todosStore.isFeatureEnabledByUser,
176 ].filter(Boolean).length;
177
178 const { isMenuCollapsed } = stores!.settings.all.app;
179
180 return (
181 <div className="sidebar">
182 <Tabbar
183 {...this.props}
184 enableToolTip={() => this.enableToolTip()}
185 disableToolTip={() => this.disableToolTip()}
186 useHorizontalStyle={stores!.settings.all.app.useHorizontalStyle}
187 />
188 <>
189 {numberActiveButtons <= 1 || hideCollapseButton ? null : (
190 <button
191 type="button"
192 onClick={() => toggleCollapseMenu()}
193 className="sidebar__button sidebar__button--hamburger-menu"
194 >
195 {isMenuCollapsed ? <Icon icon={mdiMenu} size={1.5} /> : null}
196
197 {!isMenuCollapsed && !useHorizontalStyle ? (
198 <Icon icon={mdiChevronDown} size={1.5} />
199 ) : null}
200
201 {!isMenuCollapsed && useHorizontalStyle ? (
202 <Icon icon={mdiChevronRight} size={1.5} />
203 ) : null}
204 </button>
205 )}
206 {!hideRecipesButton && !isMenuCollapsed ? (
207 <button
208 type="button"
209 onClick={() => openSettings({ path: 'recipes' })}
210 className="sidebar__button sidebar__button--new-service"
211 data-tip={`${intl.formatMessage(
212 messages.addNewService,
213 )} (${addNewServiceShortcutKey(false)})`}
214 >
215 <Icon icon={mdiPlusBox} size={1.5} />
216 </button>
217 ) : null}
218 {!hideSplitModeButton && !isMenuCollapsed ? (
219 <button
220 type="button"
221 onClick={() => {
222 actions!.settings.update({
223 type: 'app',
224 data: {
225 splitMode: !splitMode,
226 },
227 });
228 }}
229 className="sidebar__button sidebar__button--split-mode-toggle"
230 data-tip={`${intl.formatMessage(
231 messages.splitModeToggle,
232 )} (${splitModeToggleShortcutKey(false)})`}
233 >
234 <Icon icon={mdiViewSplitVertical} size={1.5} />
235 </button>
236 ) : null}
237 {!hideWorkspacesButton && !isMenuCollapsed ? (
238 <button
239 type="button"
240 onClick={() => {
241 toggleWorkspaceDrawer();
242 this.updateToolTip();
243 }}
244 className={`sidebar__button sidebar__button--workspaces ${
245 isWorkspaceDrawerOpen ? 'is-active' : ''
246 }`}
247 data-tip={`${intl.formatMessage(
248 workspaceToggleMessage,
249 )} (${workspaceToggleShortcutKey(false)})`}
250 >
251 <Icon icon={mdiViewGrid} size={1.5} />
252 </button>
253 ) : null}
254 {!hideNotificationsButton && !isMenuCollapsed ? (
255 <button
256 type="button"
257 onClick={() => {
258 toggleMuteApp();
259 this.updateToolTip();
260 }}
261 className={`sidebar__button sidebar__button--audio ${
262 isAppMuted ? 'is-muted' : ''
263 }`}
264 data-tip={`${intl.formatMessage(
265 isAppMuted ? messages.unmute : messages.mute,
266 )} (${muteFerdiumShortcutKey(false)})`}
267 >
268 <Icon icon={isAppMuted ? mdiBellOff : mdiBell} size={1.5} />
269 </button>
270 ) : null}
271 {todosStore.isFeatureEnabledByUser && !isMenuCollapsed ? (
272 <button
273 type="button"
274 onClick={() => {
275 todoActions.toggleTodosPanel();
276 this.updateToolTip();
277 }}
278 disabled={isTodosServiceActive}
279 className={`sidebar__button sidebar__button--todos ${
280 todosStore.isTodosPanelVisible ? 'is-active' : ''
281 }`}
282 data-tip={`${intl.formatMessage(
283 todosToggleMessage,
284 )} (${todosToggleShortcutKey(false)})`}
285 >
286 <Icon icon={mdiCheckAll} size={1.5} />
287 </button>
288 ) : null}
289 {stores!.settings.all.app.lockingFeatureEnabled ? (
290 <button
291 type="button"
292 className="sidebar__button"
293 onClick={() => {
294 actions!.settings.update({
295 type: 'app',
296 data: {
297 locked: true,
298 },
299 });
300 }}
301 data-tip={`${intl.formatMessage(
302 messages.lockFerdium,
303 )} (${lockFerdiumShortcutKey(false)})`}
304 >
305 <Icon icon={mdiLock} size={1.5} />
306 </button>
307 ) : null}
308 </>
309 {this.state.tooltipEnabled && (
310 <ReactTooltip place="right" type="dark" effect="solid" />
311 )}
312 {!hideSettingsButton && !isMenuCollapsed ? (
313 <button
314 type="button"
315 onClick={() => openSettings({ path: 'app' })}
316 className="sidebar__button sidebar__button--settings"
317 data-tip={`${intl.formatMessage(
318 globalMessages.settings,
319 )} (${settingsShortcutKey(false)})`}
320 >
321 <Icon icon={mdiCog} size={1.5} />
322 {stores!.settings.app.automaticUpdates &&
323 (stores!.app.updateStatus ===
324 stores!.app.updateStatusTypes.AVAILABLE ||
325 stores!.app.updateStatus ===
326 stores!.app.updateStatusTypes.DOWNLOADED ||
327 this.props.showServicesUpdatedInfoBar) && (
328 <span className="update-available">•</span>
329 )}
330 </button>
331 ) : null}
332 </div>
333 );
334 }
335}
336
337export default injectIntl(Sidebar);