1import type { AtomCommandResult } from "@t3tools/client-runtime/state/runtime";
2import type {
3 EnvironmentId,
4 PreviewCloseInput,
5 PreviewSessionSnapshot,
6 ScopedThreadRef,
7} from "@t3tools/contracts";
8
9import { useClosedViewStore } from "~/closedViewStore";
10import { beginPreviewSessionClose, cancelPreviewSessionClose } from "~/previewStateStore";
11
12interface ClosePreviewSessionInput<E> {
13 readonly closePreview: (input: {
14 readonly environmentId: EnvironmentId;
15 readonly input: PreviewCloseInput;
16 }) => Promise<AtomCommandResult<void, E>>;
17 readonly snapshot: PreviewSessionSnapshot | null;
18 readonly tabId: string;
19 readonly threadRef: ScopedThreadRef;
20}
21
22/**
23 * Optimistically closes a preview while suppressing stale list responses for
24 * the same tab. A failed close restores the last known snapshot.
25 */
26export async function closePreviewSession<E>(
27 input: ClosePreviewSessionInput<E>,
28): Promise<AtomCommandResult<void, E>> {
29 beginPreviewSessionClose(input.threadRef, input.tabId);
30 const result = await input.closePreview({
31 environmentId: input.threadRef.environmentId,
32 input: { threadId: input.threadRef.threadId, tabId: input.tabId },
33 });
34 if (result._tag === "Failure") {
35 cancelPreviewSessionClose(input.threadRef, input.snapshot, input.tabId);
36 } else if (input.snapshot) {
37 useClosedViewStore.getState().remember({
38 kind: "browser",
39 threadRef: input.threadRef,
40 snapshot: input.snapshot,
41 });
42 }
43 return result;
44}