diff --git a/integration/react-native/MapLibreParticlePackageConsumerTestHost/App.tsx b/integration/react-native/MapLibreParticlePackageConsumerTestHost/App.tsx index 99984e733..a126a7ce0 100644 --- a/integration/react-native/MapLibreParticlePackageConsumerTestHost/App.tsx +++ b/integration/react-native/MapLibreParticlePackageConsumerTestHost/App.tsx @@ -1,26 +1,87 @@ -import { useCallback, useState } from "react"; -import { Button, SafeAreaView, StyleSheet, Text, View, findNodeHandle } from "react-native"; -import { File, Paths } from "expo-file-system"; -import { Camera, Map, WeatherRuntime, createParticleWeatherStyle } from "@navsea/maplibre-particle-rn"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { Button, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, View, findNodeHandle } from "react-native"; +import { Camera, Map, WeatherRuntime, type ColorStop, type RuntimeSnapshot, type TargetFps } from "@navsea/maplibre-particle-rn"; +import { materializeRealWeatherFrames, realWeatherFrames } from "./src/realWeatherDataset"; +import { weatherTestStyle } from "./src/weatherStyle"; -const metadata = (generation: number, validTime: number) => JSON.stringify({ schema: "maplibre-particle-field/v1", fieldId: `consumer-smoke-${generation}`, fieldType: "WIND", displayDomain: "GLOBAL", generation, validTime, dataVersion: generation, bounds: { west: -180, south: -85, east: 180, north: 85 }, grid: { width: 2, height: 2 }, vector: { layout: "interleaved-uv", encoding: "float32-le", noData: -9999 }, payload: { byteLength: 32 } }); - -function writeFixture() { - const bytes = new Uint8Array(32); const view = new DataView(bytes.buffer); - for (let offset = 0; offset < bytes.byteLength; offset += 8) { view.setFloat32(offset, 5, true); view.setFloat32(offset + 4, 1, true); } - const file = new File(Paths.cache, "navsea-particle-consumer-smoke.f32"); file.write(bytes); return file.uri; -} +const initialSnapshot: RuntimeSnapshot = { state: "WAITING_FOR_FIELDS", playbackState: "PAUSE", targetFps: "AUTO", disposed: false }; +const initialVisual = { count: "4096", width: "1.5", length: "0.012", opacity: "0.9", trailOpacity: "0.8", trailFade: "0.94", weatherOpacity: "0.62" }; +const frozenStops: ColorStop[] = [ + { speedMps: 0, red: 0.08, green: 0.2, blue: 0.8, alpha: 0.72 }, { speedMps: 8, red: 0, green: 0.85, blue: 0.9, alpha: 0.72 }, + { speedMps: 16, red: 1, green: 0.85, blue: 0.05, alpha: 0.72 }, { speedMps: 30, red: 0.9, green: 0.08, blue: 0.08, alpha: 0.72 }, +]; export default function App() { - const [tag, setTag] = useState(null); const [state, setState] = useState("STYLE_LOADING"); - const onStyle = useCallback(async (event: unknown) => { - const value = findNodeHandle((event as { target?: unknown }).target as never); if (value == null) return; - try { await WeatherRuntime.attach(value); setTag(value); setState("WAITING_FOR_FIELDS"); } catch (error) { setState(String(error)); } - }, []); - const submit = useCallback(async () => { - if (tag == null) return; - try { await WeatherRuntime.clearWindFields(tag); const payload = writeFixture(); const t0 = await WeatherRuntime.submitWindField(tag, metadata(1, 1786060800000), payload); const t1 = await WeatherRuntime.submitWindField(tag, metadata(2, 1786082400000), payload); const runtime = await WeatherRuntime.getState(tag); setState(`T0 ${t0} / T1 ${t1} / ${runtime.state}`); } catch (error) { setState(String(error)); } - }, [tag]); - return Package smoke: {state}