summaryrefslogtreecommitdiff
path: root/public/App.js
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-21 10:14:24 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-21 10:14:24 +0800
commit958e24b0fd08e4bc92656964e832606dbf7d3fa3 (patch)
tree01606b1c010fecc4d3379cbc796c100c32363bac /public/App.js
parent07d6690b9b9de7db7debe25e8e3def5c0d68bb26 (diff)
downloadsomhairles-dream-fsharp-958e24b0fd08e4bc92656964e832606dbf7d3fa3.tar.gz
feat(boot): surface pre-published probe replay on landing page
- boot loads the completed run from /api/artifacts/manifest and renders its latest checkpoint with concrete build-review labels (no fake unknown-state wording); offline fallback still shows the honest placeholder - artifact manifest/steps endpoints now fall back to disk when a completed run has no in-memory registry entry, keeping pre-published history browsable after a service restart (digest-verified, .glb-only / steps/ / logs/ rejected) - driver: heritage flows pin heritage ids explicitly; new checks for the boot probe replay and its labels; 72/72 green with zero console errors
Diffstat (limited to 'public/App.js')
-rw-r--r--public/App.js65
1 files changed, 63 insertions, 2 deletions
diff --git a/public/App.js b/public/App.js
index ab4ae59..a401102 100644
--- a/public/App.js
+++ b/public/App.js
@@ -1,8 +1,8 @@
import { Union, Record } from "./fable_modules/fable-library-js.4.24.0/Types.js";
import { union_type, class_type, record_type, bool_type, string_type } from "./fable_modules/fable-library-js.4.24.0/Reflection.js";
import { Replay_frames } from "./SomhairlesDream.Shared/Replay.js";
-import { defaultOf, equals, createAtom } from "./fable_modules/fable-library-js.4.24.0/Util.js";
-import { equalsWith, tryFind, iterateIndexed, item } from "./fable_modules/fable-library-js.4.24.0/Array.js";
+import { comparePrimitives, defaultOf, equals, createAtom } from "./fable_modules/fable-library-js.4.24.0/Util.js";
+import { sortBy, map, equalsWith, tryFind, iterateIndexed, item } from "./fable_modules/fable-library-js.4.24.0/Array.js";
import { join, isNullOrWhiteSpace, printf, toText } from "./fable_modules/fable-library-js.4.24.0/String.js";
import { MeshData_triangleIndices, MeshData_positionData } from "./SomhairlesDream.Shared/Domain.js";
import { min, max } from "./fable_modules/fable-library-js.4.24.0/Double.js";
@@ -881,6 +881,66 @@ export function startRun(selection) {
})));
}
+/**
+ * Boot-time historical load: surface the pre-published probe build replay so
+ * first-time visitors see the real vehicle instead of an empty placeholder.
+ * Any failure leaves the honest placeholder idle state untouched.
+ */
+export function loadBootHistory() {
+ const selection = selectedRun();
+ const projectId = encodeURIComponent(selection.ProjectId);
+ const runId = encodeURIComponent(selection.RunId);
+ const url = toText(printf("/api/artifacts/manifest?projectId=%s&runId=%s"))(projectId)(runId);
+ const requestOptions = {
+ method: "GET",
+ };
+ startImmediate(singleton.Delay(() => singleton.TryWith(singleton.Delay(() => singleton.Bind(awaitPromise(fetch(url, requestOptions)), (_arg) => {
+ const response = _arg;
+ return response.ok ? singleton.Bind(awaitPromise(response.json()), (_arg_1) => {
+ let arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, arg_8;
+ const payload = _arg_1;
+ if ((payload.status === "complete") && (payload.steps.length > 0)) {
+ const steps = map((step_1) => step_1.artifactPath, sortBy((step) => step.stepIndex, payload.steps, {
+ Compare: comparePrimitives,
+ }));
+ if (steps.length > 0) {
+ currentProjectId(selection.ProjectId);
+ currentRunId(selection.RunId);
+ historicalSteps(steps);
+ setText("project-id", selection.ProjectId);
+ setText("run-id", selection.RunId);
+ setText("target-version", (arg_2 = (steps.length | 0), toText(printf("V%02d"))(arg_2)));
+ setText("current-version", (arg_3 = (steps.length | 0), toText(printf("V%02d"))(arg_3)));
+ setText("version-readout", (arg_4 = (steps.length | 0), (arg_5 = (steps.length | 0), toText(printf("%02d / %02d"))(arg_4)(arg_5))));
+ setWidth("progress-fill", "100%");
+ setText("updated-at", "预发布历史");
+ setText("mesh-label", (arg_6 = item(steps.length - 1, steps), toText(printf("历史 · %s"))(arg_6)));
+ setText("timeline-current", (arg_7 = (steps.length | 0), (arg_8 = item(steps.length - 1, steps), toText(printf("V%02d · 构建重演 · %s"))(arg_7)(arg_8))));
+ setText("replay-button", "播放历史");
+ setText("replay-state", "构建重演 · 预发布历史");
+ renderTimeline();
+ updateFollowButton();
+ if (viewState() == null) {
+ return singleton.Zero();
+ }
+ else {
+ loadStepArtifact(viewState(), item(steps.length - 1, steps), true);
+ return singleton.Zero();
+ }
+ }
+ else {
+ return singleton.Zero();
+ }
+ }
+ else {
+ return singleton.Zero();
+ }
+ }) : singleton.Zero();
+ })), (_arg_2) => {
+ return singleton.Zero();
+ })));
+}
+
export function boot() {
showFrameMetadata(item(0, frames));
try {
@@ -902,6 +962,7 @@ export function boot() {
event.preventDefault();
startRun(selectedRun());
});
+ loadBootHistory();
renderTimeline();
}