58 lines · 1.9 KB · TypeScript
RawDownload
import * as Data from "effect/Data";import * as Effect from "effect/Effect";import * as Schema from "effect/Schema";import { Atom } from "effect/unstable/reactivity"; const WORKSPACE_IMAGE_IDLE_TTL_MS = 30 * 60_000; type ImagePrefetch = (uri: string) => Promise<boolean>; class WorkspaceImageCacheKey extends Data.Class<{ readonly uri: string }> {} export class WorkspaceImagePrefetchError extends Schema.TaggedErrorClass<WorkspaceImagePrefetchError>()(  "WorkspaceImagePrefetchError",  {    uri: Schema.String,    cause: Schema.optional(Schema.Defect()),  },) {  override get message(): string {    return `Failed to prefetch workspace image ${this.uri}.`;  }} export const isWorkspaceImagePrefetchError = Schema.is(WorkspaceImagePrefetchError); async function prefetchWithNativeImage(uri: string): Promise<boolean> {  const { Image } = await import("react-native");  return Image.prefetch(uri);} export function createWorkspaceFileImageAtomFamily(options?: {  readonly idleTtlMs?: number;  readonly prefetch?: ImagePrefetch;}) {  const idleTtlMs = options?.idleTtlMs ?? WORKSPACE_IMAGE_IDLE_TTL_MS;  const prefetch = options?.prefetch ?? prefetchWithNativeImage;  const family = Atom.family((key: WorkspaceImageCacheKey) =>    Atom.make(      Effect.tryPromise({        try: async () => {          const cached = await prefetch(key.uri);          if (!cached) {            throw new WorkspaceImagePrefetchError({ uri: key.uri });          }          return key.uri;        },        catch: (cause) =>          isWorkspaceImagePrefetchError(cause)            ? cause            : new WorkspaceImagePrefetchError({ uri: key.uri, cause }),      }),    ).pipe(Atom.setIdleTTL(idleTtlMs), Atom.withLabel(`mobile:workspace-image:${key.uri}`)),  );   return (uri: string) => family(new WorkspaceImageCacheKey({ uri }));} export const workspaceFileImageAtom = createWorkspaceFileImageAtomFamily();