Skip to content

Commit 13f2057

Browse files
committed
refactor: port UI store to context API
1 parent 24efc14 commit 13f2057

File tree

12 files changed

+196
-134
lines changed

12 files changed

+196
-134
lines changed

GUI/ETVR/src/components/NewWindow/index.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { children, createSignal, createEffect, Show, onMount, onCleanup } from 'solid-js'
22
import { Portal } from 'solid-js/web'
33
import { onClickOutside, useEventListener } from 'solidjs-use'
4-
import { menuOpenStatus } from '@store/ui/selectors'
5-
import { setMenu, type INewMenu } from '@store/ui/ui'
4+
import type { NewMenu } from '@static/types/interfaces'
5+
import { useAppUIContext } from '@src/store/context/ui'
66
import './styles.css'
77

8-
const NewMenu = (props: INewMenu) => {
8+
const NewMenu = (props: NewMenu) => {
99
const [ref, setRef] = createSignal<HTMLElement>()
1010
const Children = children(() => props.children)
1111

12+
const { menuOpenStatus, setMenu } = useAppUIContext()
13+
1214
onMount(() => {
1315
if (props.ref) {
1416
useEventListener(props.ref, 'contextmenu', (e) => {
@@ -45,7 +47,7 @@ const NewMenu = (props: INewMenu) => {
4547
top: `${menuOpenStatus()?.y ?? 0}px`,
4648
left: `${menuOpenStatus()?.x ?? 0}px`,
4749
}}>
48-
{Children()}
50+
<Children />
4951
</div>
5052
</Portal>
5153
</Show>

GUI/ETVR/src/components/WebSocket/index.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Switch, Match, Show } from 'solid-js'
22
import { OrangeLoader, MagentaLoader } from '@components/Loader'
3+
import { useAppUIContext } from '@src/store/context/ui'
34
import { classNames } from '@src/utils'
45
import { CameraStatus } from '@static/types/enums'
5-
import { showCameraView } from '@store/ui/selectors'
66

77
// TODO: Grab selected camera from store, connect if not connected, and display video stream on component mounted
88
type IWsProps = {
@@ -32,6 +32,8 @@ export const LoaderHandler = (props: IWsProps) => {
3232
}
3333

3434
const WebSocketHandler = (props: IWsProps) => {
35+
const { showCameraView } = useAppUIContext()
36+
3537
return (
3638
<div class="w-full h-full">
3739
<Show

GUI/ETVR/src/pages/Home/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useNavigate } from '@solidjs/router'
22
import { useAppAPIContext } from '@src/store/context/api'
3+
import { useAppUIContext } from '@src/store/context/ui'
34
import Home from '@src/views/Home'
45
import { useAppCameraContext } from '@store/context/camera'
5-
import { setHideHeaderButtons } from '@store/ui/ui'
66

77
const HomePage = () => {
88
const { getFirmwareVersion, setRESTDevice } = useAppAPIContext()
9-
109
const { getCameras, setSelectedCamera, resetSelectedCamera } = useAppCameraContext()
10+
const { setHideHeaderButtons } = useAppUIContext()
1111

1212
let firmwareVersion = '0.0.0'
1313
let setRestDevice: (device: string) => void = () => {

GUI/ETVR/src/pages/Settings/index.tsx

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { useNavigate, useParams } from '@solidjs/router'
2+
import { useAppUIContext } from '@src/store/context/ui'
23
import Settings from '@src/views/Settings'
34
import { useAppCameraContext } from '@store/context/camera'
4-
import { setHideHeaderButtons } from '@store/ui/ui'
55

66
const SettingsPage = () => {
77
const navigate = useNavigate()
88
const params = useParams()
99

1010
const { getSelectedCamera } = useAppCameraContext()
1111

12+
const { setHideHeaderButtons } = useAppUIContext()
13+
1214
return (
1315
<Settings
1416
createNewCamera={params.flag === 'true'}

GUI/ETVR/src/routes/Routes.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import { useAppContext } from '@src/store/context/app'
1010
import { useAppCameraContext } from '@src/store/context/camera'
1111
import { useAppMDNSContext } from '@src/store/context/mdns'
1212
import { useAppNotificationsContext } from '@src/store/context/notifications'
13+
import { useAppUIContext } from '@src/store/context/ui'
1314
import { usePersistentStore } from '@src/store/tauriStore'
14-
import { connectedUserName, hideHeaderButtons } from '@src/store/ui/selectors'
15-
import { setConnectedUser, setHideHeaderButtons } from '@src/store/ui/ui'
1615
import { generateWebsocketClients } from '@src/utils/hooks/websocket'
1716

1817
const AppRoutes = () => {
@@ -39,9 +38,11 @@ const AppRoutes = () => {
3938
addNotification,
4039
} = useAppNotificationsContext()
4140

41+
const { connectedUserName, setConnectedUser, hideHeaderButtons, setHideHeaderButtons } =
42+
useAppUIContext()
43+
4244
onMount(() => {
4345
// load the app settings from the persistent store and assign to the global state
44-
4546
get('settings').then((settings) => {
4647
if (settings) {
4748
console.log('loading settings')

GUI/ETVR/src/static/types/interfaces/index.ts

+29
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ENotificationAction,
55
ENotificationType,
66
MdnsStatus,
7+
loaderType,
78
} from '../enums'
89
import type { RESTStatus, RESTType } from '@static/types/enums'
910
import type { WebviewWindow } from '@tauri-apps/api/window'
@@ -107,6 +108,23 @@ export interface MdnsResponse {
107108
names: string[]
108109
}
109110

111+
export interface MenuOpen {
112+
x: number
113+
y: number
114+
}
115+
116+
export interface NewMenu {
117+
children: JSXElement
118+
ref: HTMLElement | null
119+
name: string
120+
}
121+
122+
export interface ModalMenu {
123+
children: JSXElement
124+
title?: string
125+
initialFocus?: string
126+
}
127+
110128
//* App Store Interfaces */
111129

112130
export interface AppStore {
@@ -136,3 +154,14 @@ export interface AppStoreMdns {
136154
mdnsStatus: MdnsStatus
137155
mdnsData: MdnsResponse
138156
}
157+
158+
export interface UiStore {
159+
loader?: { [key in loaderType]: boolean }
160+
connecting?: boolean
161+
openModal?: boolean
162+
menuOpen?: MenuOpen | null
163+
showCameraView?: boolean
164+
connectedUser: string
165+
showNotifications?: boolean
166+
hideHeaderButtons: boolean
167+
}

GUI/ETVR/src/store/context/api/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ export const AppAPIProvider: Component<Context> = (props) => {
441441
* @description Uploads a firmware to a device
442442
* @param firmwareName The name of the firmware file
443443
* @param device The device to upload the firmware to
444-
*
444+
*
445445
*/
446446
const useOTA = async (firmwareName: string, device: string) => {
447447
let endpoints: Map<string, IEndpoint> = new Map()

GUI/ETVR/src/store/context/app/index.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { AppAPIProvider } from '../api'
44
import { AppCameraProvider } from '../camera'
55
import { AppMdnsProvider } from '../mdns'
66
import { AppNotificationProvider } from '../notifications'
7+
import { AppUIProvider } from '../ui'
78
import type { Context } from '@static/types'
89
import type { AppStore } from '@static/types/interfaces'
910

@@ -65,13 +66,15 @@ export const AppProvider: Component<Context> = (props) => {
6566
setScanForCamerasOnStartup,
6667
setStopAlgoBackend,
6768
}}>
68-
<AppNotificationProvider>
69-
<AppCameraProvider>
70-
<AppAPIProvider>
71-
<AppMdnsProvider>{props.children}</AppMdnsProvider>
72-
</AppAPIProvider>
73-
</AppCameraProvider>
74-
</AppNotificationProvider>
69+
<AppUIProvider>
70+
<AppNotificationProvider>
71+
<AppCameraProvider>
72+
<AppAPIProvider>
73+
<AppMdnsProvider>{props.children}</AppMdnsProvider>
74+
</AppAPIProvider>
75+
</AppCameraProvider>
76+
</AppNotificationProvider>
77+
</AppUIProvider>
7578
</AppContext.Provider>
7679
)
7780
}
+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { createContext, useContext, createMemo, type Component, Accessor } from 'solid-js'
2+
import { createStore, produce } from 'solid-js/store'
3+
import type { Context } from '@static/types'
4+
import { UiStore, MenuOpen } from '@src/static/types/interfaces'
5+
import { loaderType } from '@static/types/enums'
6+
7+
interface AppUIContext {
8+
connectingStatus: Accessor<boolean | undefined>
9+
loaderStatus: Accessor<Record<loaderType, boolean> | undefined>
10+
openModalStatus: Accessor<boolean | undefined>
11+
menuOpenStatus: Accessor<MenuOpen | null | undefined>
12+
connectedUserName: Accessor<string>
13+
showCameraView: Accessor<boolean | undefined>
14+
showNotifications: Accessor<boolean | undefined>
15+
hideHeaderButtons: Accessor<boolean>
16+
setMenu: (menuOpen: MenuOpen | null) => void
17+
setHideHeaderButtons: (flag: boolean) => void
18+
setConnecting: (connecting: boolean) => void
19+
setOpenModal: (openModal: boolean) => void
20+
setConnectedUser: (userName: string) => void
21+
setLoader: (type: loaderType, value: boolean) => void
22+
setShowCameraView: (showCameraView: boolean) => void
23+
}
24+
25+
const AppUIContext = createContext<AppUIContext>()
26+
export const AppUIProvider: Component<Context> = (props) => {
27+
const defaultState = {
28+
loader: { [loaderType.MDNS_CONNECTING]: false, [loaderType.REST_CLIENT]: false },
29+
connecting: false,
30+
openModal: false,
31+
menuOpen: null,
32+
connectedUser: '',
33+
showCameraView: false,
34+
showNotifications: true,
35+
hideHeaderButtons: false,
36+
}
37+
38+
const [state, setState] = createStore<UiStore>(defaultState)
39+
40+
const setMenu = (menuOpen: MenuOpen | null) => {
41+
setState(
42+
produce((s) => {
43+
s.menuOpen = menuOpen || null
44+
}),
45+
)
46+
}
47+
48+
const setHideHeaderButtons = (flag: boolean) => {
49+
setState(
50+
produce((s) => {
51+
s.hideHeaderButtons = flag
52+
}),
53+
)
54+
}
55+
56+
const setConnecting = (connecting: boolean) => {
57+
setState(
58+
produce((s) => {
59+
s.connecting = connecting
60+
}),
61+
)
62+
}
63+
64+
const setOpenModal = (openModal: boolean) => {
65+
setState(
66+
produce((s) => {
67+
s.openModal = openModal
68+
}),
69+
)
70+
}
71+
72+
const setConnectedUser = (userName: string) => {
73+
setState(
74+
produce((s) => {
75+
s.connectedUser = userName
76+
}),
77+
)
78+
}
79+
80+
const setLoader = (type: loaderType, value: boolean) => {
81+
setState(
82+
produce((s) => {
83+
if (s.loader) s.loader[type] = value
84+
}),
85+
)
86+
}
87+
88+
const setShowCameraView = (showCameraView: boolean) => {
89+
setState(
90+
produce((s) => {
91+
s.showCameraView = showCameraView
92+
}),
93+
)
94+
}
95+
96+
const uiState = createMemo(() => state)
97+
98+
const connectingStatus = createMemo(() => uiState().connecting)
99+
const loaderStatus = createMemo(() => uiState().loader)
100+
const openModalStatus = createMemo(() => uiState().openModal)
101+
const menuOpenStatus = createMemo(() => uiState().menuOpen)
102+
const connectedUserName = createMemo(() => uiState().connectedUser)
103+
const showCameraView = createMemo(() => uiState().showCameraView)
104+
const showNotifications = createMemo(() => uiState().showNotifications)
105+
const hideHeaderButtons = createMemo(() => uiState().hideHeaderButtons)
106+
107+
return (
108+
<AppUIContext.Provider
109+
value={{
110+
connectingStatus,
111+
loaderStatus,
112+
openModalStatus,
113+
menuOpenStatus,
114+
connectedUserName,
115+
showCameraView,
116+
showNotifications,
117+
hideHeaderButtons,
118+
setMenu,
119+
setHideHeaderButtons,
120+
setConnecting,
121+
setOpenModal,
122+
setConnectedUser,
123+
setLoader,
124+
setShowCameraView,
125+
}}>
126+
{props.children}
127+
</AppUIContext.Provider>
128+
)
129+
}
130+
131+
export const useAppUIContext = () => {
132+
const context = useContext(AppUIContext)
133+
if (context === undefined) {
134+
throw new Error('useAppUIContext must be used within an AppUIProvider')
135+
}
136+
return context
137+
}

GUI/ETVR/src/store/ui/selectors.ts

-11
This file was deleted.

0 commit comments

Comments
 (0)