Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit b299d0f

Browse files
feat: added custom titlebar
1 parent 06961f8 commit b299d0f

File tree

7 files changed

+232
-82
lines changed

7 files changed

+232
-82
lines changed

src/main/main.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,15 @@ const createWindow = async () => {
7373
show: false,
7474
autoHideMenuBar: true,
7575
frame: false,
76-
titleBarStyle: 'hidden',
7776
width: 1024,
7877
height: 728,
78+
minWidth: 600,
79+
minHeight: 300,
7980
icon: getAssetPath('icon.png'),
8081
webPreferences: {
8182
sandbox: false,
83+
nodeIntegration: true,
84+
contextIsolation: true,
8285
preload: app.isPackaged
8386
? path.join(__dirname, 'preload.js')
8487
: path.join(__dirname, '../../.erb/dll/preload.js'),
@@ -132,6 +135,17 @@ app
132135
.whenReady()
133136
.then(() => {
134137
createWindow();
138+
139+
ipcMain.on('minimizeApp', () => {
140+
mainWindow?.minimize();
141+
});
142+
ipcMain.on('maximizeApp', () => {
143+
mainWindow?.maximize();
144+
});
145+
ipcMain.on('closeApp', () => {
146+
mainWindow?.close();
147+
});
148+
135149
app.on('activate', () => {
136150
// On macOS it's common to re-create a window in the app when the
137151
// dock icon is clicked and there are no other windows open.

src/main/preload.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
22

3-
export type Channels = 'ipc-example';
3+
export type Channels =
4+
| 'ipc-example'
5+
| 'minimizeApp'
6+
| 'maximizeApp'
7+
| 'closeApp';
48

59
contextBridge.exposeInMainWorld('electron', {
610
ipcRenderer: {
32.3 KB
Loading
Lines changed: 52 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,76 @@
11
import { ReactNode } from 'react';
22
import { useLocation } from 'react-router-dom';
3-
import { Box, Button, Flex, Link, useDisclosure } from '@chakra-ui/react';
4-
import { Avatar, EmptyState } from '@codiga/codiga-components';
3+
import { Box, Button, Flex, useDisclosure } from '@chakra-ui/react';
4+
import { EmptyState } from '@codiga/codiga-components';
55

6-
import { APP_URL } from 'renderer/lib/config';
7-
import { getAvatarUrl } from 'renderer/utils/userUtils';
86
import Login from 'renderer/components/Login';
97
import { useUser } from 'renderer/components/UserContext';
108
import SideMenu from './SideMenu';
9+
import Titlebar from './Titlebar';
1110

1211
type LayoutProps = {
1312
children: ReactNode;
1413
};
1514

1615
export default function Layout({ children }: LayoutProps) {
1716
const { pathname } = useLocation();
18-
const { id, username, accountType } = useUser();
17+
const { id } = useUser();
1918
const { isOpen, onOpen, onClose } = useDisclosure();
2019

2120
return (
22-
<Flex
23-
flexDirection="column"
24-
h="100vh"
25-
w="100vw"
26-
bg="neutral.25"
27-
_dark={{ bg: 'base.dark' }}
28-
>
21+
<>
2922
<Flex
30-
w="full"
31-
justifyContent="flex-end"
32-
alignItems="center"
33-
gridGap="space_16"
34-
pr="space_16"
35-
h="40px"
23+
flexDirection="column"
24+
h="100vh"
25+
w="100vw"
26+
bg="neutral.25"
27+
_dark={{ bg: 'base.dark' }}
3628
>
37-
<Link
38-
isExternal
39-
href={`${APP_URL}/assistant/snippet/create`}
40-
variant="square"
41-
>
42-
Create Snippet
43-
</Link>
29+
<Titlebar openLoginModal={onOpen} />
4430

45-
{id ? (
46-
<Avatar
47-
name={username || 'Anon'}
48-
kind={accountType as any}
49-
src={getAvatarUrl({ id, username, accountType })}
50-
size="sm"
51-
/>
52-
) : (
53-
// eslint-disable-next-line jsx-a11y/anchor-is-valid
54-
<Link as="button" onClick={onOpen} variant="solid" size="sm" p="0">
55-
Login
56-
</Link>
57-
)}
58-
</Flex>
59-
60-
<Flex flex={1}>
61-
<Box
62-
w="214px"
63-
h="full"
64-
bg="neutral.25"
65-
_dark={{ bg: 'base.dark' }}
66-
pt="space_16"
67-
>
68-
<SideMenu openLoginModal={onOpen} />
69-
</Box>
70-
71-
<Flex
72-
flex={1}
73-
justifyContent="center"
74-
alignItems="flex-start"
75-
pt="space_16"
76-
bg="neutral.0"
77-
_dark={{ bg: 'neutral.100' }}
78-
>
79-
<Box w="full">
80-
{/* IF THE USER'S LOGGED IN, SHOW CONTENT, OTHERWISE SHOW AN LOGIN NOTICE */}
81-
{id || pathname === '/' ? (
82-
children
83-
) : (
84-
<EmptyState
85-
title="Log in to access this section"
86-
description="Add your API Token to access this section"
87-
illustration="disconnected"
88-
mt="space_80"
89-
mx="auto"
90-
>
91-
<Button variant="primary" size="sm" onClick={onOpen}>
92-
Add Token
93-
</Button>
94-
</EmptyState>
95-
)}
31+
<Flex flex={1}>
32+
<Box
33+
w="214px"
34+
h="full"
35+
bg="neutral.25"
36+
_dark={{ bg: 'base.dark' }}
37+
pt="space_16"
38+
>
39+
<SideMenu openLoginModal={onOpen} />
9640
</Box>
41+
42+
<Flex
43+
flex={1}
44+
justifyContent="center"
45+
alignItems="flex-start"
46+
pt="space_16"
47+
bg="neutral.0"
48+
_dark={{ bg: 'neutral.100' }}
49+
>
50+
<Box w="full">
51+
{/* IF THE USER'S LOGGED IN, SHOW CONTENT, OTHERWISE SHOW AN LOGIN NOTICE */}
52+
{id || pathname === '/' ? (
53+
children
54+
) : (
55+
<EmptyState
56+
title="Log in to access this section"
57+
description="Add your API Token to access this section"
58+
illustration="disconnected"
59+
mt="space_80"
60+
mx="auto"
61+
>
62+
<Button variant="primary" size="sm" onClick={onOpen}>
63+
Add Token
64+
</Button>
65+
</EmptyState>
66+
)}
67+
</Box>
68+
</Flex>
9769
</Flex>
98-
</Flex>
9970

100-
{/* LOGIN MODAL */}
101-
<Login isOpen={isOpen} closeModal={onClose} />
102-
</Flex>
71+
{/* LOGIN MODAL */}
72+
<Login isOpen={isOpen} closeModal={onClose} />
73+
</Flex>
74+
</>
10375
);
10476
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/* eslint-disable react/button-has-type */
2+
/* eslint-disable jsx-a11y/control-has-associated-label */
3+
import { Flex, Link, Image } from '@chakra-ui/react';
4+
import { Avatar } from '@codiga/codiga-components';
5+
import { useUser } from 'renderer/components/UserContext';
6+
import { APP_URL } from 'renderer/lib/config';
7+
import { getAvatarUrl } from 'renderer/utils/userUtils';
8+
import CodigaLogo from './CodigaIcon.png';
9+
import TitlebarButton from './TitlebarButton';
10+
11+
type TitlebarProps = {
12+
openLoginModal: () => void;
13+
};
14+
15+
export default function Titlebar({ openLoginModal }: TitlebarProps) {
16+
const { id, username, accountType } = useUser();
17+
18+
return (
19+
<Flex
20+
draggable
21+
as="nav"
22+
h="40px"
23+
alignItems="center"
24+
justifyContent="space-between"
25+
bg="neutral.25"
26+
_dark={{ bg: 'base.dark' }}
27+
sx={{
28+
'-webkit-app-region': 'drag',
29+
}}
30+
>
31+
<Image src={CodigaLogo} h="24px" ml="space_16" />
32+
33+
<Flex
34+
alignItems="center"
35+
gridGap="space_16"
36+
sx={{ '-webkit-app-region': 'no-drag' }}
37+
>
38+
<Link
39+
isExternal
40+
href={`${APP_URL}/assistant/snippet/create`}
41+
variant="square"
42+
>
43+
Create Snippet
44+
</Link>
45+
46+
<Flex w="32px" alignItems="center">
47+
{id ? (
48+
<Avatar
49+
name={username || 'Anon'}
50+
kind={accountType as any}
51+
src={getAvatarUrl({ id, username, accountType })}
52+
size="sm"
53+
/>
54+
) : (
55+
// eslint-disable-next-line jsx-a11y/anchor-is-valid
56+
<Link
57+
as="button"
58+
onClick={openLoginModal}
59+
variant="solid"
60+
size="sm"
61+
p="0"
62+
>
63+
Login
64+
</Link>
65+
)}
66+
</Flex>
67+
68+
<Flex>
69+
<TitlebarButton message="minimizeApp">
70+
<svg
71+
width="12"
72+
height="12"
73+
xmlns="http://www.w3.org/2000/svg"
74+
viewBox="0 0 448 512"
75+
>
76+
<path d="M400 288h-352c-17.69 0-32-14.32-32-32.01s14.31-31.99 32-31.99h352c17.69 0 32 14.3 32 31.99S417.7 288 400 288z" />
77+
</svg>
78+
</TitlebarButton>
79+
<TitlebarButton message="maximizeApp">
80+
<svg
81+
width="12"
82+
height="12"
83+
xmlns="http://www.w3.org/2000/svg"
84+
viewBox="0 0 448 512"
85+
>
86+
<path d="M128 32H32C14.31 32 0 46.31 0 64v96c0 17.69 14.31 32 32 32s32-14.31 32-32V96h64c17.69 0 32-14.31 32-32S145.7 32 128 32zM416 32h-96c-17.69 0-32 14.31-32 32s14.31 32 32 32h64v64c0 17.69 14.31 32 32 32s32-14.31 32-32V64C448 46.31 433.7 32 416 32zM128 416H64v-64c0-17.69-14.31-32-32-32s-32 14.31-32 32v96c0 17.69 14.31 32 32 32h96c17.69 0 32-14.31 32-32S145.7 416 128 416zM416 320c-17.69 0-32 14.31-32 32v64h-64c-17.69 0-32 14.31-32 32s14.31 32 32 32h96c17.69 0 32-14.31 32-32v-96C448 334.3 433.7 320 416 320z" />
87+
</svg>
88+
</TitlebarButton>
89+
90+
<TitlebarButton message="closeApp">
91+
<svg
92+
width="12"
93+
height="12"
94+
xmlns="http://www.w3.org/2000/svg"
95+
viewBox="0 0 320 512"
96+
>
97+
<path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z" />
98+
</svg>
99+
</TitlebarButton>
100+
</Flex>
101+
</Flex>
102+
</Flex>
103+
);
104+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Button, ButtonProps } from '@chakra-ui/react';
2+
3+
type TitlebarButtonProps = {
4+
message: 'minimizeApp' | 'maximizeApp' | 'closeApp';
5+
} & ButtonProps;
6+
7+
export default function TitlebarButton({
8+
message,
9+
children,
10+
...props
11+
}: TitlebarButtonProps) {
12+
return (
13+
<Button
14+
variant="unstyled"
15+
minW="32px"
16+
maxW="32px"
17+
h="32px"
18+
m="2px"
19+
display="flex"
20+
alignItems="center"
21+
justifyContent="center"
22+
fill="neutral.100"
23+
_dark={{ fill: 'neutral.0' }}
24+
onClick={() => {
25+
window.electron.ipcRenderer.sendMessage(message, [message]);
26+
}}
27+
{...props}
28+
>
29+
{children}
30+
</Button>
31+
);
32+
}

src/renderer/styles/app.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#title-bar {
2+
-webkit-app-region: drag;
3+
height: 24px;
4+
background-color: darkviolet;
5+
padding: none;
6+
margin: 0px;
7+
}
8+
9+
#title {
10+
position: fixed;
11+
top: 0px;
12+
left: 16px;
13+
}
14+
15+
#title-bar-btns {
16+
-webkit-app-region: no-drag;
17+
/* position: fixed;
18+
top: 0px;
19+
right: 16px; */
20+
}
21+
22+
#title-bar-btns button {
23+
margin: 0 10px;
24+
}

0 commit comments

Comments
 (0)