Skip to content

Commit b73a85d

Browse files
authored
cleanup(snapshot): move method to athena, use store (commaai#535)
1 parent 44b7c7d commit b73a85d

File tree

2 files changed

+32
-56
lines changed

2 files changed

+32
-56
lines changed

src/api/athena.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ export const getNetworkMetered = (dongleId: string) => makeAthenaCall<void, bool
77
export const setRouteViewed = (dongleId: string, route: string) =>
88
makeAthenaCall<{ route: string }, void>(dongleId, 'setRouteViewed', { route })
99

10+
export const takeSnapshot = (dongleId: string) =>
11+
makeAthenaCall<
12+
void,
13+
{
14+
jpegFront?: string
15+
jpegBack?: string
16+
}
17+
>(dongleId, 'takeSnapshot')
18+
1019
export const makeAthenaCall = async <REQ, RES>(
1120
dongleId: string,
1221
method: string,

src/pages/dashboard/activities/DeviceActivity.tsx

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,24 @@
1+
import { createResource, createSignal, For, Show, Suspense, type VoidComponent } from 'solid-js'
2+
import { createStore } from 'solid-js/store'
13
import clsx from 'clsx'
2-
import { createResource, createSignal, For, Show, Suspense } from 'solid-js'
3-
import type { VoidComponent } from 'solid-js'
44

5+
import { takeSnapshot } from '~/api/athena'
56
import { getDevice, SHARED_DEVICE } from '~/api/devices'
6-
import { ATHENA_URL } from '~/api/config'
7-
import { getAccessToken } from '~/api/auth/client'
8-
97
import { DrawerToggleButton, useDrawerContext } from '~/components/material/Drawer'
108
import Icon from '~/components/material/Icon'
119
import IconButton from '~/components/material/IconButton'
1210
import TopAppBar from '~/components/material/TopAppBar'
1311
import DeviceLocation from '~/components/DeviceLocation'
1412
import DeviceStatistics from '~/components/DeviceStatistics'
13+
import UploadQueue from '~/components/UploadQueue'
1514
import { deviceIsOnline, getDeviceName } from '~/utils/device'
1615

1716
import RouteList from '../components/RouteList'
18-
import UploadQueue from '~/components/UploadQueue'
1917

2018
type DeviceActivityProps = {
2119
dongleId: string
2220
}
2321

24-
interface SnapshotResponse {
25-
result?: {
26-
jpegFront?: string
27-
jpegBack?: string
28-
}
29-
}
30-
3122
const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
3223
// TODO: device should be passed in from DeviceList
3324
const [device] = createResource(() => props.dongleId, getDevice)
@@ -36,7 +27,7 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
3627
// TODO: remove this. if we're listing the routes for a device you should always be a user, this is for viewing public routes which are being removed
3728
const isDeviceUser = () => (device.loading ? true : device.latest?.is_owner || device.latest?.alias !== SHARED_DEVICE)
3829
const [queueVisible, setQueueVisible] = createSignal(false)
39-
const [snapshot, setSnapshot] = createSignal<{
30+
const [snapshot, setSnapshot] = createStore<{
4031
error: string | null
4132
fetching: boolean
4233
images: string[]
@@ -46,37 +37,13 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
4637
images: [],
4738
})
4839

49-
const takeSnapshot = async () => {
50-
setSnapshot({ error: null, fetching: true, images: [] })
51-
40+
const onClickSnapshot = async () => {
41+
setSnapshot({ error: null, fetching: true })
5242
try {
53-
const payload = {
54-
method: 'takeSnapshot',
55-
jsonrpc: '2.0',
56-
id: 0,
57-
}
58-
59-
const response = await fetch(`${ATHENA_URL}/${props.dongleId}`, {
60-
method: 'POST',
61-
headers: {
62-
'Content-Type': 'application/json',
63-
Authorization: `JWT ${getAccessToken()}`,
64-
},
65-
body: JSON.stringify(payload),
66-
})
67-
68-
if (!response.ok) {
69-
throw new Error(`HTTP error! status: ${response.status}`)
70-
}
71-
72-
const resp: SnapshotResponse = (await response.json()) as SnapshotResponse
73-
const images = []
74-
75-
if (resp.result?.jpegFront) images.push(resp.result.jpegFront)
76-
if (resp.result?.jpegBack) images.push(resp.result.jpegBack)
77-
43+
const resp = await takeSnapshot(props.dongleId)
44+
const images = [resp.result?.jpegFront, resp.result?.jpegBack].filter((it) => it !== undefined)
7845
if (images.length > 0) {
79-
setSnapshot({ error: null, fetching: false, images })
46+
setSnapshot('images', images)
8047
} else {
8148
throw new Error('No images found.')
8249
}
@@ -85,7 +52,9 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
8552
if (error.includes('Device not registered')) {
8653
error = 'Device offline'
8754
}
88-
setSnapshot({ error, fetching: false, images: [] })
55+
setSnapshot('error', error)
56+
} finally {
57+
setSnapshot('fetching', false)
8958
}
9059
}
9160

@@ -99,13 +68,11 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
9968
}
10069

10170
const clearImage = (index: number) => {
102-
const newImages = snapshot().images.filter((_, i) => i !== index)
103-
setSnapshot({ ...snapshot(), images: newImages })
71+
const newImages = snapshot.images.filter((_, i) => i !== index)
72+
setSnapshot('images', newImages)
10473
}
10574

106-
const clearError = () => {
107-
setSnapshot({ ...snapshot(), error: null })
108-
}
75+
const clearError = () => setSnapshot('error', null)
10976

11077
const { modal } = useDrawerContext()
11178

@@ -140,7 +107,7 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
140107
</div>
141108
</Suspense>
142109
<div class="flex gap-4">
143-
<IconButton name="camera" onClick={() => void takeSnapshot()} />
110+
<IconButton name="camera" onClick={onClickSnapshot} />
144111
<IconButton name="settings" href={`/${props.dongleId}/settings`} />
145112
</div>
146113
</div>
@@ -162,7 +129,7 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
162129
</Show>
163130
</div>
164131
<div class="flex flex-col gap-2">
165-
<For each={snapshot().images}>
132+
<For each={snapshot.images}>
166133
{(image, index) => (
167134
<div class="flex-1 overflow-hidden rounded-lg bg-surface-container-low">
168135
<div class="relative p-4">
@@ -175,21 +142,21 @@ const DeviceActivity: VoidComponent<DeviceActivityProps> = (props) => {
175142
</div>
176143
)}
177144
</For>
178-
{snapshot().fetching && (
145+
<Show when={snapshot.fetching}>
179146
<div class="flex-1 overflow-hidden rounded-lg bg-surface-container-low">
180147
<div class="p-4">
181148
<div>Loading snapshots...</div>
182149
</div>
183150
</div>
184-
)}
185-
{snapshot().error && (
151+
</Show>
152+
<Show when={snapshot.error}>
186153
<div class="flex-1 overflow-hidden rounded-lg bg-surface-container-low">
187154
<div class="flex items-center p-4">
188155
<IconButton class="text-white" name="clear" onClick={clearError} />
189-
<span>Error: {snapshot().error}</span>
156+
<span>Error: {snapshot.error}</span>
190157
</div>
191158
</div>
192-
)}
159+
</Show>
193160
</div>
194161
<RouteList dongleId={props.dongleId} />
195162
</div>

0 commit comments

Comments
 (0)