diff options
| author | Somhairle H. Marisol <[email protected]> | 2026-09-21 06:05:15 +0800 |
|---|---|---|
| committer | Somhairle H. Marisol <[email protected]> | 2026-09-21 06:05:15 +0800 |
| commit | 13479cd194cd992c67805093e59f8b1dd1b5f3a2 (patch) | |
| tree | 2918d1d408a65e694c49c081ce288566b8bcf5d5 /src/SomhairlesDream.Frontend | |
| parent | 822c092790bad4b1c0d780c1fafee063d70c91f6 (diff) | |
| download | somhairles-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 'src/SomhairlesDream.Frontend')
| -rw-r--r-- | src/SomhairlesDream.Frontend/App.fs | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/SomhairlesDream.Frontend/App.fs b/src/SomhairlesDream.Frontend/App.fs index 6e07798..549b695 100644 --- a/src/SomhairlesDream.Frontend/App.fs +++ b/src/SomhairlesDream.Frontend/App.fs @@ -60,6 +60,7 @@ let mutable loadGeneration = 0 let mutable pendingLoad: (int * LoadOwner) option = None let mutable loadedStep: LoadOwner option = None let mutable viewMode = FrameMode +let mutable failedLoad: LoadOwner option = None let mutable displayedNode: ThreeNode option = None let mutable freezeRotation = false @@ -132,6 +133,7 @@ let clearGroup (group: ThreeNode) = let invalidateLoads () = loadGeneration <- loadGeneration + 1 pendingLoad <- None + failedLoad <- None let renderFrame (frame: ReplayFrame) = selectedFrame <- frame @@ -242,6 +244,14 @@ let fallbackView () = setText "viewport-note" "WebGL 视图待命 · 已保留重建数据" (element "viewport-panel").classList.add("viewport-fallback") +let setNoteRetryable (retryable: bool) = + let note = element "viewport-note" + + if retryable then + note.classList.add("is-retryable") + else + note.classList.remove("is-retryable") + let showFrameMetadata (frame: ReplayFrame) = setText "mesh-label" frame.Label setText "timeline-current" (sprintf "V%02d · %s" frame.Version frame.Label) @@ -262,6 +272,8 @@ let startStepLoad (view: ViewState) (owner: LoadOwner) = loadGeneration <- generation pendingLoad <- Some(generation, owner) viewMode <- StepMode + failedLoad <- None + setNoteRetryable false let loader = createGLTFLoader () let projectId = JS.encodeURIComponent owner.ProjectId let runId = JS.encodeURIComponent owner.RunId @@ -285,6 +297,8 @@ let startStepLoad (view: ViewState) (owner: LoadOwner) = if pendingLoad = Some(generation, owner) then pendingLoad <- None loadedStep <- None + failedLoad <- Some owner + setNoteRetryable true setText "viewport-note" (sprintf "管线几何加载失败 · %s" owner.Path)) let loadStepArtifact (view: ViewState) (stepPath: string) = @@ -297,6 +311,12 @@ let loadStepArtifact (view: ViewState) (stepPath: string) = | Some (_, pending) when pending = owner -> () | _ -> startStepLoad view owner +let retryFailedLoad () = + match viewState, failedLoad with + | Some view, Some owner when owner.ProjectId = currentProjectId && owner.RunId = currentRunId -> + loadStepArtifact view owner.Path + | _ -> () + let updateState (payload: SnapshotPayload) = let status = statusName payload setStatusClass status @@ -474,6 +494,7 @@ let boot () = fallbackView () (element "replay-button").addEventListener("click", fun _ -> toggleReplay ()) + (element "viewport-note").addEventListener("click", fun _ -> retryFailedLoad ()) (element "run-controls").addEventListener("submit", fun event -> event.preventDefault() startRun (selectedRun ())) |
