Skip to content

Commit dc00f89

Browse files
committed
feat: new developer menu, improve modal handling
1 parent d8183cb commit dc00f89

File tree

11 files changed

+333
-128
lines changed

11 files changed

+333
-128
lines changed

src/main/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ import {
4343
getBrightness,
4444
setBrightnessSmooth,
4545
getAutoBrightness,
46-
setAutoBrightness
46+
setAutoBrightness,
47+
restore
4748
} from './lib/adb.js'
4849
import {
4950
getShortcuts,
@@ -194,6 +195,7 @@ enum IPCHandler {
194195
FindCarThing = 'findCarThing',
195196
FindSetupCarThing = 'findSetupCarThing',
196197
RebootCarThing = 'rebootCarThing',
198+
RestoreCarThing = 'restoreCarThing',
197199
InstallApp = 'installApp',
198200
StartServer = 'startServer',
199201
StopServer = 'stopServer',
@@ -252,6 +254,10 @@ async function setupIpcHandlers() {
252254
await rebootCarThing(null)
253255
})
254256

257+
ipcMain.handle(IPCHandler.RestoreCarThing, async () => {
258+
await restore(null)
259+
})
260+
255261
ipcMain.handle(IPCHandler.InstallApp, async () => {
256262
const res = await installApp(null).catch(err => ({ err }))
257263
if (res?.err) return res.err.message

src/preload/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ declare global {
1717
'not_found' | 'not_installed' | 'ready'
1818
>
1919
rebootCarThing: () => Promise<void>
20+
restoreCarThing: () => Promise<void>
2021
installApp: () => Promise<string | true>
2122
startServer: () => Promise<void>
2223
stopServer: () => Promise<void>

src/preload/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum IPCHandler {
99
FindCarThing = 'findCarThing',
1010
FindSetupCarThing = 'findSetupCarThing',
1111
RebootCarThing = 'rebootCarThing',
12+
RestoreCarThing = 'restoreCarThing',
1213
InstallApp = 'installApp',
1314
StartServer = 'startServer',
1415
StopServer = 'stopServer',
@@ -56,6 +57,7 @@ const api = {
5657
findSetupCarThing: () =>
5758
ipcRenderer.invoke(IPCHandler.FindSetupCarThing),
5859
rebootCarThing: () => ipcRenderer.invoke(IPCHandler.RebootCarThing),
60+
restoreCarThing: () => ipcRenderer.invoke(IPCHandler.RestoreCarThing),
5961
installApp: () => ipcRenderer.invoke(IPCHandler.InstallApp),
6062
startServer: () => ipcRenderer.invoke(IPCHandler.StartServer),
6163
stopServer: () => ipcRenderer.invoke(IPCHandler.StopServer),

src/renderer/src/App.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Route, Routes } from 'react-router-dom'
22

3-
import Developer from './pages/Developer/Developer.js'
43
import Setup from './pages/Setup/Setup.js'
54
import Layout from './components/Layout/Layout.js'
65
import Home from './pages/Home/Home.js'
@@ -11,7 +10,6 @@ const App: React.FC = () => {
1110
<Route path="/" element={<Layout />}>
1211
<Route index element={<Home />} />
1312
<Route path="/setup" element={<Setup />} />
14-
<Route path="/developer" element={<Developer />} />
1513
</Route>
1614
</Routes>
1715
)

src/renderer/src/components/Layout/Layout.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import React from 'react'
22
import { Outlet } from 'react-router-dom'
33

4+
import Developer from '@/pages/Developer/Developer.js'
45
import Shortcuts from '@/pages/Shortcuts/Shortcuts.js'
56
import Settings from '@/pages/Settings/Settings.js'
7+
68
import Titlebar from '@/components/Titlebar/Titlebar.js'
79

810
import styles from './Layout.module.css'
@@ -18,6 +20,7 @@ const Layout: React.FC = () => {
1820
</div>
1921
<Settings />
2022
<Shortcuts />
23+
<Developer />
2124
</>
2225
)
2326
}

src/renderer/src/components/Titlebar/Titlebar.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
import React, { useContext } from 'react'
2-
import { useNavigate } from 'react-router-dom'
32

43
import { DevModeContext } from '@/contexts/DevModeContext.js'
54
import { ModalContext } from '@/contexts/ModalContext.js'
65

76
import styles from './Titlebar.module.css'
87

98
const Titlebar: React.FC = () => {
10-
const navigate = useNavigate()
11-
const { setSettingsOpen, setShortcutsEditorOpen } =
12-
useContext(ModalContext)
9+
const { openModals, setModalOpen } = useContext(ModalContext)
1310
const { devMode } = useContext(DevModeContext)
1411

1512
const buttons = [
1613
...(devMode
1714
? [
1815
{
1916
icon: 'code',
20-
action: () => navigate('/developer')
17+
action: () =>
18+
setModalOpen('developer', !openModals.includes('developer'))
2119
}
2220
]
2321
: []),
2422
{
2523
icon: 'apps',
26-
action: () => setShortcutsEditorOpen(true)
24+
action: () =>
25+
setModalOpen('shortcuts', !openModals.includes('shortcuts'))
2726
},
2827
{
2928
icon: 'settings',
30-
action: () => setSettingsOpen(true)
29+
action: () =>
30+
setModalOpen('settings', !openModals.includes('settings'))
3131
},
3232
{
3333
icon: 'close',

src/renderer/src/contexts/ModalContext.tsx

Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,13 @@ import { createContext, useEffect, useState } from 'react'
22
import { useLocation } from 'react-router-dom'
33

44
interface ModalContextType {
5-
settingsOpen: boolean
6-
setSettingsOpen: (value: boolean) => void
7-
shortcutsEditorOpen: boolean
8-
setShortcutsEditorOpen: (value: boolean) => void
5+
openModals: string[]
6+
setModalOpen: (modalName: string, value: boolean) => void
97
}
108

119
const ModalContext = createContext<ModalContextType>({
12-
settingsOpen: false,
13-
setSettingsOpen: () => {},
14-
shortcutsEditorOpen: false,
15-
setShortcutsEditorOpen: () => {}
10+
openModals: [],
11+
setModalOpen: () => {}
1612
})
1713

1814
interface ModalContextProviderProps {
@@ -21,41 +17,24 @@ interface ModalContextProviderProps {
2117

2218
const ModalContextProvider = ({ children }: ModalContextProviderProps) => {
2319
const location = useLocation()
24-
const [settingsOpen, _setSettingsOpen] = useState(false)
25-
const [shortcutsEditorOpen, _setShortcutsEditorOpen] = useState(false)
20+
const [openModals, setOpenModals] = useState<string[]>([])
2621

27-
function setSettingsOpen(value: boolean) {
28-
if (value) {
29-
_setShortcutsEditorOpen(false)
30-
_setSettingsOpen(true)
31-
} else {
32-
_setSettingsOpen(false)
33-
}
34-
}
35-
36-
function setShortcutsEditorOpen(value: boolean) {
37-
if (value) {
38-
_setSettingsOpen(false)
39-
_setShortcutsEditorOpen(true)
40-
} else {
41-
_setShortcutsEditorOpen(false)
42-
}
22+
const setModalOpen = (modalName: string, value: boolean) => {
23+
setOpenModals(prev => {
24+
if (value) return [modalName]
25+
else return prev.filter(modal => modal !== modalName)
26+
})
4327
}
4428

4529
useEffect(() => {
46-
if (settingsOpen || shortcutsEditorOpen) {
47-
_setSettingsOpen(false)
48-
_setShortcutsEditorOpen(false)
49-
}
30+
setOpenModals([])
5031
}, [location.pathname])
5132

5233
return (
5334
<ModalContext.Provider
5435
value={{
55-
settingsOpen,
56-
setSettingsOpen,
57-
shortcutsEditorOpen,
58-
setShortcutsEditorOpen
36+
openModals,
37+
setModalOpen
5938
}}
6039
>
6140
{children}
Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,117 @@
11
.developer {
2+
position: fixed;
3+
top: 0;
4+
left: 0;
5+
width: 100%;
6+
height: 100%;
7+
8+
display: flex;
9+
align-items: center;
10+
justify-content: center;
11+
12+
opacity: 0;
13+
pointer-events: none;
14+
transition: 200ms ease;
15+
}
16+
17+
.developer[data-open='true'] {
18+
opacity: 1;
19+
backdrop-filter: blur(5px);
20+
pointer-events: all;
21+
}
22+
23+
.box {
24+
width: 500px;
25+
height: 300px;
26+
padding: 15px;
27+
background: #111;
28+
border-radius: 5px;
29+
transition: transform 200ms ease;
30+
transform: scale(1.05);
31+
232
display: flex;
333
flex-direction: column;
434
gap: 10px;
5-
align-items: flex-start;
6-
margin: 20px;
7-
animation: appear 500ms ease;
835
}
936

10-
.buttons {
37+
.developer[data-open='true'] .box {
38+
transform: scale(1);
39+
}
40+
41+
.header .close {
42+
all: unset;
43+
cursor: pointer;
44+
}
45+
46+
.header {
47+
display: flex;
48+
justify-content: space-between;
49+
align-items: center;
50+
}
51+
52+
.section {
53+
display: flex;
54+
flex-direction: column;
55+
gap: 5px;
56+
}
57+
58+
.section .status {
59+
display: flex;
60+
align-items: center;
61+
gap: 8px;
62+
font-size: 16px;
63+
}
64+
65+
.section .status .dot {
66+
width: 10px;
67+
height: 10px;
68+
border-radius: 50%;
69+
background: #444;
70+
}
71+
72+
.section .status .dot[data-color='green'] {
73+
background: #00ff00;
74+
}
75+
76+
.section .status .dot[data-color='orange'] {
77+
background: #ff8800;
78+
}
79+
80+
.section .status .dot[data-color='red'] {
81+
background: #ff0000;
82+
}
83+
84+
.section .actions {
85+
display: flex;
86+
gap: 5px;
87+
flex-wrap: wrap;
88+
}
89+
90+
.section .actions button {
91+
padding: 6px 8px;
92+
font-size: 14px;
93+
display: flex;
94+
align-items: center;
95+
gap: 5px;
96+
}
97+
98+
.section .actions button[data-color='red'] {
99+
background: #ff0000;
100+
}
101+
102+
.bottomActions {
103+
position: absolute;
104+
bottom: 0;
105+
right: 0;
106+
padding: 15px;
11107
display: flex;
12108
gap: 10px;
13109
}
14110

15-
@keyframes appear {
16-
from {
17-
opacity: 0;
18-
transform: translateY(10px);
19-
}
20-
to {
21-
opacity: 1;
22-
transform: translateY(0);
23-
}
111+
.bottomActions button {
112+
padding: 6px 8px;
113+
font-size: 14px;
114+
display: flex;
115+
align-items: center;
116+
gap: 5px;
24117
}

0 commit comments

Comments
 (0)