summaryrefslogtreecommitdiff
path: root/public/App.js
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 06:05:15 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 06:05:15 +0800
commit13479cd194cd992c67805093e59f8b1dd1b5f3a2 (patch)
tree2918d1d408a65e694c49c081ce288566b8bcf5d5 /public/App.js
parent822c092790bad4b1c0d780c1fafee063d70c91f6 (diff)
downloadsomhairles-dream-fsharp-13479cd194cd992c67805093e59f8b1dd1b5f3a2.tar.gz
feat(viewer): add user retry for failed step loads and regressions for same-run ordering and replay invalidation
Diffstat (limited to 'public/App.js')
-rw-r--r--public/App.js54
1 files changed, 54 insertions, 0 deletions
diff --git a/public/App.js b/public/App.js
index 4b842d1..70d2377 100644
--- a/public/App.js
+++ b/public/App.js
@@ -92,6 +92,8 @@ export let loadedStep = createAtom(undefined);
export let viewMode = createAtom(new ViewMode(0, []));
+export let failedLoad = createAtom(undefined);
+
export let displayedNode = createAtom(undefined);
export let freezeRotation = createAtom(false);
@@ -218,6 +220,7 @@ export function clearGroup(group) {
export function invalidateLoads() {
loadGeneration(loadGeneration() + 1);
pendingLoad(undefined);
+ failedLoad(undefined);
}
export function renderFrame(frame) {
@@ -320,6 +323,16 @@ export function fallbackView() {
element("viewport-panel").classList.add("viewport-fallback");
}
+export function setNoteRetryable(retryable) {
+ const note = element("viewport-note");
+ if (retryable) {
+ note.classList.add("is-retryable");
+ }
+ else {
+ note.classList.remove("is-retryable");
+ }
+}
+
export function showFrameMetadata(frame) {
setText("mesh-label", frame.Label);
setText("timeline-current", toText(printf("V%02d · %s"))(frame.Version)(frame.Label));
@@ -343,6 +356,8 @@ export function startStepLoad(view, owner) {
loadGeneration(generation);
pendingLoad([generation, owner]);
viewMode(new ViewMode(1, []));
+ failedLoad(undefined);
+ setNoteRetryable(false);
const loader = new GLTFLoader();
const projectId = encodeURIComponent(owner.ProjectId);
const runId = encodeURIComponent(owner.RunId);
@@ -368,6 +383,8 @@ export function startStepLoad(view, owner) {
if (equals(pendingLoad(), [generation, owner])) {
pendingLoad(undefined);
loadedStep(undefined);
+ failedLoad(owner);
+ setNoteRetryable(true);
setText("viewport-note", toText(printf("管线几何加载失败 · %s"))(owner.Path));
}
}));
@@ -399,6 +416,40 @@ export function loadStepArtifact(view, stepPath) {
}
}
+export function retryFailedLoad() {
+ let view, owner;
+ const matchValue = viewState();
+ const matchValue_1 = failedLoad();
+ let matchResult, owner_1, view_1;
+ if (matchValue != null) {
+ if (matchValue_1 != null) {
+ if ((view = matchValue, (owner = matchValue_1, (owner.ProjectId === currentProjectId()) && (owner.RunId === currentRunId())))) {
+ matchResult = 0;
+ owner_1 = matchValue_1;
+ view_1 = matchValue;
+ }
+ else {
+ matchResult = 1;
+ }
+ }
+ else {
+ matchResult = 1;
+ }
+ }
+ else {
+ matchResult = 1;
+ }
+ switch (matchResult) {
+ case 0: {
+ loadStepArtifact(view_1, owner_1.Path);
+ break;
+ }
+ case 1: {
+ break;
+ }
+ }
+}
+
export function updateState(payload) {
let arg, arg_3;
setStatusClass(statusName(payload));
@@ -573,6 +624,9 @@ export function boot() {
element("replay-button").addEventListener("click", (_arg) => {
toggleReplay();
});
+ element("viewport-note").addEventListener("click", (_arg_1) => {
+ retryFailedLoad();
+ });
element("run-controls").addEventListener("submit", (event) => {
event.preventDefault();
startRun(selectedRun());