Skip to content
Source
Sign inSign up

permissionStatusAtom.ts

32 lines1.1 KB

1import { Atom } from "effect/reactivity";
2​
3import { subscribeAppActive } from "./appState";
4​
5/**
6 * A system permission or device capability as the app last saw it. Reads it
7 * when first mounted and again each time the app returns to the foreground,
8 * where the user may have changed it in system Settings. Writing stores the outcome of a request.
9 */
10export function makePermissionStatusAtom<S>(options: {
11 readonly label: string;
12 readonly initial: S;
13 readonly read: () => Promise<S>;
14}): Atom.Writable<S, S> {
15 return Atom.writable(
16 (get) => {
17 // A read that settles after unmount is dropped: setSelf on a disposed lifetime is a no-op.
18 // Only the latest read lands, so a slow earlier read cannot overwrite a newer status.
19 let latest = 0;
20 const refresh = () => {
21 const read = ++latest;
22 void options.read().then((status) => {
23 if (read === latest) get.setSelf(status);
24 });
25 };
26 refresh();
27 get.addFinalizer(subscribeAppActive(refresh));
28 return options.initial;
29 },
30 (ctx, status: S) => ctx.setSelf(status),
31 ).pipe(Atom.withLabel(options.label));