docs: close STEP-083 ios RN validation
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Button, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, View, findNodeHandle } from "react-native";
|
||||
import { Camera, Map } from "@maplibre/maplibre-react-native";
|
||||
import { FieldRuntime, type FieldColorStop, type RuntimeSnapshot, type TargetFps } from "@navsea/maplibre-particle-rn";
|
||||
@@ -25,6 +25,9 @@ export default function App() {
|
||||
const [v4Frames, setV4Frames] = useState<Record<"T0" | "T1", string>>({ T0: "PENDING", T1: "PENDING" });
|
||||
const [v4Bindings, setV4Bindings] = useState("PENDING");
|
||||
const [v4Transport, setV4Transport] = useState("PENDING: raw QBIN bundled asset → local file:// URI");
|
||||
const [finalControlRunning, setFinalControlRunning] = useState(false);
|
||||
const [finalControlSummary, setFinalControlSummary] = useState("FINAL CONTROL REGRESSION: not run");
|
||||
const finalControlRunRef = useRef(false);
|
||||
const [weatherVisible, setWeatherVisible] = useState(true);
|
||||
const [particleVisible, setParticleVisible] = useState(true);
|
||||
const [visual, setVisual] = useState(initialVisual);
|
||||
@@ -65,35 +68,92 @@ export default function App() {
|
||||
} catch (error) { setTransport(`ERROR: ${String(error)}`); setResult(`LOAD ${dataset.id}: ${String(error)}`); }
|
||||
}, [reactTag, dataset]);
|
||||
|
||||
const prepareV4 = useCallback(async (tag: number) => {
|
||||
setV4Transport("LOADING: clear → binding → T0 → T1 → midpoint");
|
||||
setV4Frames({ T0: "PENDING", T1: "PENDING" });
|
||||
setV4Bindings("PENDING");
|
||||
const clear = await FieldRuntime.clearAllEncodedFields(tag);
|
||||
if (clear !== "ACCEPTED") throw new Error(`clearAllEncodedFields expected ACCEPTED, got ${clear}`);
|
||||
const color = await FieldRuntime.setEncodedColorBinding(tag, v4Dataset.colorBinding);
|
||||
if (color !== "ACCEPTED") throw new Error(`ColorBinding expected ACCEPTED, got ${color}`);
|
||||
const particle = v4Dataset.particleBinding == null ? "N/A" : await FieldRuntime.setEncodedParticleBinding(tag, v4Dataset.particleBinding);
|
||||
if (particle !== "N/A" && particle !== "ACCEPTED") throw new Error(`ParticleBinding expected ACCEPTED, got ${particle}`);
|
||||
setV4Bindings(`clearAll=${clear}; color=${color}; particle=${particle}`);
|
||||
const localFrames = await Promise.all(v4Dataset.frames.map(materializeV4Frame));
|
||||
const submitted: string[] = [];
|
||||
for (const frame of localFrames) {
|
||||
const submit = await FieldRuntime.submitEncodedField(tag, v4Dataset.fieldKey, frame.metadata, v4Dataset.profileContract, frame.qbinFileUri);
|
||||
submitted.push(`${frame.label}=${submit}`);
|
||||
setV4Frames((current) => ({ ...current, [frame.label]: submit }));
|
||||
if (submit !== "ACCEPTED_INSERTED") throw new Error(`${frame.label} expected ACCEPTED_INSERTED, got ${submit}`);
|
||||
}
|
||||
const midpoint = await FieldRuntime.setEncodedForecastTime(tag, v4Dataset.midpointMs);
|
||||
if (midpoint !== "ACCEPTED") throw new Error(`midpoint seek expected ACCEPTED, got ${midpoint}`);
|
||||
await refresh(tag);
|
||||
setV4Transport("READY: T0/T1 ACCEPTED_INSERTED; midpoint command ACCEPTED (mix=0.5 is not exposed)");
|
||||
return `clearAll=${clear}; color=${color}; particle=${particle}; ${submitted.join(", ")}; midpoint=${midpoint}`;
|
||||
}, [refresh, v4Dataset]);
|
||||
|
||||
const loadV4Dataset = useCallback(async () => {
|
||||
if (reactTag == null) return setResult("MAP_NOT_READY: wait for GSI/style ready");
|
||||
try {
|
||||
setV4Transport("LOADING: clear → binding → T0 → T1 → midpoint");
|
||||
setV4Frames({ T0: "PENDING", T1: "PENDING" });
|
||||
setV4Bindings("PENDING");
|
||||
const clear = await FieldRuntime.clearAllEncodedFields(reactTag);
|
||||
if (clear !== "ACCEPTED") throw new Error(`clearAllEncodedFields expected ACCEPTED, got ${clear}`);
|
||||
const color = await FieldRuntime.setEncodedColorBinding(reactTag, v4Dataset.colorBinding);
|
||||
if (color !== "ACCEPTED") throw new Error(`ColorBinding expected ACCEPTED, got ${color}`);
|
||||
const particle = v4Dataset.particleBinding == null ? "N/A" : await FieldRuntime.setEncodedParticleBinding(reactTag, v4Dataset.particleBinding);
|
||||
if (particle !== "N/A" && particle !== "ACCEPTED") throw new Error(`ParticleBinding expected ACCEPTED, got ${particle}`);
|
||||
setV4Bindings(`clearAll=${clear}; color=${color}; particle=${particle}`);
|
||||
const localFrames = await Promise.all(v4Dataset.frames.map(materializeV4Frame));
|
||||
for (const frame of localFrames) {
|
||||
const submit = await FieldRuntime.submitEncodedField(reactTag, v4Dataset.fieldKey, frame.metadata, v4Dataset.profileContract, frame.qbinFileUri);
|
||||
setV4Frames((current) => ({ ...current, [frame.label]: submit }));
|
||||
if (submit !== "ACCEPTED_INSERTED") throw new Error(`${frame.label} expected ACCEPTED_INSERTED, got ${submit}`);
|
||||
}
|
||||
const midpoint = await FieldRuntime.setEncodedForecastTime(reactTag, v4Dataset.midpointMs);
|
||||
if (midpoint !== "ACCEPTED") throw new Error(`midpoint seek expected ACCEPTED, got ${midpoint}`);
|
||||
await refresh(reactTag);
|
||||
setV4Transport("READY: T0/T1 ACCEPTED_INSERTED; midpoint command ACCEPTED (mix=0.5 is not exposed)");
|
||||
await prepareV4(reactTag);
|
||||
setResult(`${v4Dataset.title}: V4 raw QBIN load accepted`);
|
||||
} catch (error) {
|
||||
setV4Transport(`ERROR: ${String(error)}`);
|
||||
setResult(`LOAD V4 ${v4Dataset.id}: ${String(error)}`);
|
||||
}
|
||||
}, [reactTag, refresh, v4Dataset]);
|
||||
}, [prepareV4, reactTag, v4Dataset]);
|
||||
|
||||
const runV4FinalControlRegression = useCallback(async () => {
|
||||
if (reactTag == null || !Number.isInteger(reactTag) || reactTag <= 0) return setResult("MAP_NOT_READY: wait for a valid reactTag/style ready");
|
||||
if (finalControlRunRef.current) return;
|
||||
const steps: string[] = [];
|
||||
const accepted = (step: string, value: string) => {
|
||||
if (value !== "ACCEPTED") throw new Error(`${step} expected ACCEPTED, got ${value}`);
|
||||
steps.push(`${step}=${value}`);
|
||||
};
|
||||
const prepare = async (attempt: number) => {
|
||||
try { steps.push(`prepare#${attempt} PASS (${await prepareV4(reactTag)})`); }
|
||||
catch (error) { throw new Error(`prepare#${attempt}: ${String(error)}`); }
|
||||
};
|
||||
finalControlRunRef.current = true;
|
||||
setFinalControlRunning(true);
|
||||
setFinalControlSummary("FINAL CONTROL REGRESSION: RUNNING");
|
||||
try {
|
||||
await prepare(1);
|
||||
accepted("PLAY", await FieldRuntime.setEncodedForecastPlaybackState(reactTag, "PLAY"));
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 500));
|
||||
steps.push("PLAY wait≈500ms=PASS");
|
||||
accepted("PAUSE", await FieldRuntime.setEncodedForecastPlaybackState(reactTag, "PAUSE"));
|
||||
accepted("clear selected", await FieldRuntime.clearEncodedField(reactTag, v4Dataset.fieldKey));
|
||||
await prepare(2);
|
||||
accepted("clear all", await FieldRuntime.clearAllEncodedFields(reactTag));
|
||||
try { await FieldRuntime.detach(reactTag); }
|
||||
catch (error) { throw new Error(`detach: ${String(error)}`); }
|
||||
steps.push("detach=PASS");
|
||||
let attached: RuntimeSnapshot;
|
||||
try { attached = await FieldRuntime.attach(reactTag); }
|
||||
catch (error) { throw new Error(`attach: ${String(error)}`); }
|
||||
setSnapshot(attached);
|
||||
steps.push("attach=PASS");
|
||||
await prepare(3);
|
||||
try { await refresh(reactTag); }
|
||||
catch (error) { throw new Error(`refresh: ${String(error)}`); }
|
||||
steps.push("refresh=PASS");
|
||||
const summary = steps.join(" | ");
|
||||
setFinalControlSummary(`FINAL CONTROL REGRESSION PASS: ${summary}`);
|
||||
setResult("FINAL CONTROL REGRESSION PASS");
|
||||
} catch (error) {
|
||||
const failure = `FAIL: ${String(error)}`;
|
||||
steps.push(failure);
|
||||
setFinalControlSummary(`FINAL CONTROL REGRESSION ${steps.join(" | ")}`);
|
||||
setResult(`FINAL CONTROL REGRESSION ${failure}`);
|
||||
} finally {
|
||||
finalControlRunRef.current = false;
|
||||
setFinalControlRunning(false);
|
||||
}
|
||||
}, [prepareV4, reactTag, refresh, v4Dataset.fieldKey]);
|
||||
|
||||
const updateVisual = useCallback((key: keyof typeof initialVisual, value: string) => setVisual((current) => ({ ...current, [key]: value })), []);
|
||||
const applyVisual = useCallback(() => void command("particle visual", async (tag) => {
|
||||
@@ -121,6 +181,8 @@ export default function App() {
|
||||
<Text>V4 QBIN Golden: {v4Dataset.title}</Text><Text selectable>V4 raw QBIN transport = {v4Transport}</Text><Text selectable>V4 bindings: {v4Bindings}</Text><Text selectable>{v4Dataset.particleNote}</Text>
|
||||
<Text selectable>V4 T0: {v4Frames.T0}</Text><Text selectable>V4 T1: {v4Frames.T1}</Text>
|
||||
<View style={styles.row}>{qbinGoldenDatasets.map((item) => <Button key={item.id} title={`V4 ${item.id}`} onPress={() => setV4Dataset(item)} />)}</View><Button title="LOAD SELECTED V4 DATASET" onPress={() => void loadV4Dataset()} />
|
||||
<Button title={finalControlRunning ? "RUN V4 FINAL CONTROL REGRESSION (RUNNING)" : "RUN V4 FINAL CONTROL REGRESSION"} disabled={finalControlRunning} onPress={() => void runV4FinalControlRegression()} />
|
||||
<Text selectable>{finalControlSummary}</Text>
|
||||
<View style={styles.row}><Button title="V4 seek T0" onPress={() => void command("V4 seek T0", (tag) => FieldRuntime.setEncodedForecastTime(tag, v4Dataset.frames[0].validTimeMs))} /><Button title="V4 seek midpoint" onPress={() => void command("V4 seek midpoint (mix not exposed)", (tag) => FieldRuntime.setEncodedForecastTime(tag, v4Dataset.midpointMs))} /><Button title="V4 seek T1" onPress={() => void command("V4 seek T1", (tag) => FieldRuntime.setEncodedForecastTime(tag, v4Dataset.frames[1].validTimeMs))} /></View>
|
||||
<View style={styles.row}><Button title="V4 PLAY" onPress={() => void command("V4 PLAY", (tag) => FieldRuntime.setEncodedForecastPlaybackState(tag, "PLAY"))} /><Button title="V4 PAUSE" onPress={() => void command("V4 PAUSE", (tag) => FieldRuntime.setEncodedForecastPlaybackState(tag, "PAUSE"))} /><Button title="V4 speed 1.0" onPress={() => void command("V4 speed 1.0", (tag) => FieldRuntime.setEncodedForecastPlaybackSpeed(tag, 1.0))} /><Button title="V4 clear selected" onPress={() => void command("V4 clear selected", (tag) => FieldRuntime.clearEncodedField(tag, v4Dataset.fieldKey))} /><Button title="V4 clear all" onPress={() => void command("V4 clear all", (tag) => FieldRuntime.clearAllEncodedFields(tag))} /></View>
|
||||
</ScrollView>
|
||||
|
||||
Reference in New Issue
Block a user