Skip to content
Source
Sign inSign up

device.ts

40 lines1.8 KB

1import { createDeviceEnvironmentAtoms } from "@t3tools/client-runtime/state/device";
2import { resolveDeviceHubAccess } from "@t3tools/client-runtime/state/deviceHubAccess";
3import type { EnvironmentId } from "@t3tools/contracts";
4import * as Effect from "effect/Effect";
5import * as Option from "effect/Option";
6import { Atom } from "effect/reactivity";
7​
8import { connectionAtomRuntime } from "../connection/runtime";
9import { useEnvironmentQuery } from "./query";
10import { environmentSession, usePreparedConnection } from "./session";
11​
12export const deviceEnvironment = createDeviceEnvironmentAtoms(connectionAtomRuntime);
13​
14// Hub tickets are single use, so each viewer resolves its own access: a new
15// viewer (a reload, a device switch, a return to the screen) never reuses a
16// ticket an earlier connection already spent.
17const deviceHubAccessAtom = Atom.family((environmentId: EnvironmentId) =>
18 Atom.family((_viewer: string) =>
19 connectionAtomRuntime
20 .atom((get) => {
21 const prepared = Option.getOrNull(
22 get(environmentSession.preparedConnectionValueAtom(environmentId)),
23 );
24 return prepared === null
25 ? Effect.never
26 : resolveDeviceHubAccess({ prepared, hubBasePath: "/api/device-hub" });
27 })
28 .pipe(Atom.withLabel(`mobile-device-hub-access:${environmentId}`)),
29 ),
30);
31​
32export function useDeviceHubAccess(environmentId: EnvironmentId, hostId: string, viewer: string) {
33 const prepared = usePreparedConnection(environmentId);
34 const query = useEnvironmentQuery(deviceHubAccessAtom(environmentId)(viewer));
35 const access =
36 query.data && query.error === null && Option.isSome(prepared)
37 ? { ...query.data, query: { ...query.data.query, hostId } }
38 : null;
39 return { access, error: query.error, refresh: query.refresh };