import { useCallback, useEffect, useMemo, useState } from "react"; import { Button, SafeAreaView, ScrollView, StyleSheet, Text, TextInput, View, findNodeHandle } from "react-native"; import { Map } from "@maplibre/maplibre-react-native"; import { WeatherRuntimeBridge, type RuntimeSnapshot, type TargetFps } from "@maplibre-particle/weather-runtime-bridge"; import { weatherTestStyle } from "./src/weatherStyle"; const initialSnapshot: RuntimeSnapshot = { state: "WAITING_FOR_FIELDS", playbackState: "PAUSE", targetFps: "AUTO", disposed: false }; export default function App() { const [reactTag, setReactTag] = useState(null); const [snapshot, setSnapshot] = useState(initialSnapshot); const [result, setResult] = useState("Style is loading"); const [opacity, setOpacity] = useState("0.62"); const attach = useCallback(async (tag: number) => { try { setSnapshot(await WeatherRuntimeBridge.attach(tag)); setReactTag(tag); setResult("WeatherRuntime attached"); } catch (error) { setResult(String(error)); } }, []); // MLRN forwards the native MapView event. Its target is the concrete Fabric MLRNMapView tag; // this is the same tag consumed by MLRN's own NativeMapViewModule. const onStyleReady = useCallback((event: unknown) => { const tag = findNodeHandle((event as { target?: unknown }).target as never); if (tag != null) void attach(tag); }, [attach]); useEffect(() => () => { if (reactTag != null) void WeatherRuntimeBridge.detach(reactTag).catch(() => undefined); }, [reactTag]); const command = useCallback(async (name: string, operation: (tag: number) => Promise) => { if (reactTag == null) return setResult("MAP_NOT_READY: wait for style ready"); try { const value = await operation(reactTag); setResult(`${name}: ${String(value)}`); setSnapshot(await WeatherRuntimeBridge.getState(reactTag)); } catch (error) { setResult(`${name}: ${String(error)}`); } }, [reactTag]); const buttons = useMemo(() => [ ["getState", (tag: number) => WeatherRuntimeBridge.getState(tag)], ["enable", (tag: number) => WeatherRuntimeBridge.setWeatherEnabled(tag, true)], ["weather visible", (tag: number) => WeatherRuntimeBridge.setWeatherColorVisible(tag, true)], ["particle visible", (tag: number) => WeatherRuntimeBridge.setParticleVisible(tag, true)], ["FPS 30", (tag: number) => WeatherRuntimeBridge.setTargetFps(tag, "FPS_30" as TargetFps)], ["PLAY", (tag: number) => WeatherRuntimeBridge.setPlaybackState(tag, "PLAY")], ["PAUSE", (tag: number) => WeatherRuntimeBridge.setPlaybackState(tag, "PAUSE")] ] as const, []); return reactTag: {reactTag ?? "not attached"} runtime: {snapshot.state} / {snapshot.playbackState} / {snapshot.targetFps} {result} {buttons.map(([label, operation]) =>