aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/layout/AppLayout.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/layout/AppLayout.tsx')
-rw-r--r--src/components/layout/AppLayout.tsx231
1 files changed, 231 insertions, 0 deletions
diff --git a/src/components/layout/AppLayout.tsx b/src/components/layout/AppLayout.tsx
new file mode 100644
index 000000000..c2468e852
--- /dev/null
+++ b/src/components/layout/AppLayout.tsx
@@ -0,0 +1,231 @@
1import React, { Component } from 'react';
2import { observer } from 'mobx-react';
3import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl';
4import { TitleBar } from 'electron-react-titlebar/renderer';
5import injectSheet, { WithStylesProps } from 'react-jss';
6import { ipcRenderer } from 'electron';
7
8import { mdiFlash, mdiPowerPlug } from '@mdi/js';
9import { Outlet } from 'react-router-dom';
10import InfoBar from '../ui/InfoBar';
11import { Component as BasicAuth } from '../../features/basicAuth';
12import { Component as QuickSwitch } from '../../features/quickSwitch';
13import { Component as PublishDebugInfo } from '../../features/publishDebugInfo';
14import ErrorBoundary from '../util/ErrorBoundary';
15import { updateVersionParse } from '../../helpers/update-helpers';
16
17// import globalMessages from '../../i18n/globalMessages';
18import { isMac, isWindows } from '../../environment';
19import WorkspaceSwitchingIndicator from '../../features/workspaces/components/WorkspaceSwitchingIndicator';
20import { workspaceStore } from '../../features/workspaces';
21import AppUpdateInfoBar from '../AppUpdateInfoBar';
22import Todos from '../../features/todos/containers/TodosScreen';
23import Icon from '../ui/icon';
24
25import LockedScreen from '../../containers/auth/LockedScreen';
26import SettingsStore from '../../stores/SettingsStore';
27
28const messages = defineMessages({
29 servicesUpdated: {
30 id: 'infobar.servicesUpdated',
31 defaultMessage: 'Your services have been updated.',
32 },
33 buttonReloadServices: {
34 id: 'infobar.buttonReloadServices',
35 defaultMessage: 'Reload services',
36 },
37 requiredRequestsFailed: {
38 id: 'infobar.requiredRequestsFailed',
39 defaultMessage: 'Could not load services and user information',
40 },
41 authRequestFailed: {
42 id: 'infobar.authRequestFailed',
43 defaultMessage:
44 'There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.',
45 },
46});
47
48let transition = 'none';
49
50if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) {
51 transition = 'transform 0.5s ease';
52}
53
54const styles = theme => ({
55 appContent: {
56 // width: `calc(100% + ${theme.workspaces.drawer.width}px)`,
57 width: '100%',
58 transition,
59 transform() {
60 return workspaceStore.isWorkspaceDrawerOpen
61 ? 'translateX(0)'
62 : `translateX(-${theme.workspaces.drawer.width}px)`;
63 },
64 },
65 titleBar: {
66 display: 'block',
67 zIndex: 1,
68 width: '100%',
69 height: '10px',
70 position: 'absolute',
71 top: 0,
72 },
73});
74
75const toggleFullScreen = () => {
76 ipcRenderer.send('window.toolbar-double-clicked');
77};
78
79interface IProps extends WrappedComponentProps, WithStylesProps<typeof styles> {
80 settings: SettingsStore;
81 updateVersion: string;
82 isFullScreen: boolean;
83 sidebar: React.ReactElement;
84 workspacesDrawer: React.ReactElement;
85 services: React.ReactElement;
86 showServicesUpdatedInfoBar: boolean;
87 appUpdateIsDownloaded: boolean;
88 authRequestFailed: boolean;
89 installAppUpdate: () => void;
90 showRequiredRequestsError: boolean;
91 areRequiredRequestsSuccessful: boolean;
92 retryRequiredRequests: () => void;
93 areRequiredRequestsLoading: boolean;
94}
95
96interface IState {
97 shouldShowAppUpdateInfoBar: boolean;
98 shouldShowServicesUpdatedInfoBar: boolean;
99}
100
101@observer
102class AppLayout extends Component<IProps, IState> {
103 constructor(props) {
104 super(props);
105
106 this.state = {
107 shouldShowAppUpdateInfoBar: true,
108 shouldShowServicesUpdatedInfoBar: true,
109 };
110 }
111
112 render() {
113 const {
114 classes,
115 isFullScreen,
116 workspacesDrawer,
117 sidebar,
118 services,
119 showServicesUpdatedInfoBar,
120 appUpdateIsDownloaded,
121 authRequestFailed,
122 installAppUpdate,
123 settings,
124 showRequiredRequestsError,
125 areRequiredRequestsSuccessful,
126 retryRequiredRequests,
127 areRequiredRequestsLoading,
128 updateVersion,
129 } = this.props;
130
131 const { intl } = this.props;
132
133 const { locked, automaticUpdates } = settings.app;
134 if (locked) {
135 return <LockedScreen />;
136 }
137
138 return (
139 <>
140 {isMac && !isFullScreen && <div className="window-draggable" />}
141 <ErrorBoundary>
142 <div className="app">
143 {isWindows && !isFullScreen && (
144 <TitleBar
145 menu={window['ferdium'].menu.template}
146 icon="assets/images/logo.svg"
147 />
148 )}
149 {isMac && !isFullScreen && (
150 <span
151 onDoubleClick={toggleFullScreen}
152 className={classes.titleBar}
153 />
154 )}
155 <div className={`app__content ${classes.appContent}`}>
156 {workspacesDrawer}
157 {sidebar}
158 <div className="app__service">
159 <WorkspaceSwitchingIndicator />
160 {!areRequiredRequestsSuccessful && showRequiredRequestsError && (
161 <InfoBar
162 type="danger"
163 ctaLabel="Try again"
164 ctaLoading={areRequiredRequestsLoading}
165 sticky
166 onClick={retryRequiredRequests}
167 >
168 <Icon icon={mdiFlash} />
169 {intl.formatMessage(messages.requiredRequestsFailed)}
170 </InfoBar>
171 )}
172 {authRequestFailed && (
173 <InfoBar
174 type="danger"
175 ctaLabel="Try again"
176 ctaLoading={areRequiredRequestsLoading}
177 sticky
178 onClick={retryRequiredRequests}
179 >
180 <Icon icon={mdiFlash} />
181 {intl.formatMessage(messages.authRequestFailed)}
182 </InfoBar>
183 )}
184 {automaticUpdates &&
185 showServicesUpdatedInfoBar &&
186 this.state.shouldShowServicesUpdatedInfoBar && (
187 <InfoBar
188 type="primary"
189 ctaLabel={intl.formatMessage(
190 messages.buttonReloadServices,
191 )}
192 onClick={() => window.location.reload()}
193 onHide={() => {
194 this.setState({
195 shouldShowServicesUpdatedInfoBar: false,
196 });
197 }}
198 >
199 <Icon icon={mdiPowerPlug} />
200 {intl.formatMessage(messages.servicesUpdated)}
201 </InfoBar>
202 )}
203 {automaticUpdates &&
204 appUpdateIsDownloaded &&
205 this.state.shouldShowAppUpdateInfoBar && (
206 <AppUpdateInfoBar
207 onInstallUpdate={installAppUpdate}
208 updateVersionParsed={updateVersionParse(updateVersion)}
209 onHide={() => {
210 this.setState({ shouldShowAppUpdateInfoBar: false });
211 }}
212 />
213 )}
214 <BasicAuth />
215 <QuickSwitch />
216 <PublishDebugInfo />
217 {services}
218 <Outlet />
219 </div>
220 <Todos />
221 </div>
222 </div>
223 </ErrorBoundary>
224 </>
225 );
226 }
227}
228
229export default injectIntl(
230 injectSheet(styles, { injectTheme: true })(AppLayout),
231);