aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-15 14:51:05 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-16 00:55:04 +0200
commitc07e9b622b7befc0ceec645666c0214c94da4c05 (patch)
treef8969ea130210255e085ee7bc009838013e9802b
parentrefactor(renderer): remove StoreProvider (diff)
downloadsophie-c07e9b622b7befc0ceec645666c0214c94da4c05.tar.gz
sophie-c07e9b622b7befc0ceec645666c0214c94da4c05.tar.zst
sophie-c07e9b622b7befc0ceec645666c0214c94da4c05.zip
refactor(renderer): window title setting
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
-rw-r--r--packages/renderer/src/components/App.tsx66
-rw-r--r--packages/renderer/src/components/WindowTitle.tsx63
2 files changed, 86 insertions, 43 deletions
diff --git a/packages/renderer/src/components/App.tsx b/packages/renderer/src/components/App.tsx
index b0686a9..86e2a55 100644
--- a/packages/renderer/src/components/App.tsx
+++ b/packages/renderer/src/components/App.tsx
@@ -19,15 +19,31 @@
19 */ 19 */
20 20
21import Box from '@mui/material/Box'; 21import Box from '@mui/material/Box';
22import { styled } from '@mui/material/styles';
22import { observer } from 'mobx-react-lite'; 23import { observer } from 'mobx-react-lite';
23import React, { useCallback, useEffect } from 'react'; 24import React, { useCallback } from 'react';
24import { useTranslation } from 'react-i18next';
25 25
26import type RendererStore from '../stores/RendererStore'; 26import type RendererStore from '../stores/RendererStore';
27 27
28import ServicePanel from './ServicePanel'; 28import ServicePanel from './ServicePanel';
29import WindowTitle from './WindowTitle';
29import Sidebar from './sidebar/Sidebar'; 30import Sidebar from './sidebar/Sidebar';
30 31
32const AppRoot = styled(Box)({
33 display: 'flex',
34 overflow: 'hidden',
35 flexDirection: 'row',
36 alignItems: 'stretch',
37 height: '100vh',
38 width: '100vw',
39});
40
41const AppServiceArea = styled(Box)({
42 flex: 1,
43 height: '100%',
44 position: 'relative',
45});
46
31function App({ 47function App({
32 store, 48 store,
33 devMode, 49 devMode,
@@ -35,33 +51,10 @@ function App({
35 store: RendererStore; 51 store: RendererStore;
36 devMode: boolean; 52 devMode: boolean;
37}): JSX.Element { 53}): JSX.Element {
38 const { ready, t } = useTranslation(undefined, {
39 useSuspense: false,
40 });
41 const { 54 const {
42 settings: { selectedService }, 55 settings: { selectedService },
43 shared: { services }, 56 shared: { services },
44 } = store; 57 } = store;
45 const {
46 settings: { name: serviceName },
47 title: serviceTitle,
48 } = selectedService ?? { settings: { name: undefined }, title: undefined };
49
50 useEffect(() => {
51 if (!ready) {
52 // Only set title once the translations have been loaded.
53 return;
54 }
55 let title: string;
56 if (serviceName === undefined) {
57 title = t('title.noServiceName');
58 } else if (serviceTitle === undefined) {
59 title = t('title.withServiceName', { serviceName });
60 } else {
61 title = t('title.withServiceNameAndTitle', { serviceName, serviceTitle });
62 }
63 document.title = devMode ? t('title.devMode', { title }) : title;
64 }, [devMode, ready, serviceName, serviceTitle, t]);
65 58
66 const handleBackForwardMouseButtons = useCallback( 59 const handleBackForwardMouseButtons = useCallback(
67 (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => { 60 (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
@@ -83,31 +76,18 @@ function App({
83 ); 76 );
84 77
85 return ( 78 return (
86 <Box 79 <AppRoot
87 onClick={handleBackForwardMouseButtons} 80 onClick={handleBackForwardMouseButtons}
88 onAuxClick={handleBackForwardMouseButtons} 81 onAuxClick={handleBackForwardMouseButtons}
89 sx={{
90 display: 'flex',
91 overflow: 'hidden',
92 flexDirection: 'row',
93 alignItems: 'stretch',
94 height: '100vh',
95 width: '100vw',
96 }}
97 > 82 >
83 <WindowTitle selectedService={selectedService} devMode={devMode} />
98 <Sidebar store={store} /> 84 <Sidebar store={store} />
99 <Box 85 <AppServiceArea>
100 sx={{
101 flex: 1,
102 height: '100%',
103 position: 'relative',
104 }}
105 >
106 {services.map((service) => ( 86 {services.map((service) => (
107 <ServicePanel key={service.id} store={store} service={service} /> 87 <ServicePanel key={service.id} store={store} service={service} />
108 ))} 88 ))}
109 </Box> 89 </AppServiceArea>
110 </Box> 90 </AppRoot>
111 ); 91 );
112} 92}
113 93
diff --git a/packages/renderer/src/components/WindowTitle.tsx b/packages/renderer/src/components/WindowTitle.tsx
new file mode 100644
index 0000000..95e0fe6
--- /dev/null
+++ b/packages/renderer/src/components/WindowTitle.tsx
@@ -0,0 +1,63 @@
1/*
2 * Copyright (C) 2022 Kristóf Marussy <kristof@marussy.com>
3 *
4 * This file is part of Sophie.
5 *
6 * Sophie is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: AGPL-3.0-only
19 */
20
21import { observer } from 'mobx-react-lite';
22import { useEffect } from 'react';
23import { useTranslation } from 'react-i18next';
24
25import type Service from '../stores/Service';
26
27function WindowTitle({
28 selectedService,
29 devMode,
30}: {
31 selectedService: Service | undefined;
32 devMode: boolean;
33}): null {
34 const { ready, t } = useTranslation(undefined, {
35 useSuspense: false,
36 });
37
38 const {
39 settings: { name: serviceName },
40 title: serviceTitle,
41 } = selectedService ?? { settings: { name: undefined }, title: undefined };
42
43 useEffect(() => {
44 if (!ready) {
45 // Only set title once the translations have been loaded.
46 return;
47 }
48 let title: string;
49 if (serviceName === undefined) {
50 title = t('title.noServiceName');
51 } else if (serviceTitle === undefined) {
52 title = t('title.withServiceName', { serviceName });
53 } else {
54 title = t('title.withServiceNameAndTitle', { serviceName, serviceTitle });
55 }
56 document.title = devMode ? t('title.devMode', { title }) : title;
57 }, [devMode, ready, serviceName, serviceTitle, t]);
58
59 // eslint-disable-next-line unicorn/no-null -- React requires `null` to skip rendering.
60 return null;
61}
62
63export default observer(WindowTitle);