Files
model-platform/frontend/app/features/platform/state/previewSlice.ts
T

90 lines
2.5 KiB
TypeScript

// ---- previewSlice ----
//
// 拥有 previewKey / previewCode / previewCodeSize / previewLoading / previewError。
// Action: loadPreview (用 AbortController 取消旧请求 + request-id 序列号忽略过期响应)。
import type { StateCreator } from "zustand";
import {
bumpPreviewRequest,
getPreviewController,
getPreviewRequest,
setPreviewController,
} from "./helpers";
import type {
PreviewSliceActions,
PreviewSliceState,
} from "./types";
import type { ScriptWorkspaceStore } from "./useScriptWorkspaceStore";
export const createPreviewSlice: StateCreator<
ScriptWorkspaceStore,
[],
[],
PreviewSliceState & PreviewSliceActions
> = (set) => {
const initial: PreviewSliceState = {
previewKey: null,
previewCode: null,
previewCodeSize: null,
previewLoading: false,
previewError: null,
};
return {
...initial,
loadPreview: async (workspaceId, filePath) => {
const existing = getPreviewController();
if (existing) {
existing.abort();
}
const requestId = bumpPreviewRequest();
const previewKey = `${workspaceId}::${filePath}`;
set({ previewKey, previewLoading: true, previewError: null });
const controller = new AbortController();
setPreviewController(controller);
try {
const url =
`/jupyter/${workspaceId}/api/contents/${filePath}` +
`?type=file&content=1&hash=1&format=text`;
const response = await fetch(url, {
signal: controller.signal,
credentials: "include",
cache: "no-store",
});
if (!response.ok) {
throw new Error(`Failed to load file: ${response.status}`);
}
const data = await response.json();
if (getPreviewRequest() !== requestId) return;
set({
previewKey,
previewCode: data.content ?? "",
previewCodeSize: data.size ?? 0,
previewLoading: false,
previewError: null,
});
} catch (error) {
if (getPreviewRequest() !== requestId) return;
if (error instanceof Error && error.name === "AbortError") return;
set({
previewKey,
previewCode: null,
previewCodeSize: null,
previewLoading: false,
previewError:
error instanceof Error ? error.message : "加载预览失败",
});
} finally {
if (getPreviewRequest() === requestId) {
setPreviewController(null);
}
}
},
};
};