@aguacerowx/react-native 0.0.53 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/LICENSE +21 -0
  2. package/android/src/main/java/com/aguacerowx/reactnative/NexradRadarLayerView.java +14 -2
  3. package/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +77 -0
  4. package/index.js +1 -1
  5. package/ios/WeatherFrameProcessorModule.m +19 -15
  6. package/ios/WeatherFrameProcessorModule.swift +65 -0
  7. package/lib/commonjs/AguaceroContext.js +0 -4
  8. package/lib/commonjs/AguaceroContext.js.map +1 -1
  9. package/lib/commonjs/GridRenderLayer.js +62 -76
  10. package/lib/commonjs/GridRenderLayer.js.map +1 -1
  11. package/lib/commonjs/MapManager.js +110 -224
  12. package/lib/commonjs/MapManager.js.map +1 -1
  13. package/lib/commonjs/MapRegistry.js +21 -33
  14. package/lib/commonjs/MapRegistry.js.map +1 -1
  15. package/lib/commonjs/NexradRadarLayer.android.js +28 -100
  16. package/lib/commonjs/NexradRadarLayer.android.js.map +1 -1
  17. package/lib/commonjs/NexradRadarLayer.ios.js +26 -97
  18. package/lib/commonjs/NexradRadarLayer.ios.js.map +1 -1
  19. package/lib/commonjs/NexradSitesMapLayer.js +41 -61
  20. package/lib/commonjs/NexradSitesMapLayer.js.map +1 -1
  21. package/lib/commonjs/SatelliteLayer.android.js +26 -38
  22. package/lib/commonjs/SatelliteLayer.android.js.map +1 -1
  23. package/lib/commonjs/SatelliteLayer.ios.js +30 -42
  24. package/lib/commonjs/SatelliteLayer.ios.js.map +1 -1
  25. package/lib/commonjs/StyleApplicator.js +129 -175
  26. package/lib/commonjs/StyleApplicator.js.map +1 -1
  27. package/lib/commonjs/WeatherLayerManager.js +995 -1646
  28. package/lib/commonjs/WeatherLayerManager.js.map +1 -1
  29. package/lib/commonjs/aguaceroCoreDebugHooks.js +58 -130
  30. package/lib/commonjs/aguaceroCoreDebugHooks.js.map +1 -1
  31. package/lib/commonjs/aguaceroRnDebug.js +147 -288
  32. package/lib/commonjs/aguaceroRnDebug.js.map +1 -1
  33. package/lib/commonjs/cdnAuthenticatedFetch.js +104 -0
  34. package/lib/commonjs/cdnAuthenticatedFetch.js.map +1 -0
  35. package/lib/commonjs/dispatchViewManagerCommandCompat.js +51 -88
  36. package/lib/commonjs/dispatchViewManagerCommandCompat.js.map +1 -1
  37. package/lib/commonjs/gridCdnAuth.js +41 -50
  38. package/lib/commonjs/gridCdnAuth.js.map +1 -1
  39. package/lib/commonjs/index.js +14 -0
  40. package/lib/commonjs/index.js.map +1 -1
  41. package/lib/commonjs/nexrad/nexradAndroidController.js +851 -863
  42. package/lib/commonjs/nexrad/nexradAndroidController.js.map +1 -1
  43. package/lib/commonjs/nexrad/nexradCrossSectionSampleAtLatLon.bundled.js +62 -85
  44. package/lib/commonjs/nexrad/nexradCrossSectionSampleAtLatLon.bundled.js.map +1 -1
  45. package/lib/commonjs/nexrad/nexradDiag.js +32 -148
  46. package/lib/commonjs/nexrad/nexradDiag.js.map +1 -1
  47. package/lib/commonjs/nexrad/nexradLevel2Keys.js +261 -0
  48. package/lib/commonjs/nexrad/nexradLevel2Keys.js.map +1 -0
  49. package/lib/commonjs/nexrad/nexradLutBuild.js +64 -111
  50. package/lib/commonjs/nexrad/nexradLutBuild.js.map +1 -1
  51. package/lib/commonjs/nexrad/nexradMapboxFrameOpts.bundled.js +136 -164
  52. package/lib/commonjs/nexrad/nexradMapboxFrameOpts.bundled.js.map +1 -1
  53. package/lib/commonjs/nexrad/nexradSdkImports.js +51 -0
  54. package/lib/commonjs/nexrad/nexradSdkImports.js.map +1 -0
  55. package/lib/commonjs/nexrad/radarArchiveCore.bundled.js +2848 -4455
  56. package/lib/commonjs/nexrad/radarArchiveCore.bundled.js.map +1 -1
  57. package/lib/commonjs/nexrad/radarDecode.worker.bundled.js +445 -648
  58. package/lib/commonjs/nexrad/radarDecode.worker.bundled.js.map +1 -1
  59. package/lib/commonjs/nexrad/radarFrameGpuMatch.bundled.js +52 -68
  60. package/lib/commonjs/nexrad/radarFrameGpuMatch.bundled.js.map +1 -1
  61. package/lib/commonjs/nexradNativeCommandIds.js +24 -0
  62. package/lib/commonjs/nexradNativeCommandIds.js.map +1 -0
  63. package/lib/commonjs/nws/NwsAlertsOverlay.android.js.map +1 -1
  64. package/lib/commonjs/nws/NwsAlertsOverlay.ios.js.map +1 -1
  65. package/lib/commonjs/nws/NwsAlertsOverlay.js +3 -3
  66. package/lib/commonjs/nws/NwsAlertsOverlay.js.map +1 -1
  67. package/lib/commonjs/nws/NwsAlertsOverlay.native.js +235 -361
  68. package/lib/commonjs/nws/NwsAlertsOverlay.native.js.map +1 -1
  69. package/lib/commonjs/nws/eventSourceRnPolyfill.js +92 -146
  70. package/lib/commonjs/nws/eventSourceRnPolyfill.js.map +1 -1
  71. package/lib/commonjs/nws/nwsAndroidConstants.js +2 -8
  72. package/lib/commonjs/nws/nwsAndroidConstants.js.map +1 -1
  73. package/lib/commonjs/satellite/satelliteAndroidController.js +117 -202
  74. package/lib/commonjs/satellite/satelliteAndroidController.js.map +1 -1
  75. package/lib/commonjs/satelliteBridgeDiag.js +3 -13
  76. package/lib/commonjs/satelliteBridgeDiag.js.map +1 -1
  77. package/lib/commonjs/satelliteRnDebug.js +117 -218
  78. package/lib/commonjs/satelliteRnDebug.js.map +1 -1
  79. package/lib/module/AguaceroContext.js +2 -7
  80. package/lib/module/AguaceroContext.js.map +1 -1
  81. package/lib/module/GridRenderLayer.js +66 -80
  82. package/lib/module/GridRenderLayer.js.map +1 -1
  83. package/lib/module/MapManager.js +125 -239
  84. package/lib/module/MapManager.js.map +1 -1
  85. package/lib/module/MapRegistry.js +21 -33
  86. package/lib/module/MapRegistry.js.map +1 -1
  87. package/lib/module/NexradRadarLayer.android.js +32 -104
  88. package/lib/module/NexradRadarLayer.android.js.map +1 -1
  89. package/lib/module/NexradRadarLayer.ios.js +30 -101
  90. package/lib/module/NexradRadarLayer.ios.js.map +1 -1
  91. package/lib/module/NexradSitesMapLayer.js +44 -63
  92. package/lib/module/NexradSitesMapLayer.js.map +1 -1
  93. package/lib/module/SatelliteLayer.android.js +32 -44
  94. package/lib/module/SatelliteLayer.android.js.map +1 -1
  95. package/lib/module/SatelliteLayer.ios.js +36 -48
  96. package/lib/module/SatelliteLayer.ios.js.map +1 -1
  97. package/lib/module/StyleApplicator.js +144 -191
  98. package/lib/module/StyleApplicator.js.map +1 -1
  99. package/lib/module/WeatherLayerManager.js +1024 -1675
  100. package/lib/module/WeatherLayerManager.js.map +1 -1
  101. package/lib/module/aguaceroCoreDebugHooks.js +59 -130
  102. package/lib/module/aguaceroCoreDebugHooks.js.map +1 -1
  103. package/lib/module/aguaceroRnDebug.js +151 -292
  104. package/lib/module/aguaceroRnDebug.js.map +1 -1
  105. package/lib/module/cdnAuthenticatedFetch.js +97 -0
  106. package/lib/module/cdnAuthenticatedFetch.js.map +1 -0
  107. package/lib/module/dispatchViewManagerCommandCompat.js +52 -90
  108. package/lib/module/dispatchViewManagerCommandCompat.js.map +1 -1
  109. package/lib/module/gridCdnAuth.js +38 -50
  110. package/lib/module/gridCdnAuth.js.map +1 -1
  111. package/lib/module/index.js +9 -7
  112. package/lib/module/index.js.map +1 -1
  113. package/lib/module/nexrad/nexradAndroidController.js +865 -876
  114. package/lib/module/nexrad/nexradAndroidController.js.map +1 -1
  115. package/lib/module/nexrad/nexradCrossSectionSampleAtLatLon.bundled.js +62 -85
  116. package/lib/module/nexrad/nexradCrossSectionSampleAtLatLon.bundled.js.map +1 -1
  117. package/lib/module/nexrad/nexradDiag.js +31 -145
  118. package/lib/module/nexrad/nexradDiag.js.map +1 -1
  119. package/lib/module/nexrad/nexradLevel2Keys.js +245 -0
  120. package/lib/module/nexrad/nexradLevel2Keys.js.map +1 -0
  121. package/lib/module/nexrad/nexradLutBuild.js +64 -110
  122. package/lib/module/nexrad/nexradLutBuild.js.map +1 -1
  123. package/lib/module/nexrad/nexradMapboxFrameOpts.bundled.js +136 -163
  124. package/lib/module/nexrad/nexradMapboxFrameOpts.bundled.js.map +1 -1
  125. package/lib/module/nexrad/nexradSdkImports.js +4 -0
  126. package/lib/module/nexrad/nexradSdkImports.js.map +1 -0
  127. package/lib/module/nexrad/radarArchiveCore.bundled.js +2839 -4448
  128. package/lib/module/nexrad/radarArchiveCore.bundled.js.map +1 -1
  129. package/lib/module/nexrad/radarDecode.worker.bundled.js +445 -648
  130. package/lib/module/nexrad/radarDecode.worker.bundled.js.map +1 -1
  131. package/lib/module/nexrad/radarFrameGpuMatch.bundled.js +50 -66
  132. package/lib/module/nexrad/radarFrameGpuMatch.bundled.js.map +1 -1
  133. package/lib/module/nexradNativeCommandIds.js +18 -0
  134. package/lib/module/nexradNativeCommandIds.js.map +1 -0
  135. package/lib/module/nws/NwsAlertsOverlay.android.js +1 -1
  136. package/lib/module/nws/NwsAlertsOverlay.android.js.map +1 -1
  137. package/lib/module/nws/NwsAlertsOverlay.ios.js +1 -1
  138. package/lib/module/nws/NwsAlertsOverlay.ios.js.map +1 -1
  139. package/lib/module/nws/NwsAlertsOverlay.js +5 -5
  140. package/lib/module/nws/NwsAlertsOverlay.js.map +1 -1
  141. package/lib/module/nws/NwsAlertsOverlay.native.js +248 -373
  142. package/lib/module/nws/NwsAlertsOverlay.native.js.map +1 -1
  143. package/lib/module/nws/eventSourceRnPolyfill.js +92 -146
  144. package/lib/module/nws/eventSourceRnPolyfill.js.map +1 -1
  145. package/lib/module/nws/nwsAndroidConstants.js +2 -8
  146. package/lib/module/nws/nwsAndroidConstants.js.map +1 -1
  147. package/lib/module/satellite/satelliteAndroidController.js +123 -208
  148. package/lib/module/satellite/satelliteAndroidController.js.map +1 -1
  149. package/lib/module/satelliteBridgeDiag.js +3 -13
  150. package/lib/module/satelliteBridgeDiag.js.map +1 -1
  151. package/lib/module/satelliteRnDebug.js +123 -223
  152. package/lib/module/satelliteRnDebug.js.map +1 -1
  153. package/lib/typescript/AguaceroContext.d.ts +0 -4
  154. package/lib/typescript/AguaceroContext.d.ts.map +1 -1
  155. package/lib/typescript/GridRenderLayer.d.ts.map +1 -1
  156. package/lib/typescript/MapManager.d.ts +0 -12
  157. package/lib/typescript/MapManager.d.ts.map +1 -1
  158. package/lib/typescript/MapRegistry.d.ts +10 -12
  159. package/lib/typescript/MapRegistry.d.ts.map +1 -1
  160. package/lib/typescript/NexradRadarLayer.android.d.ts.map +1 -1
  161. package/lib/typescript/NexradRadarLayer.ios.d.ts.map +1 -1
  162. package/lib/typescript/NexradSitesMapLayer.d.ts +4 -10
  163. package/lib/typescript/NexradSitesMapLayer.d.ts.map +1 -1
  164. package/lib/typescript/SatelliteLayer.android.d.ts.map +1 -1
  165. package/lib/typescript/SatelliteLayer.ios.d.ts.map +1 -1
  166. package/lib/typescript/StyleApplicator.d.ts +1 -1
  167. package/lib/typescript/StyleApplicator.d.ts.map +1 -1
  168. package/lib/typescript/WeatherLayerManager.d.ts.map +1 -1
  169. package/lib/typescript/aguaceroCoreDebugHooks.d.ts +2 -9
  170. package/lib/typescript/aguaceroCoreDebugHooks.d.ts.map +1 -1
  171. package/lib/typescript/aguaceroRnDebug.d.ts +47 -66
  172. package/lib/typescript/aguaceroRnDebug.d.ts.map +1 -1
  173. package/lib/typescript/cdnAuthenticatedFetch.d.ts +10 -0
  174. package/lib/typescript/cdnAuthenticatedFetch.d.ts.map +1 -0
  175. package/lib/typescript/dispatchViewManagerCommandCompat.d.ts +1 -17
  176. package/lib/typescript/dispatchViewManagerCommandCompat.d.ts.map +1 -1
  177. package/lib/typescript/gridCdnAuth.d.ts +16 -21
  178. package/lib/typescript/gridCdnAuth.d.ts.map +1 -1
  179. package/lib/typescript/index.d.ts +1 -0
  180. package/lib/typescript/nexrad/nexradAndroidController.d.ts +39 -89
  181. package/lib/typescript/nexrad/nexradAndroidController.d.ts.map +1 -1
  182. package/lib/typescript/nexrad/nexradCrossSectionSampleAtLatLon.bundled.d.ts +2 -1
  183. package/lib/typescript/nexrad/nexradCrossSectionSampleAtLatLon.bundled.d.ts.map +1 -1
  184. package/lib/typescript/nexrad/nexradDiag.d.ts +13 -101
  185. package/lib/typescript/nexrad/nexradDiag.d.ts.map +1 -1
  186. package/lib/typescript/nexrad/nexradLevel2Keys.d.ts +36 -0
  187. package/lib/typescript/nexrad/nexradLevel2Keys.d.ts.map +1 -0
  188. package/lib/typescript/nexrad/nexradLutBuild.d.ts +3 -10
  189. package/lib/typescript/nexrad/nexradLutBuild.d.ts.map +1 -1
  190. package/lib/typescript/nexrad/nexradMapboxFrameOpts.bundled.d.ts +4 -3
  191. package/lib/typescript/nexrad/nexradMapboxFrameOpts.bundled.d.ts.map +1 -1
  192. package/lib/typescript/nexrad/nexradSdkImports.d.ts +2 -0
  193. package/lib/typescript/nexrad/nexradSdkImports.d.ts.map +1 -0
  194. package/lib/typescript/nexrad/radarArchiveCore.bundled.d.ts +12 -7
  195. package/lib/typescript/nexrad/radarArchiveCore.bundled.d.ts.map +1 -1
  196. package/lib/typescript/nexrad/radarDecode.worker.bundled.d.ts +20 -20
  197. package/lib/typescript/nexrad/radarDecode.worker.bundled.d.ts.map +1 -1
  198. package/lib/typescript/nexrad/radarFrameGpuMatch.bundled.d.ts +4 -3
  199. package/lib/typescript/nexrad/radarFrameGpuMatch.bundled.d.ts.map +1 -1
  200. package/lib/typescript/nexradNativeCommandIds.d.ts +2 -0
  201. package/lib/typescript/nexradNativeCommandIds.d.ts.map +1 -0
  202. package/lib/typescript/nws/NwsAlertsOverlay.native.d.ts +6 -17
  203. package/lib/typescript/nws/NwsAlertsOverlay.native.d.ts.map +1 -1
  204. package/lib/typescript/nws/eventSourceRnPolyfill.d.ts +0 -3
  205. package/lib/typescript/nws/eventSourceRnPolyfill.d.ts.map +1 -1
  206. package/lib/typescript/nws/nwsAndroidConstants.d.ts +0 -5
  207. package/lib/typescript/nws/nwsAndroidConstants.d.ts.map +1 -1
  208. package/lib/typescript/satellite/satelliteAndroidController.d.ts +9 -47
  209. package/lib/typescript/satellite/satelliteAndroidController.d.ts.map +1 -1
  210. package/lib/typescript/satelliteBridgeDiag.d.ts +1 -5
  211. package/lib/typescript/satelliteBridgeDiag.d.ts.map +1 -1
  212. package/lib/typescript/satelliteRnDebug.d.ts +24 -30
  213. package/lib/typescript/satelliteRnDebug.d.ts.map +1 -1
  214. package/package.json +75 -74
  215. package/src/AguaceroContext.js +1 -7
  216. package/src/GridRenderLayer.js +1 -128
  217. package/src/MapManager.js +1 -277
  218. package/src/MapRegistry.js +1 -56
  219. package/src/NexradRadarLayer.android.js +1 -121
  220. package/src/NexradRadarLayer.ios.js +1 -115
  221. package/src/NexradSitesMapLayer.js +1 -75
  222. package/src/SatelliteLayer.android.js +1 -63
  223. package/src/SatelliteLayer.ios.js +1 -70
  224. package/src/StyleApplicator.js +1 -241
  225. package/src/WeatherLayerManager.js +1 -2045
  226. package/src/aguaceroCoreDebugHooks.js +1 -142
  227. package/src/aguaceroRnDebug.js +1 -336
  228. package/src/cdnAuthenticatedFetch.js +1 -0
  229. package/src/dispatchViewManagerCommandCompat.js +1 -100
  230. package/src/gridCdnAuth.js +1 -56
  231. package/src/index.js +1 -27
  232. package/src/nexrad/nexradAndroidController.js +1 -1078
  233. package/src/nexrad/nexradCrossSectionSampleAtLatLon.bundled.js +1 -91
  234. package/src/nexrad/nexradDiag.js +1 -150
  235. package/src/nexrad/nexradLevel2Keys.js +1 -0
  236. package/src/nexrad/nexradLutBuild.js +1 -126
  237. package/src/nexrad/nexradMapboxFrameOpts.bundled.js +1 -245
  238. package/src/nexrad/nexradSdkImports.js +1 -0
  239. package/src/nexrad/radarArchiveCore.bundled.js +1 -7085
  240. package/src/nexrad/radarDecode.worker.bundled.js +1 -813
  241. package/src/nexrad/radarFrameGpuMatch.bundled.js +1 -79
  242. package/src/nexradNativeCommandIds.js +1 -0
  243. package/src/nws/NwsAlertsOverlay.android.js +1 -1
  244. package/src/nws/NwsAlertsOverlay.ios.js +1 -1
  245. package/src/nws/NwsAlertsOverlay.js +1 -7
  246. package/src/nws/NwsAlertsOverlay.native.js +1 -463
  247. package/src/nws/eventSourceRnPolyfill.js +7 -193
  248. package/src/nws/nwsAndroidConstants.js +1 -8
  249. package/src/satellite/satelliteAndroidController.js +1 -257
  250. package/src/satelliteBridgeDiag.js +1 -15
  251. package/src/satelliteRnDebug.js +1 -269
  252. package/lib/commonjs/nexrad/nexradNativeCommandIds.js +0 -51
  253. package/lib/commonjs/nexrad/nexradNativeCommandIds.js.map +0 -1
  254. package/lib/module/nexrad/nexradNativeCommandIds.js +0 -44
  255. package/lib/module/nexrad/nexradNativeCommandIds.js.map +0 -1
  256. package/lib/typescript/nexrad/nexradNativeCommandIds.d.ts +0 -9
  257. package/lib/typescript/nexrad/nexradNativeCommandIds.d.ts.map +0 -1
  258. package/src/nexrad/nexradNativeCommandIds.js +0 -44
  259. /package/lib/commonjs/{nexrad/nexradSitesUs.json → nexradSitesUs.json} +0 -0
  260. /package/lib/module/{nexrad/nexradSitesUs.json → nexradSitesUs.json} +0 -0
  261. /package/src/{nexrad/nexradSitesUs.json → nexradSitesUs.json} +0 -0
@@ -1,1835 +1,1184 @@
1
- // packages/react-native/src/WeatherLayerManager.js
2
-
3
- import { AguaceroCore, DICTIONARIES, formatTimelineDurationValue, getUnitConversionFunction, parseTimelineDurationHours } from '@aguacerowx/javascript-sdk';
4
- import { fromByteArray } from 'base64-js';
5
- import React, { forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
6
- import { NativeModules, Platform, UIManager } from 'react-native';
7
- import { AguaceroContext } from './AguaceroContext';
8
- import { GridRenderLayer } from './GridRenderLayer';
9
- import NexradRadarLayer from './NexradRadarLayer';
10
- import SatelliteLayer from './SatelliteLayer';
11
- import { NexradSitesMapLayer } from './NexradSitesMapLayer';
12
- import { NexradAndroidController } from './nexrad/nexradAndroidController';
13
- import { SatelliteAndroidController } from './satellite/satelliteAndroidController';
14
- import NwsAlertsOverlay from './nws/NwsAlertsOverlay';
15
- import { mapRegistry } from './MapRegistry';
16
- import { satBridgeWarn } from './satelliteBridgeDiag';
17
- import { augmentProcessFrameOptionsForDebug, aguaceroDebugWarn, configureAguaceroRnDebug, getAguaceroAuthDiagnosticSnapshot, isAguaceroRnDebugEnabled } from './aguaceroRnDebug';
18
- import { installAguaceroCoreDebugHooks, logProcessFrameAuthMismatch } from './aguaceroCoreDebugHooks';
19
- import { resolveGridRequestSiteOrigin } from './gridCdnAuth';
20
- import { auditSatelliteIntegration, installSatelliteDiagnosticListener } from './satelliteRnDebug';
21
- const NEXRAD_NATIVE = Platform.OS === 'android' || Platform.OS === 'ios';
22
- const SATELLITE_NATIVE = Platform.OS === 'android' || Platform.OS === 'ios';
23
- satBridgeWarn('SDK fingerprint', {
24
- platform: Platform.OS,
25
- SATELLITE_NATIVE,
26
- note: 'If you never see sat-bridge logs, the app bundle is not loading this WeatherLayerManager build.'
1
+ import { AguaceroCore as je, DICTIONARIES as Be, formatTimelineDurationValue as ct, getUnitConversionFunction as ve, parseTimelineDurationHours as xt } from "@aguacerowx/javascript-sdk";
2
+ import { fromByteArray as ze } from "base64-js";
3
+ import be, { forwardRef as Tt, useCallback as we, useContext as Ct, useEffect as j, useImperativeHandle as Mt, useMemo as ut, useRef as V, useState as Je } from "react";
4
+ import { NativeModules as vt, Platform as se, UIManager as mt } from "react-native";
5
+ import { AguaceroContext as $t } from "./AguaceroContext";
6
+ import { GridRenderLayer as _t } from "./GridRenderLayer";
7
+ import Nt from "./NexradRadarLayer";
8
+ import Dt from "./SatelliteLayer";
9
+ import { NexradSitesMapLayer as It } from "./NexradSitesMapLayer";
10
+ import { SatelliteAndroidController as Rt } from "./satellite/satelliteAndroidController";
11
+ import { NexradAndroidController as Ft } from "./nexrad/nexradAndroidController";
12
+ import { createNexradCloudFrontFetch as At } from "./cdnAuthenticatedFetch";
13
+ import { setNexradLevel2CloudFrontFetch as dt } from "./nexrad/radarArchiveCore.bundled.js";
14
+ import Pt from "./nws/NwsAlertsOverlay";
15
+ import { mapRegistry as Ue } from "./MapRegistry";
16
+ import { satBridgeWarn as Ee } from "./satelliteBridgeDiag";
17
+ import { augmentProcessFrameOptionsForDebug as Xe, aguaceroDebugWarn as Ye, configureAguaceroRnDebug as Lt, getAguaceroAuthDiagnosticSnapshot as ft, isAguaceroRnDebugEnabled as Ke } from "./aguaceroRnDebug";
18
+ import { installAguaceroCoreDebugHooks as Vt, logProcessFrameAuthMismatch as Qe } from "./aguaceroCoreDebugHooks";
19
+ import { buildNativeCloudFrontFetchOptions as Ot, resolveGridRequestSiteOrigin as wt } from "./gridCdnAuth";
20
+ import { auditSatelliteIntegration as Ut, installSatelliteDiagnosticListener as Et } from "./satelliteRnDebug";
21
+ const Q = se.OS === "android" || se.OS === "ios",
22
+ ie = se.OS === "android" || se.OS === "ios";
23
+ Ee("SDK fingerprint", {
24
+ platform: se.OS,
25
+ SATELLITE_NATIVE: ie,
26
+ note: "If you never see sat-bridge logs, the app bundle is not loading this WeatherLayerManager build."
27
27
  });
28
-
29
- /**
30
- * Same filtering as {@link AguaceroCore#_getFilteredMrmsTimestampsForVariable} for older cores
31
- * where that helper (or {@code setMRMSDurationValue}) is missing from the prototype chain.
32
- */
33
- function getFilteredMrmsTimestampsCompat(core, variable) {
34
- const raw = core.mrmsStatus?.[variable];
35
- if (!raw || !raw.length) return [];
36
- const hours = parseTimelineDurationHours(core.state.mrmsDurationValue);
37
- let list = [...raw].map(t => Number(t)).filter(t => !Number.isNaN(t)).sort((a, b) => a - b);
38
- if (hours > 0 && list.length > 0) {
39
- const latest = list[list.length - 1];
40
- const cutoff = latest - hours * 3600;
41
- list = list.filter(t => t >= cutoff);
28
+ function Kt(m, x) {
29
+ const g = m.mrmsStatus?.[x];
30
+ if (!g || !g.length) return [];
31
+ const I = xt(m.state.mrmsDurationValue);
32
+ let v = [...g].map(O => Number(O)).filter(O => !Number.isNaN(O)).sort((O, _) => O - _);
33
+ if (I > 0 && v.length > 0) {
34
+ const O = v[v.length - 1] - I * 3600;
35
+ v = v.filter(_ => _ >= O);
42
36
  }
43
- return list;
37
+ return v;
44
38
  }
45
-
46
- /**
47
- * Older npm installs may resolve an {@link AguaceroCore} without {@code setMRMSDurationValue} /
48
- * {@code setNexradDurationValue}; mirror those methods here using the same logic as the SDK.
49
- */
50
- async function applyMrmsDurationValue(core, value) {
51
- if (typeof core.setMRMSDurationValue === 'function') {
52
- await core.setMRMSDurationValue(value);
39
+ async function qt(m, x) {
40
+ if (typeof m.setMRMSDurationValue == "function") {
41
+ await m.setMRMSDurationValue(x);
53
42
  return;
54
43
  }
55
- const v = formatTimelineDurationValue(value);
56
- await core.setState({
57
- mrmsDurationValue: v
58
- });
59
- if (!core.state.isMRMS || !core.state.variable) return;
60
- const filtered = typeof core._getFilteredMrmsTimestampsForVariable === 'function' ? core._getFilteredMrmsTimestampsForVariable(core.state.variable) : getFilteredMrmsTimestampsCompat(core, core.state.variable);
61
- if (!filtered || filtered.length === 0) return;
62
- const curN = core.state.mrmsTimestamp == null ? null : Number(core.state.mrmsTimestamp);
63
- if (curN == null || !filtered.includes(curN)) {
64
- await core.setState({
65
- mrmsTimestamp: filtered[filtered.length - 1]
66
- });
67
- }
68
- }
69
- async function applyNexradDurationValue(core, value) {
70
- if (typeof core.setNexradDurationValue === 'function') {
71
- await core.setNexradDurationValue(value);
72
- return;
73
- }
74
- const v = formatTimelineDurationValue(value);
75
- await core.setState({
76
- nexradDurationValue: v
77
- });
78
- if (!core.state.isNexrad || !core.state.nexradSite) return;
79
- if (typeof core.refreshNexradTimes === 'function') {
80
- await core.refreshNexradTimes();
81
- }
82
- const nk = typeof core._nexradTimesCacheKey === 'function' ? core._nexradTimesCacheKey() : null;
83
- const raw = nk ? core.nexradTimesByStation?.[nk]?.unixTimes || [] : [];
84
- const filtered = typeof core._getFilteredNexradTimestampsForVariable === 'function' ? core._getFilteredNexradTimestampsForVariable(raw) : [...raw].map(t => Number(t)).filter(t => !Number.isNaN(t)).sort((a, b) => a - b);
85
- if (!filtered || filtered.length === 0) return;
86
- const curN = core.state.nexradTimestamp == null ? null : Number(core.state.nexradTimestamp);
87
- if (curN == null || !filtered.includes(curN)) {
88
- await core.setState({
89
- nexradTimestamp: filtered[filtered.length - 1]
90
- });
91
- }
44
+ const g = ct(x);
45
+ if (await m.setState({
46
+ mrmsDurationValue: g
47
+ }), !m.state.isMRMS || !m.state.variable) return;
48
+ const I = typeof m._getFilteredMrmsTimestampsForVariable == "function" ? m._getFilteredMrmsTimestampsForVariable(m.state.variable) : Kt(m, m.state.variable);
49
+ if (!I || I.length === 0) return;
50
+ const v = m.state.mrmsTimestamp == null ? null : Number(m.state.mrmsTimestamp);
51
+ (v == null || !I.includes(v)) && (await m.setState({
52
+ mrmsTimestamp: I[I.length - 1]
53
+ }));
92
54
  }
93
- function findLatestModelRun(modelsData, modelName) {
94
- const model = modelsData?.[modelName];
95
- if (!model) return null;
96
- const availableDates = Object.keys(model).sort((a, b) => b.localeCompare(a));
97
- for (const date of availableDates) {
98
- const runs = model[date];
99
- if (!runs) continue;
100
- const availableRuns = Object.keys(runs).sort((a, b) => b.localeCompare(a));
101
- if (availableRuns.length > 0) return {
102
- date: date,
103
- run: availableRuns[0]
55
+ function Gt(m, x) {
56
+ const g = m?.[x];
57
+ if (!g) return null;
58
+ const I = Object.keys(g).sort((v, O) => O.localeCompare(v));
59
+ for (const v of I) {
60
+ const O = g[v];
61
+ if (!O) continue;
62
+ const _ = Object.keys(O).sort((ee, B) => B.localeCompare(ee));
63
+ if (_.length > 0) return {
64
+ date: v,
65
+ run: _[0]
104
66
  };
105
67
  }
106
68
  return null;
107
69
  }
108
70
  const {
109
- WeatherFrameProcessorModule,
110
- InspectorModule
111
- } = NativeModules;
112
-
113
- /**
114
- * `state:change` payloads can briefly have {@code isNexrad} before {@code nexradSite} / {@code nexradTimestamp}
115
- * are populated; {@code core.state} is updated first. Merge so readouts match the active radar.
116
- *
117
- * @param {object | null} emitted
118
- * @param {object | null} coreState
119
- */
120
- function mergeNexradEmittedWithCore(emitted, coreState) {
121
- if (!emitted || !coreState) return null;
122
- return {
123
- ...emitted,
124
- nexradSite: coreState.nexradSite ?? emitted.nexradSite,
125
- nexradTimestamp: coreState.nexradTimestamp ?? emitted.nexradTimestamp,
126
- nexradProduct: coreState.nexradProduct ?? emitted.nexradProduct,
127
- nexradTilt: coreState.nexradTilt ?? emitted.nexradTilt,
128
- nexradDataSource: coreState.nexradDataSource ?? emitted.nexradDataSource,
129
- nexradStormRelative: coreState.nexradStormRelative ?? emitted.nexradStormRelative
130
- };
71
+ WeatherFrameProcessorModule: qe,
72
+ InspectorModule: kt
73
+ } = vt;
74
+ function ue(m) {
75
+ const x = Object.keys(m?.satelliteTimeToFileMap || {}).map(Number).filter(g => Number.isFinite(g)).sort((g, I) => g - I);
76
+ return x.length ? `${x.length}:${x[0]}:${x[x.length - 1]}` : "0";
131
77
  }
132
-
133
- /**
134
- * Compact timeline identity for deduping {@code state:change}: extending the NEXRAD/satellite window
135
- * often keeps the same selected unix — without this, {@link WeatherLayerManager} short-circuits and
136
- * never calls native {@code sync} / preload with the expanded frame list.
137
- */
138
- function nexradObsTimelineSig(state) {
139
- const arr = [...(state?.availableNexradTimestamps || [])].map(Number).filter(t => Number.isFinite(t)).sort((a, b) => a - b);
140
- if (!arr.length) return '0';
141
- return `${arr.length}:${arr[0]}:${arr[arr.length - 1]}`;
142
- }
143
- function satelliteObsTimelineSig(state) {
144
- const keys = Object.keys(state?.satelliteTimeToFileMap || {}).map(Number).filter(t => Number.isFinite(t)).sort((a, b) => a - b);
145
- if (!keys.length) return '0';
146
- return `${keys.length}:${keys[0]}:${keys[keys.length - 1]}`;
147
- }
148
-
149
- /** True when {@link WeatherLayerManager} `debug` / {@link configureAguaceroRnDebug}, or legacy `__AGUACERO_WX_GRID_DEBUG__`. */
150
- function wxGridDebugEnabled() {
151
- if (isAguaceroRnDebugEnabled()) return true;
78
+ function pt() {
79
+ if (Ke()) return !0;
152
80
  try {
153
- if (typeof __DEV__ !== 'undefined' && __DEV__) return true;
154
- return Boolean(typeof globalThis !== 'undefined' && globalThis.__AGUACERO_WX_GRID_DEBUG__);
81
+ return typeof __DEV__ < "u" && __DEV__ ? !0 : !!(typeof globalThis < "u" && globalThis.__AGUACERO_WX_GRID_DEBUG__);
155
82
  } catch {
156
- return false;
83
+ return !1;
157
84
  }
158
85
  }
159
- function wxGridVerbose(tag, detail) {
160
- if (!wxGridDebugEnabled()) return;
161
- if (detail !== undefined) {
162
- console.log(`[AguaceroWX][grid][${tag}]`, detail);
163
- } else {
164
- console.log(`[AguaceroWX][grid][${tag}]`);
165
- }
86
+ function z(m, x) {
87
+ pt() && (x !== void 0 ? console.log(`[AguaceroWX][grid][${m}]`, x) : console.log(`[AguaceroWX][grid][${m}]`));
166
88
  }
167
-
168
- /** Always logs (Metro / device logs) use for failures and unusual early exits. */
169
- function wxGridWarn(tag, detail) {
170
- if (detail !== undefined) {
171
- console.warn(`[AguaceroWX][grid][${tag}]`, detail);
172
- } else {
173
- console.warn(`[AguaceroWX][grid][${tag}]`);
174
- }
89
+ function Z(m, x) {
90
+ x !== void 0 ? console.warn(`[AguaceroWX][grid][${m}]`, x) : console.warn(`[AguaceroWX][grid][${m}]`);
175
91
  }
176
-
177
- /**
178
- * Native {@code processFrame} must mirror browser/AguaceroCore grid auth: encoded {@code apiKey}
179
- * in the query string and optional {@code Origin} / {@code Referer} (many CloudFront setups require them).
180
- *
181
- * @param {string} baseGridUrl
182
- * @param {string} resourcePath
183
- * @param {string} apiKey
184
- * @param {string | null | undefined} bundleId
185
- * @param {string | undefined} gridRequestSiteOrigin - prop or core origin (see {@link resolveGridRequestSiteOrigin})
186
- * @param {import('@aguacerowx/javascript-sdk').AguaceroCore | null | undefined} core
187
- */
188
- function buildGridFrameProcessOptions(baseGridUrl, resourcePath, apiKey, bundleId, gridRequestSiteOrigin, core) {
189
- const trimmedKey = typeof apiKey === 'string' ? apiKey.trim() : apiKey;
190
- const url = `${baseGridUrl}${resourcePath}?apiKey=${encodeURIComponent(trimmedKey || '')}`;
191
- const options = {
192
- url,
193
- apiKey: trimmedKey,
194
- bundleId
195
- };
196
- const origin = resolveGridRequestSiteOrigin(gridRequestSiteOrigin, core);
197
- if (origin) {
198
- options.gridRequestSiteOrigin = origin;
199
- }
200
- return options;
92
+ function Ze(m, x, g, I, v, O) {
93
+ const _ = `${m}${x}`;
94
+ return Ot({
95
+ url: _,
96
+ apiKey: g,
97
+ bundleId: I,
98
+ gridRequestSiteOrigin: v,
99
+ core: O
100
+ });
201
101
  }
202
-
203
- /**
204
- * A helper function to generate the raw RGBA byte buffer for the colormap texture.
205
- */
206
- const _generateColormapBytes = colormap => {
207
- const width = 256;
208
- const data = new Uint8Array(width * 4);
209
- const stops = colormap.reduce((acc, _, i) => i % 2 === 0 ? [...acc, {
210
- value: colormap[i],
211
- color: colormap[i + 1]
212
- }] : acc, []);
213
- if (stops.length === 0) return data;
214
- const minVal = stops[0].value;
215
- const maxVal = stops[stops.length - 1].value;
216
- const hexToRgb = hex => {
217
- const r = parseInt(hex.slice(1, 3), 16);
218
- const g = parseInt(hex.slice(3, 5), 16);
219
- const b = parseInt(hex.slice(5, 7), 16);
220
- return [r, g, b];
221
- };
222
- for (let i = 0; i < width; i++) {
223
- const val = minVal + i / (width - 1) * (maxVal - minVal);
224
- let lower = stops[0];
225
- let upper = stops[stops.length - 1];
226
- for (let j = 0; j < stops.length - 1; j++) {
227
- if (val >= stops[j].value && val <= stops[j + 1].value) {
228
- lower = stops[j];
229
- upper = stops[j + 1];
230
- break;
231
- }
102
+ const et = m => {
103
+ const x = new Uint8Array(1024),
104
+ g = m.reduce((_, ee, B) => B % 2 === 0 ? [..._, {
105
+ value: m[B],
106
+ color: m[B + 1]
107
+ }] : _, []);
108
+ if (g.length === 0) return x;
109
+ const I = g[0].value,
110
+ v = g[g.length - 1].value,
111
+ O = _ => {
112
+ const ee = parseInt(_.slice(1, 3), 16),
113
+ B = parseInt(_.slice(3, 5), 16),
114
+ fe = parseInt(_.slice(5, 7), 16);
115
+ return [ee, B, fe];
116
+ };
117
+ for (let _ = 0; _ < 256; _++) {
118
+ const ee = I + _ / 255 * (v - I);
119
+ let B = g[0],
120
+ fe = g[g.length - 1];
121
+ for (let J = 0; J < g.length - 1; J++) if (ee >= g[J].value && ee <= g[J + 1].value) {
122
+ B = g[J], fe = g[J + 1];
123
+ break;
232
124
  }
233
- const t = (val - lower.value) / (upper.value - lower.value || 1);
234
- const lowerRgb = hexToRgb(lower.color);
235
- const upperRgb = hexToRgb(upper.color);
236
- const rgb = lowerRgb.map((c, idx) => c * (1 - t) + upperRgb[idx] * t);
237
- const offset = i * 4;
238
- data[offset + 0] = Math.round(rgb[0]);
239
- data[offset + 1] = Math.round(rgb[1]);
240
- data[offset + 2] = Math.round(rgb[2]);
241
- data[offset + 3] = 255;
125
+ const Ae = (ee - B.value) / (fe.value - B.value || 1),
126
+ Pe = O(B.color),
127
+ xe = O(fe.color),
128
+ $e = Pe.map((J, Ge) => J * (1 - Ae) + xe[Ge] * Ae),
129
+ Te = _ * 4;
130
+ x[Te + 0] = Math.round($e[0]), x[Te + 1] = Math.round($e[1]), x[Te + 2] = Math.round($e[2]), x[Te + 3] = 255;
242
131
  }
243
- return data;
132
+ return x;
244
133
  };
245
- AguaceroCore.prototype.setMapCenter = function (center) {
246
- this.emit('map:move', center);
134
+ je.prototype.setMapCenter = function (m) {
135
+ this.emit("map:move", m);
247
136
  };
248
- export const WeatherLayerManager = /*#__PURE__*/forwardRef((props, ref) => {
137
+ export const WeatherLayerManager = /*#__PURE__*/Tt((m, x) => {
249
138
  const {
250
- inspectorEnabled,
251
- onInspect,
252
- apiKey,
253
- customColormaps,
254
- initialMode,
255
- initialVariable,
256
- /** GOES instrument when {@link initialMode} is `"satellite"` (default `GOES19-EAST`). */
257
- initialSatelliteId,
258
- /** Sector token or label when {@link initialMode} is `"satellite"` (default `conus` → GOES-EAST CONUS). */
259
- initialSatelliteSector,
260
- /** Product/band when {@link initialMode} is `"satellite"` (e.g. `geocolor`, `C13`). Falls back to {@link initialVariable}. */
261
- initialSatelliteProduct,
262
- autoRefresh,
263
- autoRefreshInterval,
264
- initialModel,
265
- belowID: belowIDFromProps,
266
- interpolateNexradColormap = true,
267
- nexradGateSmoothing = false,
268
- watchesWarnings: watchesWarningsProp,
269
- onNwsAlertClick,
270
- /** Same semantics as mapsgl / AguaceroCore: Origin + Referer for grid CDN (required by many CloudFront rules). */
271
- gridRequestSiteOrigin,
272
- /** When true, logs auth/HTTP diagnostics under `[AguaceroRN][debug]` (Metro / Logcat / Xcode). */
273
- debug = false,
274
- ...restProps
275
- } = props;
276
- useEffect(() => {
277
- configureAguaceroRnDebug({
278
- enabled: Boolean(debug)
139
+ inspectorEnabled: g,
140
+ onInspect: I,
141
+ apiKey: v,
142
+ customColormaps: O,
143
+ initialMode: _,
144
+ initialVariable: ee,
145
+ initialSatelliteId: B,
146
+ initialSatelliteSector: fe,
147
+ initialSatelliteProduct: Ae,
148
+ autoRefresh: Pe,
149
+ autoRefreshInterval: xe,
150
+ initialModel: $e,
151
+ belowID: Te,
152
+ watchesWarnings: J,
153
+ onNwsAlertClick: Ge,
154
+ gridRequestSiteOrigin: te,
155
+ debug: Ce = !1,
156
+ ...Ht
157
+ } = m;
158
+ j(() => {
159
+ Lt({
160
+ enabled: !!Ce
279
161
  });
280
- }, [debug]);
281
- useEffect(() => {
282
- if (!debug) return undefined;
283
- auditSatelliteIntegration({
284
- core,
285
- satelliteLayerRef
286
- });
287
- return installSatelliteDiagnosticListener();
288
- }, [debug, core]);
289
- const context = useContext(AguaceroContext);
290
-
291
- // Create the core here instead of getting it from context
292
- const core = useMemo(() => new AguaceroCore({
293
- apiKey: apiKey,
294
- customColormaps: customColormaps,
295
- gridRequestSiteOrigin: gridRequestSiteOrigin,
296
- layerOptions: {
297
- mode: initialMode,
298
- variable: initialVariable,
299
- model: initialModel,
300
- ...(initialMode === 'satellite' ? {
301
- satelliteId: initialSatelliteId,
302
- sector: initialSatelliteSector,
303
- satelliteProduct: initialSatelliteProduct ?? initialVariable
304
- } : {})
305
- },
306
- autoRefresh: false // <-- add this
307
- }), [apiKey, gridRequestSiteOrigin]);
308
- useEffect(() => {
309
- if (!core) return;
310
- installAguaceroCoreDebugHooks(core, {
311
- gridRequestSiteOriginProp: gridRequestSiteOrigin ?? null,
312
- debugProp: Boolean(debug)
313
- });
314
- if (isAguaceroRnDebugEnabled() && !apiKey) {
315
- aguaceroDebugWarn('WeatherLayerManager.missingApiKey', {
316
- hint: 'apiKey prop is empty — all CDN requests will fail or return 403'
317
- });
318
- }
319
- if (isAguaceroRnDebugEnabled() && apiKey && !gridRequestSiteOrigin) {
320
- aguaceroDebugWarn('WeatherLayerManager.missingGridOrigin', {
321
- hint: 'gridRequestSiteOrigin is not set — CloudFront often returns 403 without Origin/Referer on React Native',
322
- snapshot: getAguaceroAuthDiagnosticSnapshot(core)
323
- });
324
- }
325
- }, [core, debug, gridRequestSiteOrigin, apiKey]);
326
- const [watchesWarningsOptions, setWatchesWarningsOptions] = useState(() => ({
327
- alertInteractionEnabled: true,
328
- ...(watchesWarningsProp ?? {})
162
+ }, [Ce]), j(() => {
163
+ if (Ce) return Ut({
164
+ core: t,
165
+ satelliteLayerRef: Ne
166
+ }), Et();
167
+ }, [Ce, t]);
168
+ const _e = Ct($t),
169
+ t = ut(() => new je({
170
+ apiKey: v,
171
+ customColormaps: O,
172
+ gridRequestSiteOrigin: te,
173
+ layerOptions: {
174
+ mode: _,
175
+ variable: ee,
176
+ model: $e,
177
+ ...(_ === "satellite" ? {
178
+ satelliteId: B,
179
+ sector: fe,
180
+ satelliteProduct: Ae ?? ee
181
+ } : {})
182
+ },
183
+ autoRefresh: !1
184
+ }), [v, te]);
185
+ j(() => {
186
+ t && (Vt(t, {
187
+ gridRequestSiteOriginProp: te ?? null,
188
+ debugProp: !!Ce
189
+ }), Ke() && !v && Ye("WeatherLayerManager.missingApiKey", {
190
+ hint: "apiKey prop is empty \u2014 all CDN requests will fail or return 403"
191
+ }), Ke() && v && !te && Ye("WeatherLayerManager.missingGridOrigin", {
192
+ hint: "gridRequestSiteOrigin is not set \u2014 CloudFront often returns 403 without Origin/Referer on React Native",
193
+ snapshot: ft(t)
194
+ }));
195
+ }, [t, Ce, te, v]);
196
+ const [gt, tt] = Je(() => ({
197
+ alertInteractionEnabled: !0,
198
+ ...(J ?? {})
329
199
  }));
330
- useEffect(() => {
331
- setWatchesWarningsOptions(prev => ({
332
- ...prev,
333
- ...(watchesWarningsProp ?? {})
200
+ j(() => {
201
+ tt(r => ({
202
+ ...r,
203
+ ...(J ?? {})
334
204
  }));
335
- }, [watchesWarningsProp]);
336
- useEffect(() => {
337
- setNexradSitesMapVisible(Boolean(core.state.isNexrad && core.state.nexradShowSitesPicker !== false));
338
- }, [core]);
339
- const gridLayerRef = useRef(null);
340
- const nexradLayerRef = useRef(null);
341
- const nexradControllerRef = useRef(null);
342
- /** Latest {@code state:change} payload (includes {@code colormap}, NEXRAD maps) — required for readouts; {@code core.state} omits those. */
343
- const lastEmittedStateForInspectRef = useRef(null);
344
- const satelliteLayerRef = useRef(null);
345
- const satelliteControllerRef = useRef(null);
346
- /** @type {React.MutableRefObject<{ cancel?: () => void } | null>} */
347
- const nexradPreloadInteractionRef = useRef(null);
348
- const currentGridDataRef = useRef(null);
349
- const autoRefreshIntervalId = useRef(null);
350
- const ensureNexradController = useCallback(() => {
351
- if (!NEXRAD_NATIVE) return null;
352
- if (!nexradControllerRef.current) {
353
- nexradControllerRef.current = new NexradAndroidController(core, nexradLayerRef, {
354
- interpolateNexradColormap,
355
- nexradGateSmoothing
356
- });
357
- }
358
- return nexradControllerRef.current;
359
- }, [core, interpolateNexradColormap, nexradGateSmoothing]);
360
-
361
- /** Synchronous NEXRAD readout (mapsgl-style); no await — avoids jank on map move. */
362
- const getNexradInspectPayloadAt = useCallback((lng, lat) => {
363
- if (!NEXRAD_NATIVE || !core?.state?.isNexrad) return null;
364
- const ctl = ensureNexradController();
365
- if (!ctl) {
366
- return null;
367
- }
368
- const emitted = lastEmittedStateForInspectRef.current;
369
- if (!emitted) {
370
- return null;
371
- }
372
- const st = mergeNexradEmittedWithCore(emitted, core.state);
373
- if (!st?.nexradSite || st.nexradTimestamp == null) {
374
- return null;
375
- }
376
- return ctl.getInspectPayload(lng, lat, st) ?? null;
377
- }, [core, ensureNexradController]);
378
- const ensureSatelliteController = useCallback(() => {
379
- if (!SATELLITE_NATIVE) return null;
380
- if (!satelliteControllerRef.current) {
381
- satelliteControllerRef.current = new SatelliteAndroidController(core, satelliteLayerRef);
382
- }
383
- return satelliteControllerRef.current;
384
- }, [core]);
385
- useEffect(() => {
386
- if (!SATELLITE_NATIVE) return;
387
- let gridCmdKeys = [];
388
- let satCmdKeys = [];
205
+ }, [J]), j(() => {
206
+ st(!!(t.state.isNexrad && t.state.nexradShowSitesPicker !== !1));
207
+ }, [t]);
208
+ const p = V(null),
209
+ rt = V(null),
210
+ X = V(null),
211
+ Ne = V(null),
212
+ re = V(null),
213
+ De = V(null),
214
+ me = V(null),
215
+ at = we(() => ie ? (re.current || (re.current = new Rt(t, Ne)), re.current) : null, [t]),
216
+ nt = we(() => !Q || !t ? null : (X.current || (X.current = new Ft(t, rt, {
217
+ interpolateNexradColormap: t.state?.shaderSmoothingEnabled !== !1
218
+ })), X.current), [t]),
219
+ ht = we(r => {
220
+ const {
221
+ colormap: a,
222
+ baseUnit: e
223
+ } = t._getColormapForVariable(r.variable),
224
+ o = t._getTargetUnit(e, r.units);
225
+ return {
226
+ ...r,
227
+ colormap: t._convertColormapUnits(a, e, o),
228
+ colormapBaseUnit: o
229
+ };
230
+ }, [t]),
231
+ Ie = we(r => {
232
+ if (!Q || !r?.isNexrad) return;
233
+ const a = nt();
234
+ a && (ae.current = !0, a.preloadAllAvailable(r), a.sync(r));
235
+ }, [nt]);
236
+ j(() => {
237
+ if (!Q || !t) return;
238
+ const r = wt(te, t),
239
+ a = At(() => ({
240
+ apiKey: t.apiKey,
241
+ bundleId: t.bundleId,
242
+ gridRequestSiteOrigin: r
243
+ }));
244
+ return dt(a), () => dt(null);
245
+ }, [t, te]), j(() => {
246
+ if (!ie) return;
247
+ let r = [],
248
+ a = [];
389
249
  try {
390
- gridCmdKeys = Object.keys(UIManager.getViewManagerConfig?.('GridRenderLayer')?.Commands ?? {});
250
+ r = Object.keys(mt.getViewManagerConfig?.("GridRenderLayer")?.Commands ?? {});
391
251
  } catch {
392
- gridCmdKeys = ['error'];
252
+ r = ["error"];
393
253
  }
394
254
  try {
395
- satCmdKeys = Object.keys(UIManager.getViewManagerConfig?.('SatelliteLayer')?.Commands ?? {});
255
+ a = Object.keys(mt.getViewManagerConfig?.("SatelliteLayer")?.Commands ?? {});
396
256
  } catch {
397
- satCmdKeys = ['error'];
257
+ a = ["error"];
398
258
  }
399
- satBridgeWarn('mount UIManager command registration', {
400
- GridRenderLayerCommands: gridCmdKeys,
401
- SatelliteLayerCommands: satCmdKeys,
402
- satelliteMissing: satCmdKeys.length === 0
259
+ Ee("mount UIManager command registration", {
260
+ GridRenderLayerCommands: r,
261
+ SatelliteLayerCommands: a,
262
+ satelliteMissing: a.length === 0
403
263
  });
404
264
  }, []);
405
- useEffect(() => {
406
- const ctl = nexradControllerRef.current;
407
- if (NEXRAD_NATIVE && ctl) {
408
- ctl.updateStyleOptions({
409
- interpolateNexradColormap,
410
- nexradGateSmoothing
411
- });
412
- if (core?.state?.isNexrad) {
413
- ctl.applyStyleFromState(core.state);
265
+ const W = V(new Map()),
266
+ pe = V(null),
267
+ ge = V(null),
268
+ ke = V([0, 1]),
269
+ ae = V(!1),
270
+ ne = V(!1),
271
+ Le = V(0),
272
+ He = V(null),
273
+ l = V(null),
274
+ [Ve, Me] = Je({
275
+ opacity: 1,
276
+ dataRange: [0, 1]
277
+ }),
278
+ [St, st] = Je(!1);
279
+ Mt(x, () => ({
280
+ play: () => {
281
+ t.play();
282
+ },
283
+ pause: () => {
284
+ t.pause();
285
+ },
286
+ togglePlay: () => {
287
+ t.togglePlay();
288
+ },
289
+ step: r => {
290
+ t.step(r);
291
+ },
292
+ setPlaybackSpeed: r => {
293
+ r > 0 && (t.playbackSpeed = r, t.isPlaying && (t.pause(), t.play()));
294
+ },
295
+ setOpacity: r => t.setOpacity(r),
296
+ setUnits: r => t.setUnits(r),
297
+ switchMode: r => t.switchMode(r),
298
+ getAvailableVariables: r => t.getAvailableVariables(r),
299
+ getVariableDisplayName: r => t.getVariableDisplayName(r),
300
+ setRun: r => t.setState({
301
+ run: r.split(":")[1]
302
+ }),
303
+ setState: r => t.setState(r),
304
+ setMRMSTimestamp: r => t.setMRMSTimestamp(r),
305
+ setMRMSDurationValue: r => qt(t, r),
306
+ setNexradSite: r => t.setNexradSite(r),
307
+ setNexradProduct: r => t.setNexradProduct(r),
308
+ setNexradTilt: r => t.setNexradTilt(r),
309
+ setNexradStormRelative: r => t.setNexradStormRelative(r),
310
+ setNexradTimestamp: r => t.setNexradTimestamp(r),
311
+ setNexradDurationValue: r => typeof t.setNexradDurationValue == "function" ? t.setNexradDurationValue(r) : t.setState({
312
+ nexradDurationValue: ct(r)
313
+ }),
314
+ setSatelliteTimestamp: r => t.setSatelliteTimestamp(r),
315
+ setSatelliteDurationValue: r => t.setSatelliteDurationValue(r),
316
+ setSatelliteSelection: r => t.setSatelliteSelection(r),
317
+ setShaderSmoothing: async r => {
318
+ await t.setShaderSmoothing(r), p.current && p.current.setSmoothing(r);
319
+ },
320
+ setSmoothing: r => {
321
+ p.current && p.current.setSmoothing(r);
322
+ },
323
+ setAutoRefresh: (r, a) => {
324
+ if (me.current && (clearInterval(me.current), me.current = null), r) {
325
+ const e = (a || xe || 30) * 1e3;
326
+ Se(), me.current = setInterval(Se, e);
414
327
  }
328
+ },
329
+ refreshData: () => {
330
+ Se();
331
+ },
332
+ configureWatchesWarnings: r => {
333
+ tt(a => ({
334
+ ...a,
335
+ ...r
336
+ }));
415
337
  }
416
- }, [interpolateNexradColormap, nexradGateSmoothing, core]);
417
-
418
- // Cache for preloaded grid data - stores the processed data ready for GPU upload
419
- const preloadedDataCache = useRef(new Map());
420
-
421
- // Store geometry and colormap that don't change with forecast hour
422
- const cachedGeometry = useRef(null);
423
- const cachedColormap = useRef(null);
424
- const cachedDataRange = useRef([0, 1]);
425
-
426
- // Track if we've done the initial load
427
- const hasInitialLoad = useRef(false);
428
- const hasPreloadedRef = useRef(false);
429
- /** Bumped on {@code cancelAllFrames} / full reload so stale {@code processFrame} results are ignored. */
430
- const preloadGenerationRef = useRef(0);
431
-
432
- // Track the last state we processed to avoid redundant updates
433
- const lastProcessedState = useRef(null);
434
- const previousStateRef = useRef(null);
435
- const [renderProps, setRenderProps] = useState({
436
- opacity: 1,
437
- dataRange: [0, 1]
438
- });
439
- /** Drives {@link NexradSitesMapLayer}; must re-render when core NEXRAD / picker flags change. */
440
- const [nexradSitesMapVisible, setNexradSitesMapVisible] = useState(false);
441
- useImperativeHandle(ref, () => {
442
- const setAutoRefresh = (enabled, intervalSeconds) => {
443
- if (autoRefreshIntervalId.current) {
444
- clearInterval(autoRefreshIntervalId.current);
445
- autoRefreshIntervalId.current = null;
446
- }
447
- if (enabled) {
448
- const effectiveInterval = (intervalSeconds || autoRefreshInterval || 30) * 1000;
449
- // Run once immediately, then start the interval
450
- _checkForUpdates();
451
- autoRefreshIntervalId.current = setInterval(_checkForUpdates, effectiveInterval);
452
- }
453
- };
454
- return {
455
- play: () => {
456
- core.play();
457
- },
458
- pause: () => {
459
- core.pause();
460
- },
461
- togglePlay: () => {
462
- core.togglePlay();
463
- },
464
- step: direction => {
465
- core.step(direction);
466
- },
467
- setPlaybackSpeed: speed => {
468
- if (speed > 0) {
469
- core.playbackSpeed = speed;
470
- if (core.isPlaying) {
471
- core.pause();
472
- core.play();
473
- }
474
- }
475
- },
476
- setOpacity: opacity => core.setOpacity(opacity),
477
- setUnits: units => core.setUnits(units),
478
- switchMode: options => core.switchMode(options),
479
- getAvailableVariables: model => core.getAvailableVariables(model),
480
- getVariableDisplayName: code => core.getVariableDisplayName(code),
481
- setRun: runString => core.setState({
482
- run: runString.split(':')[1]
483
- }),
484
- setState: newState => core.setState(newState),
485
- setMRMSTimestamp: timestamp => core.setMRMSTimestamp(timestamp),
486
- setMRMSDurationValue: value => applyMrmsDurationValue(core, value),
487
- setNexradSite: siteId => core.setNexradSite(siteId),
488
- setNexradProduct: product => core.setNexradProduct(product),
489
- setNexradTilt: tilt => core.setNexradTilt(tilt),
490
- setNexradStormRelative: enabled => core.setNexradStormRelative(enabled),
491
- setNexradTimestamp: ts => core.setNexradTimestamp(ts),
492
- setNexradDurationValue: value => applyNexradDurationValue(core, value),
493
- setSatelliteTimestamp: timestamp => core.setSatelliteTimestamp(timestamp),
494
- setSatelliteDurationValue: value => core.setSatelliteDurationValue(value),
495
- setSatelliteSelection: opts => core.setSatelliteSelection(opts),
496
- setShaderSmoothing: async enabled => {
497
- await core.setShaderSmoothing(enabled);
498
- if (gridLayerRef.current) {
499
- gridLayerRef.current.setSmoothing(enabled);
500
- }
501
- },
502
- setSmoothing: enabled => {
503
- if (gridLayerRef.current) {
504
- gridLayerRef.current.setSmoothing(enabled);
505
- }
506
- },
507
- setAutoRefresh,
508
- refreshData: () => {
509
- _checkForUpdates();
510
- },
511
- /**
512
- * NWS watches/warnings (native map, iOS + Android): same options as mapsgl {@link WeatherLayerManager#configureWatchesWarnings}.
513
- * @param {object} partial
514
- */
515
- configureWatchesWarnings: partial => {
516
- setWatchesWarningsOptions(prev => ({
517
- ...prev,
518
- ...partial
519
- }));
520
- }
521
- };
522
- }, [core, autoRefreshInterval, _checkForUpdates]);
523
- const preloadAllFramesToDisk = async state => {
524
- if (state.isNexrad || state.isSatellite) {
525
- hasPreloadedRef.current = false;
526
- wxGridVerbose('preloadSkip', {
527
- reason: 'nexrad_or_satellite'
338
+ }), [t, xe, Se]);
339
+ const it = async r => {
340
+ if (r.isNexrad || r.isSatellite) {
341
+ ne.current = !1, z("preloadSkip", {
342
+ reason: "nexrad_or_satellite"
528
343
  });
529
344
  return;
530
345
  }
531
- if (hasPreloadedRef.current) {
532
- wxGridVerbose('preloadSkip', {
533
- reason: 'hasPreloadedRef_gate',
534
- isMRMS: state.isMRMS,
535
- variable: state.variable
346
+ if (ne.current) {
347
+ z("preloadSkip", {
348
+ reason: "hasPreloadedRef_gate",
349
+ isMRMS: r.isMRMS,
350
+ variable: r.variable
536
351
  });
537
352
  return;
538
353
  }
539
354
  const {
540
- isMRMS,
541
- model,
542
- date,
543
- run,
544
- variable,
545
- units,
546
- availableHours,
547
- availableTimestamps,
548
- forecastHour,
549
- mrmsTimestamp
550
- } = state;
551
-
552
- // CRITICAL: Don't start preloading if we don't have a valid current frame
553
- if (isMRMS && (mrmsTimestamp == null || !availableTimestamps || availableTimestamps.length === 0)) {
554
- hasPreloadedRef.current = false;
555
- wxGridWarn('preloadAbort', {
556
- reason: 'mrms_missing_frame_or_timestamps',
557
- mrmsTimestamp,
558
- timestampCount: availableTimestamps?.length ?? 0,
559
- variable
355
+ isMRMS: a,
356
+ model: e,
357
+ date: o,
358
+ run: F,
359
+ variable: s,
360
+ units: w,
361
+ availableHours: N,
362
+ availableTimestamps: c,
363
+ forecastHour: i,
364
+ mrmsTimestamp: u
365
+ } = r;
366
+ if (a && (u == null || !c || c.length === 0)) {
367
+ ne.current = !1, Z("preloadAbort", {
368
+ reason: "mrms_missing_frame_or_timestamps",
369
+ mrmsTimestamp: u,
370
+ timestampCount: c?.length ?? 0,
371
+ variable: s
560
372
  });
561
373
  return;
562
374
  }
563
- if (!isMRMS && (forecastHour == null || !availableHours || availableHours.length === 0)) {
564
- hasPreloadedRef.current = false;
565
- wxGridWarn('preloadAbort', {
566
- reason: 'model_missing_hour_or_hours',
567
- forecastHour,
568
- hourCount: availableHours?.length ?? 0,
569
- model,
570
- variable
375
+ if (!a && (i == null || !N || N.length === 0)) {
376
+ ne.current = !1, Z("preloadAbort", {
377
+ reason: "model_missing_hour_or_hours",
378
+ forecastHour: i,
379
+ hourCount: N?.length ?? 0,
380
+ model: e,
381
+ variable: s
571
382
  });
572
383
  return;
573
384
  }
574
-
575
- // Only mark as "has preloaded" after validation passes
576
- hasPreloadedRef.current = true;
577
- const generation = preloadGenerationRef.current;
578
- const isStaleGeneration = () => generation !== preloadGenerationRef.current;
579
- wxGridVerbose('preloadStart', {
580
- isMRMS,
581
- model,
582
- date,
583
- run,
584
- variable,
585
- mrmsTimestamp: isMRMS ? mrmsTimestamp : undefined,
586
- forecastHour: !isMRMS ? forecastHour : undefined,
587
- baseGridUrl: core?.baseGridUrl,
588
- hasApiKey: Boolean(core?.apiKey),
589
- bundleId: core?.bundleId ?? null,
590
- gridRequestSiteOrigin: gridRequestSiteOrigin || null
385
+ ne.current = !0;
386
+ const A = Le.current,
387
+ y = () => A !== Le.current;
388
+ z("preloadStart", {
389
+ isMRMS: a,
390
+ model: e,
391
+ date: o,
392
+ run: F,
393
+ variable: s,
394
+ mrmsTimestamp: a ? u : void 0,
395
+ forecastHour: a ? void 0 : i,
396
+ baseGridUrl: t?.baseGridUrl,
397
+ hasApiKey: !!t?.apiKey,
398
+ bundleId: t?.bundleId ?? null,
399
+ gridRequestSiteOrigin: te || null
591
400
  });
592
-
593
- // Fix the current forecast hour if it's invalid for this variable/model combo
594
- let effectiveForecastHour = forecastHour;
595
- if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
596
- const validHours = availableHours.filter(hour => hour !== 0);
597
- effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
401
+ let M = i;
402
+ if (!a && s === "ptypeRefl" && e === "hrrr" && i === 0) {
403
+ const d = N.filter(G => G !== 0);
404
+ M = d.length > 0 ? d[0] : 0;
598
405
  }
599
- if (!cachedGeometry.current || !cachedColormap.current) {
600
- const gridModel = isMRMS ? 'mrms' : model;
601
- const {
602
- corners,
603
- gridDef
604
- } = core._getGridCornersAndDef(gridModel);
605
- gridLayerRef.current.updateGeometry(corners, gridDef);
606
- cachedGeometry.current = {
607
- model: gridModel,
608
- variable
609
- };
610
- wxGridVerbose('geometryColormapInit', {
611
- gridModel,
612
- variable,
613
- nx: gridDef?.grid_params?.nx,
614
- ny: gridDef?.grid_params?.ny
406
+ if (!pe.current || !ge.current) {
407
+ const d = a ? "mrms" : e,
408
+ {
409
+ corners: G,
410
+ gridDef: n
411
+ } = t._getGridCornersAndDef(d);
412
+ p.current.updateGeometry(G, n), pe.current = {
413
+ model: d,
414
+ variable: s
415
+ }, z("geometryColormapInit", {
416
+ gridModel: d,
417
+ variable: s,
418
+ nx: n?.grid_params?.nx,
419
+ ny: n?.grid_params?.ny
615
420
  });
616
421
  const {
617
- colormap,
618
- baseUnit
619
- } = core._getColormapForVariable(variable);
620
- const toUnit = core._getTargetUnit(baseUnit, units);
621
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
622
- let dataRange;
623
- if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
624
- dataRange = isMRMS ? [5, 380] : [5, 380];
625
- } else {
626
- dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
627
- }
628
- const colormapBytes = _generateColormapBytes(finalColormap);
629
- const colormapAsBase64 = fromByteArray(colormapBytes);
630
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
631
- cachedColormap.current = {
632
- key: `${variable}-${units}`
633
- };
634
- cachedDataRange.current = dataRange;
635
- setRenderProps({
636
- opacity: state.opacity,
637
- dataRange: dataRange
638
- });
639
- hasInitialLoad.current = true;
422
+ colormap: R,
423
+ baseUnit: h
424
+ } = t._getColormapForVariable(s),
425
+ k = t._getTargetUnit(h, w),
426
+ P = t._convertColormapUnits(R, h, k);
427
+ let f;
428
+ s === "ptypeRefl" || s === "ptypeRate" ? f = a ? [5, 380] : [5, 380] : f = [P[0], P[P.length - 2]];
429
+ const C = et(P),
430
+ b = ze(C);
431
+ p.current.updateColormapTexture(b), ge.current = {
432
+ key: `${s}-${w}`
433
+ }, ke.current = f, Me({
434
+ opacity: r.opacity,
435
+ dataRange: f
436
+ }), ae.current = !0;
640
437
  }
641
-
642
- // Apply the same filtering logic as in AguaceroCore._emitStateChange
643
- let filteredHours = availableHours;
644
- if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && availableHours && availableHours.length > 0) {
645
- filteredHours = availableHours.filter(hour => hour !== 0);
646
- }
647
- const allFrames = isMRMS ? availableTimestamps : filteredHours;
648
- if (!allFrames || allFrames.length === 0) {
649
- hasPreloadedRef.current = false;
650
- wxGridWarn('preloadAbort', {
651
- reason: 'no_frames_after_filter',
652
- isMRMS,
653
- variable
438
+ let U = N;
439
+ !a && s === "ptypeRefl" && e === "hrrr" && N && N.length > 0 && (U = N.filter(d => d !== 0));
440
+ const E = a ? c : U;
441
+ if (!E || E.length === 0) {
442
+ ne.current = !1, Z("preloadAbort", {
443
+ reason: "no_frames_after_filter",
444
+ isMRMS: a,
445
+ variable: s
654
446
  });
655
447
  return;
656
448
  }
657
- const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
658
-
659
- // Double-check currentFrame is valid
660
- if (currentFrame == null) {
661
- hasPreloadedRef.current = false;
662
- wxGridWarn('preloadAbort', {
663
- reason: 'currentFrame_null',
664
- isMRMS,
665
- variable
449
+ const K = a ? u : M;
450
+ if (K == null) {
451
+ ne.current = !1, Z("preloadAbort", {
452
+ reason: "currentFrame_null",
453
+ isMRMS: a,
454
+ variable: s
666
455
  });
667
456
  return;
668
457
  }
669
-
670
- // Reverse the frame order to load from last to first
671
- const reversedFrames = [...allFrames].reverse();
672
- const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
673
- const {
674
- corners,
675
- gridDef
676
- } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
677
- const {
678
- nx,
679
- ny
680
- } = gridDef.grid_params;
681
-
682
- // Load the current frame FIRST and WAIT for it before continuing
683
- const currentCacheKey = isMRMS ? `mrms-${currentFrame}-${variable}` : `${model}-${date}-${run}-${currentFrame}-${variable}`;
684
- if (!preloadedDataCache.current.has(currentCacheKey)) {
685
- let resourcePath;
686
- if (isMRMS) {
687
- const frameDate = new Date(currentFrame * 1000);
688
- const y = frameDate.getUTCFullYear();
689
- const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
690
- const d = frameDate.getUTCDate().toString().padStart(2, '0');
691
- resourcePath = `/grids/mrms/${y}${m}${d}/${currentFrame}/0/${variable}/0`;
692
- } else {
693
- resourcePath = `/grids/${model}/${date}/${run}/${currentFrame}/${variable}/0`;
694
- }
695
- const options = augmentProcessFrameOptionsForDebug(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin, core), core);
696
- logProcessFrameAuthMismatch(core, options, {
697
- phase: 'preloadCurrent',
698
- currentCacheKey
458
+ const Y = [...E].reverse().filter(d => d !== K),
459
+ {
460
+ corners: D,
461
+ gridDef: q
462
+ } = t._getGridCornersAndDef(a ? "mrms" : e),
463
+ {
464
+ nx: de,
465
+ ny: ye
466
+ } = q.grid_params,
467
+ $ = a ? `mrms-${K}-${s}` : `${e}-${o}-${F}-${K}-${s}`;
468
+ if (!W.current.has($)) {
469
+ let d;
470
+ if (a) {
471
+ const n = new Date(K * 1e3),
472
+ R = n.getUTCFullYear(),
473
+ h = (n.getUTCMonth() + 1).toString().padStart(2, "0"),
474
+ k = n.getUTCDate().toString().padStart(2, "0");
475
+ d = `/grids/mrms/${R}${h}${k}/${K}/0/${s}/0`;
476
+ } else d = `/grids/${e}/${o}/${F}/${K}/${s}/0`;
477
+ const G = Xe(Ze(t.baseGridUrl, d, t.apiKey, t.bundleId, te, t), t);
478
+ Qe(t, G, {
479
+ phase: "preloadCurrent",
480
+ currentCacheKey: $
699
481
  });
700
482
  try {
701
- wxGridVerbose('processFrameRequest', {
702
- currentCacheKey,
703
- resourcePath,
704
- frame: currentFrame
483
+ z("processFrameRequest", {
484
+ currentCacheKey: $,
485
+ resourcePath: d,
486
+ frame: K
705
487
  });
706
- const result = await WeatherFrameProcessorModule.processFrame(options);
707
- if (isStaleGeneration()) {
708
- wxGridVerbose('preloadCurrentFrameStale', {
709
- currentCacheKey,
710
- generation
488
+ const n = await qe.processFrame(G);
489
+ if (y()) {
490
+ z("preloadCurrentFrameStale", {
491
+ currentCacheKey: $,
492
+ generation: A
711
493
  });
712
494
  return;
713
495
  }
714
- if (!result || !result.filePath) {
715
- hasPreloadedRef.current = false;
716
- wxGridWarn('preloadAbort', {
717
- reason: 'processFrame_empty_result',
718
- currentCacheKey,
719
- resultKeys: result ? Object.keys(result) : []
496
+ if (!n || !n.filePath) {
497
+ ne.current = !1, Z("preloadAbort", {
498
+ reason: "processFrame_empty_result",
499
+ currentCacheKey: $,
500
+ resultKeys: n ? Object.keys(n) : []
720
501
  });
721
502
  return;
722
503
  }
723
504
  const {
724
- baseUnit
725
- } = core._getColormapForVariable(variable);
726
- const toUnit = core._getTargetUnit(baseUnit, units);
727
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
728
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
729
- let dataScale = result.scale;
730
- let dataOffset = result.offset;
731
- let convertedScale = dataScale;
732
- let convertedOffset = dataOffset;
733
- if (serverDataUnit !== baseUnit) {
734
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
735
- if (conversionFunc) {
736
- if (result.scaleType === 'sqrt') {
737
- const physicalAtOffset = dataOffset * dataOffset;
738
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
739
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
740
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
741
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
742
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
743
- convertedScale = newOffsetPlusScale - convertedOffset;
744
- } else {
745
- convertedOffset = conversionFunc(dataOffset);
746
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
747
- convertedScale = convertedOffsetPlusScale - convertedOffset;
748
- }
749
- dataScale = convertedScale;
750
- dataOffset = convertedOffset;
505
+ baseUnit: R
506
+ } = t._getColormapForVariable(s),
507
+ h = t._getTargetUnit(R, w),
508
+ k = (Be?.fld?.[s] || {}).defaultUnit || R;
509
+ let P = n.scale,
510
+ f = n.offset,
511
+ C = P,
512
+ b = f;
513
+ if (k !== R) {
514
+ const T = ve(k, R);
515
+ if (T) {
516
+ if (n.scaleType === "sqrt") {
517
+ const L = f * f,
518
+ H = (f + P) * (f + P),
519
+ oe = T(L),
520
+ ce = T(H);
521
+ b = Math.sqrt(Math.abs(oe)) * Math.sign(oe), C = Math.sqrt(Math.abs(ce)) * Math.sign(ce) - b;
522
+ } else b = T(f), C = T(f + P) - b;
523
+ P = C, f = b;
751
524
  }
752
525
  }
753
- if (baseUnit !== toUnit) {
754
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
755
- if (conversionFunc) {
756
- if (result.scaleType === 'sqrt') {
757
- const physicalAtOffset = dataOffset * dataOffset;
758
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
759
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
760
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
761
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
762
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
763
- convertedScale = newOffsetPlusScale - convertedOffset;
764
- } else {
765
- convertedOffset = conversionFunc(dataOffset);
766
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
767
- convertedScale = convertedOffsetPlusScale - convertedOffset;
768
- }
769
- }
526
+ if (R !== h) {
527
+ const T = ve(R, h);
528
+ if (T) if (n.scaleType === "sqrt") {
529
+ const L = f * f,
530
+ H = (f + P) * (f + P),
531
+ oe = T(L),
532
+ ce = T(H);
533
+ b = Math.sqrt(Math.abs(oe)) * Math.sign(oe), C = Math.sqrt(Math.abs(ce)) * Math.sign(ce) - b;
534
+ } else b = T(f), C = T(f + P) - b;
770
535
  }
771
- const frameData = {
772
- filePath: result.filePath,
773
- nx,
774
- ny,
775
- scale: convertedScale,
776
- offset: convertedOffset,
777
- missing: result.missing,
778
- corners,
779
- gridDef,
780
- scaleType: result.scaleType,
781
- originalScale: result.scale,
782
- originalOffset: result.offset
783
- };
784
- preloadedDataCache.current.set(currentCacheKey, frameData);
785
-
786
- // Update the GPU with the current frame
787
- gridLayerRef.current.updateDataTextureFromFile(frameData.filePath, frameData.nx, frameData.ny, frameData.scale, frameData.offset, frameData.missing, frameData.scaleType);
788
- currentGridDataRef.current = {
789
- nx: frameData.nx,
790
- ny: frameData.ny,
791
- scale: frameData.scale,
792
- offset: frameData.offset,
793
- missing: frameData.missing,
794
- gridDef: frameData.gridDef,
795
- variable: variable,
796
- units: units,
797
- scaleType: frameData.scaleType
536
+ const S = {
537
+ filePath: n.filePath,
538
+ nx: de,
539
+ ny: ye,
540
+ scale: C,
541
+ offset: b,
542
+ missing: n.missing,
543
+ corners: D,
544
+ gridDef: q,
545
+ scaleType: n.scaleType,
546
+ originalScale: n.scale,
547
+ originalOffset: n.offset
798
548
  };
799
- wxGridVerbose('preloadCurrentFrameOk', {
800
- currentCacheKey,
801
- nx: frameData.nx,
802
- ny: frameData.ny,
803
- scale: frameData.scale,
804
- offset: frameData.offset,
805
- filePathSuffix: String(frameData.filePath).split('/').pop()
549
+ W.current.set($, S), p.current.updateDataTextureFromFile(S.filePath, S.nx, S.ny, S.scale, S.offset, S.missing, S.scaleType), De.current = {
550
+ nx: S.nx,
551
+ ny: S.ny,
552
+ scale: S.scale,
553
+ offset: S.offset,
554
+ missing: S.missing,
555
+ gridDef: S.gridDef,
556
+ variable: s,
557
+ units: w,
558
+ scaleType: S.scaleType
559
+ }, z("preloadCurrentFrameOk", {
560
+ currentCacheKey: $,
561
+ nx: S.nx,
562
+ ny: S.ny,
563
+ scale: S.scale,
564
+ offset: S.offset,
565
+ filePathSuffix: String(S.filePath).split("/").pop()
806
566
  });
807
- } catch (e) {
808
- const cancelled = e && (e.code === 'E_CANCELLED' || e?.userInfo?.code === 'E_CANCELLED' || typeof e?.message === 'string' && e.message.includes('superseded'));
809
- if (!cancelled) {
810
- hasPreloadedRef.current = false;
811
- const errDetail = {
812
- currentCacheKey,
813
- code: e?.code,
814
- message: e?.message,
815
- userInfo: e?.userInfo
567
+ } catch (n) {
568
+ if (n && (n.code === "E_CANCELLED" || n?.userInfo?.code === "E_CANCELLED" || typeof n?.message == "string" && n.message.includes("superseded"))) z("preloadProcessFrameCancelled", {
569
+ currentCacheKey: $
570
+ });else {
571
+ ne.current = !1;
572
+ const R = {
573
+ currentCacheKey: $,
574
+ code: n?.code,
575
+ message: n?.message,
576
+ userInfo: n?.userInfo
816
577
  };
817
- wxGridWarn('preloadProcessFrameError', errDetail);
818
- if (isAguaceroRnDebugEnabled()) {
819
- aguaceroDebugWarn('preloadProcessFrameError', {
820
- ...errDetail,
821
- auth: getAguaceroAuthDiagnosticSnapshot(core),
822
- is403: e?.code === 'HTTP_ERROR' && typeof e?.message === 'string' && e.message.includes('403')
823
- });
824
- }
825
- } else {
826
- wxGridVerbose('preloadProcessFrameCancelled', {
827
- currentCacheKey
578
+ Z("preloadProcessFrameError", R), Ke() && Ye("preloadProcessFrameError", {
579
+ ...R,
580
+ auth: ft(t),
581
+ is403: n?.code === "HTTP_ERROR" && typeof n?.message == "string" && n.message.includes("403")
828
582
  });
829
583
  }
830
584
  }
831
585
  }
832
-
833
- // NOW preload the rest of the frames asynchronously
834
- framesToPreload.forEach(frame => {
835
- const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
836
- if (preloadedDataCache.current.has(cacheKey)) {
837
- return;
838
- }
839
- let resourcePath;
840
- if (isMRMS) {
841
- const frameDate = new Date(frame * 1000);
842
- const y = frameDate.getUTCFullYear();
843
- const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
844
- const d = frameDate.getUTCDate().toString().padStart(2, '0');
845
- resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${variable}/0`;
846
- } else {
847
- resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
848
- }
849
- const options = augmentProcessFrameOptionsForDebug(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin, core), core);
850
- logProcessFrameAuthMismatch(core, options, {
851
- phase: 'preloadBackground',
852
- cacheKey
853
- });
854
- WeatherFrameProcessorModule.processFrame(options).then(result => {
855
- if (isStaleGeneration()) {
856
- return;
857
- }
858
- if (!result || !result.filePath) {
859
- return;
860
- }
861
-
862
- // ADD: Same two-step conversion as the current frame
586
+ Y.forEach(d => {
587
+ const G = a ? `mrms-${d}-${s}` : `${e}-${o}-${F}-${d}-${s}`;
588
+ if (W.current.has(G)) return;
589
+ let n;
590
+ if (a) {
591
+ const h = new Date(d * 1e3),
592
+ k = h.getUTCFullYear(),
593
+ P = (h.getUTCMonth() + 1).toString().padStart(2, "0"),
594
+ f = h.getUTCDate().toString().padStart(2, "0");
595
+ n = `/grids/mrms/${k}${P}${f}/${d}/0/${s}/0`;
596
+ } else n = `/grids/${e}/${o}/${F}/${d}/${s}/0`;
597
+ const R = Xe(Ze(t.baseGridUrl, n, t.apiKey, t.bundleId, te, t), t);
598
+ Qe(t, R, {
599
+ phase: "preloadBackground",
600
+ cacheKey: G
601
+ }), qe.processFrame(R).then(h => {
602
+ if (y() || !h || !h.filePath) return;
863
603
  const {
864
- baseUnit
865
- } = core._getColormapForVariable(variable);
866
- const toUnit = core._getTargetUnit(baseUnit, units);
867
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
868
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
869
- let dataScale = result.scale;
870
- let dataOffset = result.offset;
871
- let convertedScale = dataScale;
872
- let convertedOffset = dataOffset;
873
-
874
- // Step 1: Convert from server unit to colormap base unit
875
- if (serverDataUnit !== baseUnit) {
876
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
877
- if (conversionFunc) {
878
- if (result.scaleType === 'sqrt') {
879
- const physicalAtOffset = dataOffset * dataOffset;
880
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
881
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
882
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
883
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
884
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
885
- convertedScale = newOffsetPlusScale - convertedOffset;
886
- } else {
887
- convertedOffset = conversionFunc(dataOffset);
888
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
889
- convertedScale = convertedOffsetPlusScale - convertedOffset;
890
- }
891
- dataScale = convertedScale;
892
- dataOffset = convertedOffset;
604
+ baseUnit: k
605
+ } = t._getColormapForVariable(s),
606
+ P = t._getTargetUnit(k, w),
607
+ f = (Be?.fld?.[s] || {}).defaultUnit || k;
608
+ let C = h.scale,
609
+ b = h.offset,
610
+ S = C,
611
+ T = b;
612
+ if (f !== k) {
613
+ const H = ve(f, k);
614
+ if (H) {
615
+ if (h.scaleType === "sqrt") {
616
+ const oe = b * b,
617
+ ce = (b + C) * (b + C),
618
+ Re = H(oe),
619
+ Fe = H(ce);
620
+ T = Math.sqrt(Math.abs(Re)) * Math.sign(Re), S = Math.sqrt(Math.abs(Fe)) * Math.sign(Fe) - T;
621
+ } else T = H(b), S = H(b + C) - T;
622
+ C = S, b = T;
893
623
  }
894
624
  }
895
-
896
- // Step 2: Convert from colormap base unit to target display unit
897
- if (baseUnit !== toUnit) {
898
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
899
- if (conversionFunc) {
900
- if (result.scaleType === 'sqrt') {
901
- const physicalAtOffset = dataOffset * dataOffset;
902
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
903
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
904
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
905
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
906
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
907
- convertedScale = newOffsetPlusScale - convertedOffset;
908
- } else {
909
- convertedOffset = conversionFunc(dataOffset);
910
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
911
- convertedScale = convertedOffsetPlusScale - convertedOffset;
912
- }
913
- }
625
+ if (k !== P) {
626
+ const H = ve(k, P);
627
+ if (H) if (h.scaleType === "sqrt") {
628
+ const oe = b * b,
629
+ ce = (b + C) * (b + C),
630
+ Re = H(oe),
631
+ Fe = H(ce);
632
+ T = Math.sqrt(Math.abs(Re)) * Math.sign(Re), S = Math.sqrt(Math.abs(Fe)) * Math.sign(Fe) - T;
633
+ } else T = H(b), S = H(b + C) - T;
914
634
  }
915
- const frameData = {
916
- filePath: result.filePath,
917
- nx,
918
- ny,
919
- scale: convertedScale,
920
- offset: convertedOffset,
921
- missing: result.missing,
922
- corners,
923
- gridDef,
924
- scaleType: result.scaleType,
925
- originalScale: result.scale,
926
- originalOffset: result.offset
635
+ const L = {
636
+ filePath: h.filePath,
637
+ nx: de,
638
+ ny: ye,
639
+ scale: S,
640
+ offset: T,
641
+ missing: h.missing,
642
+ corners: D,
643
+ gridDef: q,
644
+ scaleType: h.scaleType,
645
+ originalScale: h.scale,
646
+ originalOffset: h.offset
927
647
  };
928
- preloadedDataCache.current.set(cacheKey, frameData);
929
- if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
930
- const frameInfoForGpu = {
931
- [cacheKey]: {
932
- filePath: frameData.filePath,
933
- nx: frameData.nx,
934
- ny: frameData.ny,
935
- scale: frameData.scale,
936
- offset: frameData.offset,
937
- missing: frameData.missing,
938
- scaleType: frameData.scaleType || 'linear',
939
- originalScale: frameData.originalScale,
940
- originalOffset: frameData.originalOffset
648
+ if (W.current.set(G, L), se.OS === "ios" && p.current.primeGpuCache) {
649
+ const H = {
650
+ [G]: {
651
+ filePath: L.filePath,
652
+ nx: L.nx,
653
+ ny: L.ny,
654
+ scale: L.scale,
655
+ offset: L.offset,
656
+ missing: L.missing,
657
+ scaleType: L.scaleType || "linear",
658
+ originalScale: L.originalScale,
659
+ originalOffset: L.originalOffset
941
660
  }
942
661
  };
943
- gridLayerRef.current.primeGpuCache(frameInfoForGpu);
944
- }
945
- }).catch(e => {
946
- const cancelled = e && (e.code === 'E_CANCELLED' || e?.userInfo?.code === 'E_CANCELLED' || typeof e?.message === 'string' && e.message.includes('superseded'));
947
- if (!cancelled) {
948
- wxGridWarn('backgroundFrameError', {
949
- cacheKey,
950
- code: e?.code,
951
- message: e?.message
952
- });
662
+ p.current.primeGpuCache(H);
953
663
  }
664
+ }).catch(h => {
665
+ h && (h.code === "E_CANCELLED" || h?.userInfo?.code === "E_CANCELLED" || typeof h?.message == "string" && h.message.includes("superseded")) || Z("backgroundFrameError", {
666
+ cacheKey: G,
667
+ code: h?.code,
668
+ message: h?.message
669
+ });
954
670
  });
955
671
  });
956
672
  };
957
- useEffect(() => {
958
- // This effect manages the auto-refresh based on props
959
- if (autoRefresh) {
960
- const interval = (autoRefreshInterval || 30) * 1000;
961
- _checkForUpdates(); // Run immediately on enable
962
- autoRefreshIntervalId.current = setInterval(_checkForUpdates, interval);
673
+ j(() => {
674
+ if (Pe) {
675
+ const r = (xe || 30) * 1e3;
676
+ Se(), me.current = setInterval(Se, r);
963
677
  }
964
-
965
- // Cleanup function: this runs when the component unmounts or props change
966
678
  return () => {
967
- if (autoRefreshIntervalId.current) {
968
- clearInterval(autoRefreshIntervalId.current);
969
- autoRefreshIntervalId.current = null;
970
- }
679
+ me.current && (clearInterval(me.current), me.current = null);
971
680
  };
972
- }, [autoRefresh, autoRefreshInterval, _checkForUpdates]);
973
- const updateGPUWithCachedData = state => {
974
- const {
975
- model,
976
- date,
977
- run,
978
- forecastHour,
979
- variable,
980
- units,
981
- isMRMS,
982
- mrmsTimestamp
983
- } = state;
984
- const cacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
985
- if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
986
- // Get the cached data BEFORE calling setActiveFrame
987
- const cachedData = preloadedDataCache.current.get(cacheKey);
988
- if (cachedData) {
989
- currentGridDataRef.current = {
990
- nx: cachedData.nx,
991
- ny: cachedData.ny,
992
- scale: cachedData.scale,
993
- offset: cachedData.offset,
994
- missing: cachedData.missing,
995
- gridDef: cachedData.gridDef,
996
- variable: variable,
997
- units: units,
998
- scaleType: cachedData.scaleType
999
- };
1000
- } else {
1001
- wxGridVerbose('gpuIOS_setActiveFrame_no_row', {
1002
- cacheKey,
1003
- cacheSize: preloadedDataCache.current.size
1004
- });
1005
- }
1006
- gridLayerRef.current.setActiveFrame(cacheKey);
1007
- wxGridVerbose('gpuIOS_setActiveFrame', {
1008
- cacheKey,
1009
- hadCachedRow: Boolean(cachedData)
1010
- });
1011
- return true;
1012
- }
1013
- const cachedData = preloadedDataCache.current.get(cacheKey);
1014
- if (!cachedData) {
1015
- wxGridWarn('updateGPUNoCache', {
1016
- cacheKey,
1017
- cacheSize: preloadedDataCache.current.size,
1018
- sampleKeys: Array.from(preloadedDataCache.current.keys()).slice(0, 5)
1019
- });
1020
- return false;
1021
- }
1022
- if (!gridLayerRef.current) {
1023
- wxGridWarn('updateGPUNoGridLayerRef', {
1024
- cacheKey
1025
- });
1026
- return false;
1027
- }
1028
- if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
1029
- gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
1030
- cachedGeometry.current = {
1031
- model: isMRMS ? 'mrms' : model,
1032
- variable
1033
- };
1034
- }
1035
- const colormapKey = `${variable}-${units}`;
1036
- if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
681
+ }, [Pe, xe, Se]);
682
+ const yt = r => {
1037
683
  const {
1038
- colormap,
1039
- baseUnit
1040
- } = core._getColormapForVariable(variable);
1041
- const toUnit = core._getTargetUnit(baseUnit, units);
1042
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
1043
- let dataRange;
1044
- if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
1045
- if (isMRMS) {
1046
- dataRange = [5, 380];
1047
- } else {
1048
- dataRange = [5, 380];
1049
- }
1050
- } else {
1051
- dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
684
+ model: a,
685
+ date: e,
686
+ run: o,
687
+ forecastHour: F,
688
+ variable: s,
689
+ units: w,
690
+ isMRMS: N,
691
+ mrmsTimestamp: c
692
+ } = r,
693
+ i = N ? `mrms-${c}-${s}` : `${a}-${e}-${o}-${F}-${s}`;
694
+ if (se.OS === "ios" && p.current.setActiveFrame) {
695
+ const y = W.current.get(i);
696
+ return y ? De.current = {
697
+ nx: y.nx,
698
+ ny: y.ny,
699
+ scale: y.scale,
700
+ offset: y.offset,
701
+ missing: y.missing,
702
+ gridDef: y.gridDef,
703
+ variable: s,
704
+ units: w,
705
+ scaleType: y.scaleType
706
+ } : z("gpuIOS_setActiveFrame_no_row", {
707
+ cacheKey: i,
708
+ cacheSize: W.current.size
709
+ }), p.current.setActiveFrame(i), z("gpuIOS_setActiveFrame", {
710
+ cacheKey: i,
711
+ hadCachedRow: !!y
712
+ }), !0;
1052
713
  }
1053
- const colormapBytes = _generateColormapBytes(finalColormap);
1054
- const colormapAsBase64 = fromByteArray(colormapBytes);
1055
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
1056
- cachedColormap.current = {
1057
- key: colormapKey
1058
- };
1059
- cachedDataRange.current = dataRange;
1060
- setRenderProps(prev => ({
1061
- ...prev,
1062
- dataRange
1063
- }));
1064
- }
1065
- if (cachedData.filePath) {
1066
- gridLayerRef.current.updateDataTextureFromFile(cachedData.filePath, cachedData.nx, cachedData.ny, cachedData.scale, cachedData.offset, cachedData.missing, cachedData.scaleType);
1067
- currentGridDataRef.current = {
1068
- nx: cachedData.nx,
1069
- ny: cachedData.ny,
1070
- scale: cachedData.scale,
1071
- offset: cachedData.offset,
1072
- missing: cachedData.missing,
1073
- gridDef: cachedData.gridDef,
1074
- variable: variable,
1075
- units: units,
1076
- scaleType: cachedData.scaleType
1077
- };
1078
- wxGridVerbose('gpuUploadFromFile', {
1079
- cacheKey,
1080
- nx: cachedData.nx,
1081
- ny: cachedData.ny,
1082
- filePathSuffix: String(cachedData.filePath).split('/').pop()
714
+ const u = W.current.get(i);
715
+ if (!u) return Z("updateGPUNoCache", {
716
+ cacheKey: i,
717
+ cacheSize: W.current.size,
718
+ sampleKeys: Array.from(W.current.keys()).slice(0, 5)
719
+ }), !1;
720
+ if (!p.current) return Z("updateGPUNoGridLayerRef", {
721
+ cacheKey: i
722
+ }), !1;
723
+ (!pe.current || pe.current.model !== (N ? "mrms" : a) || pe.current.variable !== s) && (p.current.updateGeometry(u.corners, u.gridDef), pe.current = {
724
+ model: N ? "mrms" : a,
725
+ variable: s
1083
726
  });
1084
- } else {
1085
- wxGridWarn('updateGPUNoFilePath', {
1086
- cacheKey
1087
- });
1088
- return false;
1089
- }
1090
-
1091
- // Update inspector parameters for file-based data too
1092
- if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
1093
- gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
1094
- }
1095
- return true;
1096
- };
1097
- const handleStateChangeRef = useRef(null);
1098
- const debounceTimeoutRef = useRef(null);
1099
- useEffect(() => {
1100
- if (core && props.customColormaps) {
1101
- core.customColormaps = props.customColormaps;
1102
- // Trigger a re-render if we already have data loaded
1103
- if (hasInitialLoad.current) {
1104
- core._emitStateChange();
1105
- }
1106
- }
1107
- }, [core, props.customColormaps]);
1108
- const getValueAtPoint = async (lng, lat) => {
1109
- if (!core) {
1110
- return null;
1111
- }
1112
- if (NEXRAD_NATIVE && core.state?.isNexrad) {
1113
- return getNexradInspectPayloadAt(lng, lat);
1114
- }
1115
-
1116
- // ADD THIS: Check if we have valid data before attempting inspection
1117
- if (!currentGridDataRef.current) {
1118
- return null;
1119
- }
1120
- try {
1121
- const gridIndices = core._getGridIndexFromLngLat(lng, lat);
1122
- if (!gridIndices) return null;
1123
- const {
1124
- i,
1125
- j
1126
- } = gridIndices;
1127
- const value = await InspectorModule.getValueAtGridIndex(i, j);
1128
- if (value === null) {
1129
- return null;
1130
- }
1131
- const {
1132
- colormap,
1133
- baseUnit
1134
- } = core._getColormapForVariable(core.state.variable);
1135
- const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
1136
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
1137
- const minThreshold = finalColormap[0];
1138
- if (value < minThreshold) {
1139
- return null;
727
+ const A = `${s}-${w}`;
728
+ if (!ge.current || ge.current.key !== A) {
729
+ const {
730
+ colormap: y,
731
+ baseUnit: M
732
+ } = t._getColormapForVariable(s),
733
+ U = t._getTargetUnit(M, w),
734
+ E = t._convertColormapUnits(y, M, U);
735
+ let K;
736
+ s === "ptypeRefl" || s === "ptypeRate" ? N ? K = [5, 380] : K = [5, 380] : K = [E[0], E[E.length - 2]];
737
+ const Y = et(E),
738
+ D = ze(Y);
739
+ p.current.updateColormapTexture(D), ge.current = {
740
+ key: A
741
+ }, ke.current = K, Me(q => ({
742
+ ...q,
743
+ dataRange: K
744
+ }));
1140
745
  }
1141
-
1142
- // Filter out values below the minimum threshold (matching shader behavior)
1143
- if (value < minThreshold) {
1144
- return null;
746
+ if (u.filePath) p.current.updateDataTextureFromFile(u.filePath, u.nx, u.ny, u.scale, u.offset, u.missing, u.scaleType), De.current = {
747
+ nx: u.nx,
748
+ ny: u.ny,
749
+ scale: u.scale,
750
+ offset: u.offset,
751
+ missing: u.missing,
752
+ gridDef: u.gridDef,
753
+ variable: s,
754
+ units: w,
755
+ scaleType: u.scaleType
756
+ }, z("gpuUploadFromFile", {
757
+ cacheKey: i,
758
+ nx: u.nx,
759
+ ny: u.ny,
760
+ filePathSuffix: String(u.filePath).split("/").pop()
761
+ });else return Z("updateGPUNoFilePath", {
762
+ cacheKey: i
763
+ }), !1;
764
+ return p.current && p.current.updateDataParameters && p.current.updateDataParameters(u.scale, u.offset, u.missing), !0;
765
+ },
766
+ he = V(null),
767
+ le = V(null);
768
+ j(() => {
769
+ t && m.customColormaps && (t.customColormaps = m.customColormaps, ae.current && t._emitStateChange());
770
+ }, [t, m.customColormaps]);
771
+ const lt = async (r, a) => {
772
+ if (!t) return null;
773
+ if (t.state?.isNexrad) {
774
+ const e = X.current;
775
+ return e ? e.getInspectPayload(r, a, ht(t.state)) : null;
1145
776
  }
1146
-
1147
- // Also check if value is NaN or effectively missing
1148
- if (!isFinite(value)) {
777
+ if (!De.current) return null;
778
+ try {
779
+ const e = t._getGridIndexFromLngLat(r, a);
780
+ if (!e) return null;
781
+ const {
782
+ i: o,
783
+ j: F
784
+ } = e,
785
+ s = await kt.getValueAtGridIndex(o, F);
786
+ if (s === null) return null;
787
+ const {
788
+ colormap: w,
789
+ baseUnit: N
790
+ } = t._getColormapForVariable(t.state.variable),
791
+ c = t._getTargetUnit(N, t.state.units),
792
+ i = t._convertColormapUnits(w, N, c)[0];
793
+ return s < i || s < i || !isFinite(s) ? null : {
794
+ value: s,
795
+ unit: c,
796
+ variable: {
797
+ code: t.state.variable,
798
+ name: t.getVariableDisplayName(t.state.variable)
799
+ },
800
+ lngLat: {
801
+ lng: r,
802
+ lat: a
803
+ }
804
+ };
805
+ } catch {
1149
806
  return null;
1150
807
  }
1151
- return {
1152
- value: value,
1153
- unit: displayUnit,
1154
- variable: {
1155
- code: core.state.variable,
1156
- name: core.getVariableDisplayName(core.state.variable)
1157
- },
1158
- lngLat: {
1159
- lng,
1160
- lat
1161
- }
1162
- };
1163
- } catch {
1164
- return null;
1165
- }
1166
- };
1167
- const getValueAtPointRef = useRef(getValueAtPoint);
1168
- getValueAtPointRef.current = getValueAtPoint;
1169
- const getNexradInspectPayloadAtRef = useRef(getNexradInspectPayloadAt);
1170
- getNexradInspectPayloadAtRef.current = getNexradInspectPayloadAt;
1171
- const _checkForUpdates = useMemo(() => async () => {
1172
- if (!core) return;
1173
- const s = core.state;
1174
- const {
1175
- isMRMS,
1176
- isSatellite,
1177
- isNexrad,
1178
- model: currentModel,
1179
- variable: currentVariable,
1180
- date,
1181
- run
1182
- } = s;
1183
- if (isSatellite) {
1184
- const prevTimeline = core._computeSatelliteTimeline();
1185
- const prevTimes = [...(prevTimeline.unixTimes || [])].map(t => Number(t)).filter(t => !Number.isNaN(t)).sort((a, b) => a - b);
1186
- const prevMax = prevTimes.length ? prevTimes[prevTimes.length - 1] : null;
1187
- const curSat = s.satelliteTimestamp == null ? null : Number(s.satelliteTimestamp);
1188
- await core.fetchSatelliteListing(true);
1189
- core._emitStateChange();
1190
- const nextTimeline = core._computeSatelliteTimeline();
1191
- const nextTimes = [...(nextTimeline.unixTimes || [])].map(t => Number(t)).filter(t => !Number.isNaN(t)).sort((a, b) => a - b);
1192
- const newMax = nextTimes.length ? nextTimes[nextTimes.length - 1] : null;
1193
- if (prevMax != null && curSat != null && curSat === prevMax && newMax != null && newMax > prevMax) {
1194
- await core.setSatelliteTimestamp(newMax);
1195
- } else if (curSat != null && newMax != null && nextTimes.length && !nextTimes.includes(curSat)) {
1196
- await core.setSatelliteTimestamp(newMax);
1197
- }
808
+ },
809
+ We = V(lt);
810
+ We.current = lt;
811
+ const Se = ut(() => async () => {
812
+ if (!t) return;
813
+ const r = t.state,
814
+ {
815
+ isMRMS: a,
816
+ isSatellite: e,
817
+ isNexrad: o,
818
+ model: F,
819
+ variable: s,
820
+ date: w,
821
+ run: N
822
+ } = r;
823
+ if (e) {
824
+ const c = [...(t._computeSatelliteTimeline().unixTimes || [])].map(M => Number(M)).filter(M => !Number.isNaN(M)).sort((M, U) => M - U),
825
+ i = c.length ? c[c.length - 1] : null,
826
+ u = r.satelliteTimestamp == null ? null : Number(r.satelliteTimestamp);
827
+ await t.fetchSatelliteListing(!0), t._emitStateChange();
828
+ const A = [...(t._computeSatelliteTimeline().unixTimes || [])].map(M => Number(M)).filter(M => !Number.isNaN(M)).sort((M, U) => M - U),
829
+ y = A.length ? A[A.length - 1] : null;
830
+ i != null && u != null && u === i && y != null && y > i ? await t.setSatelliteTimestamp(y) : u != null && y != null && A.length && !A.includes(u) && (await t.setSatelliteTimestamp(y));
1198
831
  return;
1199
832
  }
1200
- if (isNexrad && s.nexradSite) {
1201
- const nk = core._nexradTimesCacheKey();
1202
- const rawBefore = nk ? core.nexradTimesByStation[nk]?.unixTimes : [];
1203
- const filteredBefore = core._getFilteredNexradTimestampsForVariable(rawBefore || []);
1204
- const prevMax = filteredBefore.length ? filteredBefore[filteredBefore.length - 1] : null;
1205
- const curNx = s.nexradTimestamp == null ? null : Number(s.nexradTimestamp);
1206
- await core.refreshNexradTimes();
1207
- const rawAfter = nk ? core.nexradTimesByStation[nk]?.unixTimes : [];
1208
- const filteredAfter = core._getFilteredNexradTimestampsForVariable(rawAfter || []);
1209
- const newMax = filteredAfter.length ? filteredAfter[filteredAfter.length - 1] : null;
1210
- if (prevMax != null && curNx != null && curNx === prevMax && newMax != null && newMax > prevMax) {
1211
- await core.setNexradTimestamp(newMax);
1212
- } else if (curNx != null && newMax != null && filteredAfter.length && !filteredAfter.includes(curNx)) {
1213
- await core.setNexradTimestamp(newMax);
1214
- }
833
+ if (o && r.nexradSite) {
834
+ const c = t._nexradTimesCacheKey(),
835
+ i = c ? t.nexradTimesByStation[c]?.unixTimes : [],
836
+ u = t._getFilteredNexradTimestampsForVariable(i || []),
837
+ A = u.length ? u[u.length - 1] : null,
838
+ y = r.nexradTimestamp == null ? null : Number(r.nexradTimestamp);
839
+ await t.refreshNexradTimes(), t._emitStateChange();
840
+ const M = c ? t.nexradTimesByStation[c]?.unixTimes : [],
841
+ U = t._getFilteredNexradTimestampsForVariable(M || []),
842
+ E = U.length ? U[U.length - 1] : null;
843
+ A != null && y != null && y === A && E != null && E > A ? await t.setNexradTimestamp(E) : y != null && E != null && U.length && !U.includes(y) && (await t.setNexradTimestamp(E));
1215
844
  return;
1216
845
  }
1217
- if (isMRMS) {
1218
- // --- MRMS LOGIC (Keep existing logic) ---
1219
- const oldTimestamps = new Set(core.mrmsStatus?.[currentVariable] || []);
1220
- const mrmsStatus = await core.fetchMRMSStatus(true);
1221
- const newTimestamps = mrmsStatus?.[currentVariable] || [];
1222
- if (newTimestamps.length === 0) return;
1223
- const newTimestampsToPreload = newTimestamps.filter(ts => !oldTimestamps.has(ts));
1224
- if (newTimestampsToPreload.length > 0) {
1225
- core.mrmsStatus = mrmsStatus;
1226
- core._emitStateChange(); // Update UI slider without changing selection
1227
-
1228
- // ... (Keep your existing preloading logic here) ...
1229
- const {
1230
- corners,
1231
- gridDef
1232
- } = core._getGridCornersAndDef('mrms');
846
+ if (a) {
847
+ const c = new Set(t.mrmsStatus?.[s] || []),
848
+ i = await t.fetchMRMSStatus(!0),
849
+ u = i?.[s] || [];
850
+ if (u.length === 0) return;
851
+ const A = u.filter(y => !c.has(y));
852
+ if (A.length > 0) {
853
+ t.mrmsStatus = i, t._emitStateChange();
1233
854
  const {
1234
- nx,
1235
- ny
1236
- } = gridDef.grid_params;
1237
- newTimestampsToPreload.forEach(frame => {
1238
- const cacheKey = `mrms-${frame}-${currentVariable}`;
1239
- if (preloadedDataCache.current.has(cacheKey)) return;
1240
- const frameDate = new Date(frame * 1000);
1241
- const y = frameDate.getUTCFullYear(),
1242
- m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0'),
1243
- d = frameDate.getUTCDate().toString().padStart(2, '0');
1244
- const resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${currentVariable}/0`;
1245
- const options = augmentProcessFrameOptionsForDebug(buildGridFrameProcessOptions(core.baseGridUrl, resourcePath, core.apiKey, core.bundleId, gridRequestSiteOrigin, core), core);
1246
- logProcessFrameAuthMismatch(core, options, {
1247
- phase: 'mrmsRefresh',
1248
- cacheKey
1249
- });
1250
- WeatherFrameProcessorModule.processFrame(options).then(result => {
1251
- if (!result || !result.filePath) return;
1252
- const frameData = {
1253
- filePath: result.filePath,
1254
- nx,
1255
- ny,
1256
- scale: result.scale,
1257
- offset: result.offset,
1258
- missing: result.missing,
1259
- corners,
1260
- gridDef,
1261
- scaleType: result.scaleType,
1262
- originalScale: result.scale,
1263
- originalOffset: result.offset
855
+ corners: y,
856
+ gridDef: M
857
+ } = t._getGridCornersAndDef("mrms"),
858
+ {
859
+ nx: U,
860
+ ny: E
861
+ } = M.grid_params;
862
+ A.forEach(Y => {
863
+ const D = `mrms-${Y}-${s}`;
864
+ if (W.current.has(D)) return;
865
+ const q = new Date(Y * 1e3),
866
+ de = q.getUTCFullYear(),
867
+ ye = (q.getUTCMonth() + 1).toString().padStart(2, "0"),
868
+ $ = q.getUTCDate().toString().padStart(2, "0"),
869
+ d = `/grids/mrms/${de}${ye}${$}/${Y}/0/${s}/0`,
870
+ G = Xe(Ze(t.baseGridUrl, d, t.apiKey, t.bundleId, te, t), t);
871
+ Qe(t, G, {
872
+ phase: "mrmsRefresh",
873
+ cacheKey: D
874
+ }), qe.processFrame(G).then(n => {
875
+ if (!n || !n.filePath) return;
876
+ const R = {
877
+ filePath: n.filePath,
878
+ nx: U,
879
+ ny: E,
880
+ scale: n.scale,
881
+ offset: n.offset,
882
+ missing: n.missing,
883
+ corners: y,
884
+ gridDef: M,
885
+ scaleType: n.scaleType,
886
+ originalScale: n.scale,
887
+ originalOffset: n.offset
1264
888
  };
1265
- preloadedDataCache.current.set(cacheKey, frameData);
1266
- if (Platform.OS === 'ios' && gridLayerRef.current?.primeGpuCache) {
1267
- gridLayerRef.current.primeGpuCache({
1268
- [cacheKey]: frameData
1269
- });
1270
- }
1271
- }).catch(e => {
1272
- const cancelled = e && (e.code === 'E_CANCELLED' || e?.userInfo?.code === 'E_CANCELLED' || typeof e?.message === 'string' && e.message.includes('superseded'));
1273
- if (!cancelled) {
1274
- wxGridWarn('mrmsRefreshFrameError', {
1275
- cacheKey,
1276
- code: e?.code,
1277
- message: e?.message
1278
- });
1279
- }
889
+ W.current.set(D, R), se.OS === "ios" && p.current?.primeGpuCache && p.current.primeGpuCache({
890
+ [D]: R
891
+ });
892
+ }).catch(n => {
893
+ n && (n.code === "E_CANCELLED" || n?.userInfo?.code === "E_CANCELLED" || typeof n?.message == "string" && n.message.includes("superseded")) || Z("mrmsRefreshFrameError", {
894
+ cacheKey: D,
895
+ code: n?.code,
896
+ message: n?.message
897
+ });
1280
898
  });
1281
899
  });
1282
- const newTimestampsSet = new Set(newTimestamps);
1283
- oldTimestamps.forEach(oldTs => {
1284
- if (!newTimestampsSet.has(oldTs)) {
1285
- const cacheKey = `mrms-${oldTs}-${currentVariable}`;
1286
- preloadedDataCache.current.delete(cacheKey);
900
+ const K = new Set(u);
901
+ c.forEach(Y => {
902
+ if (!K.has(Y)) {
903
+ const D = `mrms-${Y}-${s}`;
904
+ W.current.delete(D);
1287
905
  }
1288
906
  });
1289
907
  }
1290
908
  } else {
1291
- const previousStatus = core.modelStatus;
1292
- const modelStatus = await core.fetchModelStatus(true);
1293
- const statusChanged = JSON.stringify(previousStatus) !== JSON.stringify(modelStatus);
1294
- if (statusChanged) {
1295
- core._emitStateChange();
1296
- }
1297
- const latestRun = findLatestModelRun(modelStatus, currentModel);
1298
- if (!latestRun) return;
1299
- }
1300
- }, [core]);
1301
- useEffect(() => {
1302
- if (!core) {
1303
- return;
909
+ const c = t.modelStatus,
910
+ i = await t.fetchModelStatus(!0);
911
+ if (JSON.stringify(c) !== JSON.stringify(i) && t._emitStateChange(), !Gt(i, F)) return;
1304
912
  }
1305
- const handleStateChange = newState => {
1306
- if (!previousStateRef.current) {
1307
- previousStateRef.current = core.state;
1308
- }
1309
- const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
1310
- if (variableChanged && gridLayerRef.current?.setVariable) {
1311
- gridLayerRef.current.setVariable(newState.variable);
1312
- }
1313
- const stateKey = newState.isNexrad ? `nx-${newState.nexradSite}-${newState.nexradProduct}-${newState.nexradDataSource}-${newState.nexradTimestamp}-${newState.nexradTilt}-${newState.units}-${newState.model}-${newState.variable}-${newState.mrmsTimestamp}-${newState.forecastHour}-dur:${newState.nexradDurationValue ?? ''}-tl:${nexradObsTimelineSig(newState)}` : newState.isSatellite ? `sat-${newState.satelliteInstrumentId}-${newState.satelliteSectorLabel}-${newState.satelliteChannel}-${newState.satelliteTimestamp}-${newState.variable}-${newState.units}-${newState.opacity}-dur:${newState.satelliteDurationValue ?? ''}-tl:${satelliteObsTimelineSig(newState)}` : `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
1314
- const sameTimeline = newState.isNexrad ? newState.nexradTimestamp === previousStateRef.current?.nexradTimestamp && newState.nexradSite === previousStateRef.current?.nexradSite && newState.nexradProduct === previousStateRef.current?.nexradProduct && Number(newState.nexradTilt) === Number(previousStateRef.current?.nexradTilt) && newState.nexradDurationValue === previousStateRef.current?.nexradDurationValue && nexradObsTimelineSig(newState) === nexradObsTimelineSig(previousStateRef.current) : newState.isSatellite ? newState.satelliteTimestamp === previousStateRef.current?.satelliteTimestamp && newState.satelliteInstrumentId === previousStateRef.current?.satelliteInstrumentId && newState.satelliteSectorLabel === previousStateRef.current?.satelliteSectorLabel && newState.satelliteChannel === previousStateRef.current?.satelliteChannel && newState.satelliteDurationValue === previousStateRef.current?.satelliteDurationValue && satelliteObsTimelineSig(newState) === satelliteObsTimelineSig(previousStateRef.current) : newState.forecastHour === previousStateRef.current?.forecastHour && newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp;
1315
- const sameModeAnchor = newState.isSatellite ? newState.satelliteInstrumentId === previousStateRef.current?.satelliteInstrumentId && newState.satelliteSectorLabel === previousStateRef.current?.satelliteSectorLabel && newState.satelliteChannel === previousStateRef.current?.satelliteChannel : newState.model === previousStateRef.current?.model && newState.isMRMS === previousStateRef.current?.isMRMS;
1316
- const isOpacityOnlyChange = hasInitialLoad.current && newState.opacity !== renderProps.opacity && newState.variable === previousStateRef.current?.variable && sameTimeline && sameModeAnchor && newState.units === previousStateRef.current?.units;
1317
- const isPlayStateOnlyChange = hasInitialLoad.current && newState.isPlaying !== previousStateRef.current?.isPlaying && newState.variable === previousStateRef.current?.variable && sameTimeline && sameModeAnchor && newState.units === previousStateRef.current?.units && newState.opacity === previousStateRef.current?.opacity;
1318
- if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
1319
- previousStateRef.current = newState;
913
+ }, [t]);
914
+ j(() => {
915
+ if (!t) return;
916
+ const r = e => {
917
+ l.current || (l.current = t.state), (!l.current || e.variable !== l.current.variable) && p.current?.setVariable && p.current.setVariable(e.variable);
918
+ const o = e.isNexrad ? `nx-${e.nexradSite}-${e.nexradProduct}-${e.nexradDataSource}-${e.nexradTimestamp}-${e.nexradTilt}-${e.opacity}` : e.isSatellite ? `sat-${e.satelliteInstrumentId}-${e.satelliteSectorLabel}-${e.satelliteChannel}-${e.satelliteTimestamp}-${e.variable}-${e.units}-${e.opacity}-dur:${e.satelliteDurationValue ?? ""}-tl:${ue(e)}` : `${e.model}-${e.variable}-${e.date}-${e.run}-${e.forecastHour}-${e.units}-${e.mrmsTimestamp}`,
919
+ F = e.isNexrad ? e.nexradTimestamp === l.current?.nexradTimestamp && e.nexradSite === l.current?.nexradSite && e.nexradProduct === l.current?.nexradProduct && Number(e.nexradTilt) === Number(l.current?.nexradTilt) : e.isSatellite ? e.satelliteTimestamp === l.current?.satelliteTimestamp && e.satelliteInstrumentId === l.current?.satelliteInstrumentId && e.satelliteSectorLabel === l.current?.satelliteSectorLabel && e.satelliteChannel === l.current?.satelliteChannel && e.satelliteDurationValue === l.current?.satelliteDurationValue && ue(e) === ue(l.current) : e.forecastHour === l.current?.forecastHour && e.mrmsTimestamp === l.current?.mrmsTimestamp,
920
+ s = e.isSatellite ? e.satelliteInstrumentId === l.current?.satelliteInstrumentId && e.satelliteSectorLabel === l.current?.satelliteSectorLabel && e.satelliteChannel === l.current?.satelliteChannel : e.model === l.current?.model && e.isMRMS === l.current?.isMRMS,
921
+ w = ae.current && e.opacity !== Ve.opacity && e.variable === l.current?.variable && F && s && e.units === l.current?.units,
922
+ N = ae.current && e.isPlaying !== l.current?.isPlaying && e.variable === l.current?.variable && F && s && e.units === l.current?.units && e.opacity === l.current?.opacity;
923
+ if (!w && !N && He.current === o) {
924
+ l.current = e;
1320
925
  return;
1321
926
  }
1322
- if (wxGridDebugEnabled() && Platform.OS === 'ios' && (newState.isNexrad && previousStateRef.current?.isNexrad || newState.isSatellite && previousStateRef.current?.isSatellite)) {
1323
- const prev = previousStateRef.current;
1324
- if (newState.isNexrad && prev?.isNexrad) {
1325
- if (newState.nexradDurationValue !== prev.nexradDurationValue || nexradObsTimelineSig(newState) !== nexradObsTimelineSig(prev)) {
1326
- wxGridVerbose('iosNexradTimelineWindowChanged', {
1327
- duration: {
1328
- from: prev.nexradDurationValue,
1329
- to: newState.nexradDurationValue
1330
- },
1331
- timelineSig: {
1332
- from: nexradObsTimelineSig(prev),
1333
- to: nexradObsTimelineSig(newState)
1334
- },
1335
- willSyncNative: true
1336
- });
1337
- }
1338
- }
1339
- if (newState.isSatellite && prev?.isSatellite) {
1340
- if (newState.satelliteDurationValue !== prev.satelliteDurationValue || satelliteObsTimelineSig(newState) !== satelliteObsTimelineSig(prev)) {
1341
- wxGridVerbose('iosSatelliteTimelineWindowChanged', {
1342
- duration: {
1343
- from: prev.satelliteDurationValue,
1344
- to: newState.satelliteDurationValue
1345
- },
1346
- timelineSig: {
1347
- from: satelliteObsTimelineSig(prev),
1348
- to: satelliteObsTimelineSig(newState)
1349
- },
1350
- willSyncNative: true
1351
- });
1352
- }
1353
- }
1354
- }
1355
- if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
1356
- lastProcessedState.current = stateKey;
927
+ if (pt() && se.OS === "ios" && e.isSatellite && l.current?.isSatellite) {
928
+ const i = l.current;
929
+ e.isSatellite && i?.isSatellite && (e.satelliteDurationValue !== i.satelliteDurationValue || ue(e) !== ue(i)) && z("iosSatelliteTimelineWindowChanged", {
930
+ duration: {
931
+ from: i.satelliteDurationValue,
932
+ to: e.satelliteDurationValue
933
+ },
934
+ timelineSig: {
935
+ from: ue(i),
936
+ to: ue(e)
937
+ },
938
+ willSyncNative: !0
939
+ });
1357
940
  }
1358
- if (isOpacityOnlyChange) {
1359
- setRenderProps(prev => ({
1360
- ...prev,
1361
- opacity: newState.opacity
1362
- }));
1363
- if (NEXRAD_NATIVE && newState.isNexrad) {
1364
- nexradControllerRef.current?.applyStyleFromState?.(newState);
1365
- }
1366
- if (SATELLITE_NATIVE && newState.isSatellite) {
1367
- satelliteLayerRef.current?.updateSatelliteStyle?.(JSON.stringify({
1368
- visible: newState.visible !== false,
1369
- opacity: newState.opacity ?? 1,
1370
- fillSmoothing: 0
1371
- }));
1372
- }
1373
- previousStateRef.current = newState;
941
+ if (!w && !N && (He.current = o), w) {
942
+ Me(i => ({
943
+ ...i,
944
+ opacity: e.opacity
945
+ })), ie && e.isSatellite && Ne.current?.updateSatelliteStyle?.(JSON.stringify({
946
+ visible: e.visible !== !1,
947
+ opacity: e.opacity ?? 1,
948
+ fillSmoothing: 0
949
+ })), Q && e.isNexrad && Ie(e), l.current = e;
1374
950
  return;
1375
951
  }
1376
- if (isPlayStateOnlyChange) {
1377
- previousStateRef.current = newState;
952
+ if (N) {
953
+ l.current = e;
1378
954
  return;
1379
955
  }
1380
- const isUnitsOnlyChange = hasInitialLoad.current && newState.model === previousStateRef.current.model && newState.isMRMS === previousStateRef.current.isMRMS && newState.variable === previousStateRef.current.variable && newState.date === previousStateRef.current.date && newState.run === previousStateRef.current.run && (newState.isNexrad ? newState.nexradTimestamp === previousStateRef.current.nexradTimestamp && newState.nexradSite === previousStateRef.current.nexradSite && newState.nexradProduct === previousStateRef.current.nexradProduct : newState.forecastHour === previousStateRef.current.forecastHour && newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp) && newState.units !== previousStateRef.current.units;
1381
- if (isUnitsOnlyChange) {
1382
- if (NEXRAD_NATIVE && newState.isNexrad) {
1383
- setRenderProps(prev => ({
1384
- ...prev,
1385
- opacity: newState.opacity
1386
- }));
1387
- nexradControllerRef.current?.applyStyleFromState?.(newState);
1388
- previousStateRef.current = newState;
956
+ if (ae.current && e.model === l.current.model && e.isMRMS === l.current.isMRMS && e.variable === l.current.variable && e.date === l.current.date && e.run === l.current.run && (e.isNexrad ? e.nexradTimestamp === l.current.nexradTimestamp && e.nexradSite === l.current.nexradSite && e.nexradProduct === l.current.nexradProduct : e.forecastHour === l.current.forecastHour && e.mrmsTimestamp === l.current.mrmsTimestamp) && e.units !== l.current.units) {
957
+ if (Q && e.isNexrad) {
958
+ Me(q => ({
959
+ ...q,
960
+ opacity: e.opacity
961
+ })), Ie(e), l.current = e;
1389
962
  return;
1390
963
  }
1391
964
  const {
1392
- variable,
1393
- units,
1394
- isMRMS,
1395
- mrmsTimestamp,
1396
- model,
1397
- date,
1398
- run,
1399
- forecastHour
1400
- } = newState;
1401
- const oldCacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
1402
- const cachedData = preloadedDataCache.current.get(oldCacheKey);
1403
- if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
965
+ variable: i,
966
+ units: u,
967
+ isMRMS: A,
968
+ mrmsTimestamp: y,
969
+ model: M,
970
+ date: U,
971
+ run: E,
972
+ forecastHour: K
973
+ } = e,
974
+ Y = A ? `mrms-${y}-${i}` : `${M}-${U}-${E}-${K}-${i}`,
975
+ D = W.current.get(Y);
976
+ if (D && D.originalScale !== void 0 && D.originalOffset !== void 0) {
1404
977
  const {
1405
- baseUnit
1406
- } = core._getColormapForVariable(variable);
1407
- const toUnit = core._getTargetUnit(baseUnit, units);
1408
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
1409
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
1410
- let dataScale = cachedData.originalScale;
1411
- let dataOffset = cachedData.originalOffset;
1412
- if (serverDataUnit !== baseUnit) {
1413
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
1414
- if (conversionFunc) {
1415
- if (cachedData.scaleType === 'sqrt') {
1416
- const physicalAtOffset = dataOffset * dataOffset;
1417
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
1418
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
1419
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
1420
- const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
1421
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
1422
- dataScale = newOffsetPlusScale - newOffset;
1423
- dataOffset = newOffset;
1424
- } else {
1425
- const convertedOffset = conversionFunc(dataOffset);
1426
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
1427
- dataScale = convertedOffsetPlusScale - convertedOffset;
1428
- dataOffset = convertedOffset;
1429
- }
978
+ baseUnit: q
979
+ } = t._getColormapForVariable(i),
980
+ de = t._getTargetUnit(q, u),
981
+ ye = (Be?.fld?.[i] || {}).defaultUnit || q;
982
+ let $ = D.originalScale,
983
+ d = D.originalOffset;
984
+ if (ye !== q) {
985
+ const f = ve(ye, q);
986
+ if (f) if (D.scaleType === "sqrt") {
987
+ const C = d * d,
988
+ b = (d + $) * (d + $),
989
+ S = f(C),
990
+ T = f(b),
991
+ L = Math.sqrt(Math.abs(S)) * Math.sign(S);
992
+ $ = Math.sqrt(Math.abs(T)) * Math.sign(T) - L, d = L;
993
+ } else {
994
+ const C = f(d);
995
+ $ = f(d + $) - C, d = C;
1430
996
  }
1431
997
  }
1432
- if (baseUnit !== toUnit) {
1433
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
1434
- if (conversionFunc) {
1435
- if (cachedData.scaleType === 'sqrt') {
1436
- const physicalAtOffset = dataOffset * dataOffset;
1437
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
1438
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
1439
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
1440
- const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
1441
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
1442
- dataScale = newOffsetPlusScale - newOffset;
1443
- dataOffset = newOffset;
1444
- } else {
1445
- const convertedOffset = conversionFunc(dataOffset);
1446
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
1447
- dataScale = convertedOffsetPlusScale - convertedOffset;
1448
- dataOffset = convertedOffset;
1449
- }
998
+ if (q !== de) {
999
+ const f = ve(q, de);
1000
+ if (f) if (D.scaleType === "sqrt") {
1001
+ const C = d * d,
1002
+ b = (d + $) * (d + $),
1003
+ S = f(C),
1004
+ T = f(b),
1005
+ L = Math.sqrt(Math.abs(S)) * Math.sign(S);
1006
+ $ = Math.sqrt(Math.abs(T)) * Math.sign(T) - L, d = L;
1007
+ } else {
1008
+ const C = f(d);
1009
+ $ = f(d + $) - C, d = C;
1450
1010
  }
1451
1011
  }
1452
1012
  const {
1453
- colormap
1454
- } = core._getColormapForVariable(variable);
1455
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
1456
- let dataRange = variable === 'ptypeRefl' || variable === 'ptypeRate' ? [5, 380] : [finalColormap[0], finalColormap[finalColormap.length - 2]];
1457
- const colormapBytes = _generateColormapBytes(finalColormap);
1458
- const colormapAsBase64 = fromByteArray(colormapBytes);
1459
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
1460
- cachedColormap.current = {
1461
- key: `${variable}-${units}`
1462
- };
1463
- cachedDataRange.current = dataRange;
1464
- setRenderProps(prev => ({
1465
- ...prev,
1466
- dataRange,
1467
- opacity: newState.opacity
1468
- }));
1469
- if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
1470
- const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0;
1471
- gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue);
1013
+ colormap: G
1014
+ } = t._getColormapForVariable(i),
1015
+ n = t._convertColormapUnits(G, q, de);
1016
+ let R = i === "ptypeRefl" || i === "ptypeRate" ? [5, 380] : [n[0], n[n.length - 2]];
1017
+ const h = et(n),
1018
+ k = ze(h);
1019
+ if (p.current.updateColormapTexture(k), ge.current = {
1020
+ key: `${i}-${u}`
1021
+ }, ke.current = R, Me(f => ({
1022
+ ...f,
1023
+ dataRange: R,
1024
+ opacity: e.opacity
1025
+ })), p.current && p.current.updateDataParameters) {
1026
+ const f = D.scaleType === "sqrt" ? 1 : 0;
1027
+ p.current.updateDataParameters($, d, D.missing, f);
1472
1028
  }
1473
- const newCacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
1474
- preloadedDataCache.current.set(newCacheKey, {
1475
- ...cachedData,
1476
- scale: dataScale,
1477
- offset: dataOffset
1029
+ const P = A ? `mrms-${y}-${i}` : `${M}-${U}-${E}-${K}-${i}`;
1030
+ W.current.set(P, {
1031
+ ...D,
1032
+ scale: $,
1033
+ offset: d
1478
1034
  });
1479
1035
  }
1480
- previousStateRef.current = newState;
1036
+ l.current = e;
1481
1037
  return;
1482
1038
  }
1483
- const prev = previousStateRef.current;
1484
- const needsFullLoad = !hasInitialLoad.current || newState.isNexrad !== prev?.isNexrad || newState.isSatellite !== prev?.isSatellite || newState.isNexrad && prev?.isNexrad && (newState.nexradSite !== prev.nexradSite || newState.nexradDataSource !== prev.nexradDataSource || newState.nexradProduct !== prev.nexradProduct) || newState.isSatellite && prev?.isSatellite && (newState.satelliteInstrumentId !== prev.satelliteInstrumentId || newState.satelliteSectorLabel !== prev.satelliteSectorLabel || newState.satelliteChannel !== prev.satelliteChannel) || !newState.isNexrad && !newState.isSatellite && (newState.model !== prev?.model || newState.isMRMS !== prev?.isMRMS || newState.variable !== prev?.variable || newState.date !== prev?.date || newState.run !== prev?.run);
1485
- if (needsFullLoad) {
1486
- wxGridVerbose('needsFullLoad', {
1487
- variable: newState.variable,
1488
- isMRMS: newState.isMRMS,
1489
- model: newState.model,
1490
- isInitial: !hasInitialLoad.current,
1491
- prevVariable: prev?.variable,
1492
- prevModel: prev?.model
1493
- });
1494
- const nexradIdentityChange = NEXRAD_NATIVE && (newState.isNexrad !== prev?.isNexrad || newState.isNexrad && prev?.isNexrad && (newState.nexradSite !== prev.nexradSite || newState.nexradDataSource !== prev.nexradDataSource || newState.nexradProduct !== prev.nexradProduct));
1495
- const satelliteIdentityChange = SATELLITE_NATIVE && (newState.isSatellite !== prev?.isSatellite || newState.isSatellite && prev?.isSatellite && (newState.satelliteInstrumentId !== prev.satelliteInstrumentId || newState.satelliteSectorLabel !== prev.satelliteSectorLabel || newState.satelliteChannel !== prev.satelliteChannel));
1496
- if (nexradIdentityChange) {
1497
- nexradPreloadInteractionRef.current?.cancel?.();
1498
- nexradPreloadInteractionRef.current = null;
1499
- nexradControllerRef.current?.destroy();
1500
- nexradControllerRef.current = null;
1501
- }
1502
- if (satelliteIdentityChange) {
1503
- satelliteControllerRef.current?.destroy();
1504
- satelliteControllerRef.current = null;
1505
- }
1506
- if (gridLayerRef.current) {
1507
- gridLayerRef.current.setVariable(newState.variable);
1508
- gridLayerRef.current.clear();
1509
- if (Platform.OS === 'ios' && gridLayerRef.current.clearGpuCache) {
1510
- gridLayerRef.current.clearGpuCache();
1511
- }
1512
- }
1513
- hasPreloadedRef.current = false;
1514
- preloadGenerationRef.current += 1;
1515
- preloadedDataCache.current.clear();
1516
- cachedGeometry.current = null;
1517
- cachedColormap.current = null;
1518
- currentGridDataRef.current = null;
1519
- WeatherFrameProcessorModule.cancelAllFrames();
1520
- wxGridVerbose('cancelAllFrames', {
1521
- reason: 'needsFullLoad',
1522
- variable: newState.variable,
1523
- generation: preloadGenerationRef.current
1039
+ const c = l.current;
1040
+ if (!ae.current || e.isNexrad !== c?.isNexrad || e.isSatellite !== c?.isSatellite || e.isNexrad && c?.isNexrad && (e.nexradSite !== c.nexradSite || e.nexradDataSource !== c.nexradDataSource || e.nexradProduct !== c.nexradProduct) || e.isSatellite && c?.isSatellite && (e.satelliteInstrumentId !== c.satelliteInstrumentId || e.satelliteSectorLabel !== c.satelliteSectorLabel || e.satelliteChannel !== c.satelliteChannel) || !e.isNexrad && !e.isSatellite && (e.model !== c?.model || e.isMRMS !== c?.isMRMS || e.variable !== c?.variable || e.date !== c?.date || e.run !== c?.run)) {
1041
+ z("needsFullLoad", {
1042
+ variable: e.variable,
1043
+ isMRMS: e.isMRMS,
1044
+ model: e.model,
1045
+ isInitial: !ae.current,
1046
+ prevVariable: c?.variable,
1047
+ prevModel: c?.model
1524
1048
  });
1525
- if (!newState.variable) {
1526
- previousStateRef.current = newState;
1049
+ const i = Q && (e.isNexrad !== c?.isNexrad || e.isNexrad && c?.isNexrad && (e.nexradSite !== c.nexradSite || e.nexradDataSource !== c.nexradDataSource || e.nexradProduct !== c.nexradProduct)),
1050
+ u = ie && (e.isSatellite !== c?.isSatellite || e.isSatellite && c?.isSatellite && (e.satelliteInstrumentId !== c.satelliteInstrumentId || e.satelliteSectorLabel !== c.satelliteSectorLabel || e.satelliteChannel !== c.satelliteChannel));
1051
+ if (i && (X.current?.destroy(), X.current = null), u && (re.current?.destroy(), re.current = null), p.current && (p.current.setVariable(e.variable), p.current.clear(), se.OS === "ios" && p.current.clearGpuCache && p.current.clearGpuCache()), ne.current = !1, Le.current += 1, W.current.clear(), pe.current = null, ge.current = null, De.current = null, qe.cancelAllFrames(), z("cancelAllFrames", {
1052
+ reason: "needsFullLoad",
1053
+ variable: e.variable,
1054
+ generation: Le.current
1055
+ }), !e.variable) {
1056
+ l.current = e;
1527
1057
  return;
1528
1058
  }
1529
- if (!newState.isNexrad && !newState.isSatellite) {
1530
- preloadAllFramesToDisk(newState);
1531
- } else if (NEXRAD_NATIVE && newState.isNexrad) {
1532
- hasInitialLoad.current = true;
1533
- } else if (SATELLITE_NATIVE && newState.isSatellite) {
1534
- hasInitialLoad.current = true;
1535
- }
1536
- } else if (!newState.isNexrad && (newState.forecastHour !== previousStateRef.current.forecastHour || newState.isMRMS && newState.mrmsTimestamp !== previousStateRef.current.mrmsTimestamp)) {
1537
- const success = updateGPUWithCachedData(newState);
1538
- if (!success) {
1539
- wxGridWarn('timelineGpuUpdateMiss', {
1540
- isMRMS: newState.isMRMS,
1541
- variable: newState.variable,
1542
- mrmsTimestamp: newState.mrmsTimestamp,
1543
- forecastHour: newState.forecastHour
1544
- });
1545
- hasPreloadedRef.current = false;
1546
- void preloadAllFramesToDisk(newState);
1547
- }
1548
- if (success && newState.opacity !== renderProps.opacity) {
1549
- setRenderProps(prev => ({
1550
- ...prev,
1551
- opacity: newState.opacity
1552
- }));
1553
- }
1554
- }
1555
- if (NEXRAD_NATIVE && newState.isNexrad && newState.nexradSite && newState.nexradTimestamp != null) {
1556
- const ctl = ensureNexradController();
1557
- if (ctl) {
1558
- hasInitialLoad.current = true;
1559
- void ctl.sync(newState);
1560
- nexradPreloadInteractionRef.current?.cancel?.();
1561
- const preloadCancelled = {
1562
- v: false
1563
- };
1564
- nexradPreloadInteractionRef.current = {
1565
- cancel: () => {
1566
- preloadCancelled.v = true;
1567
- }
1568
- };
1569
- const nexradTimelineSnapshot = Array.isArray(newState.availableNexradTimestamps) ? newState.availableNexradTimestamps : [];
1570
- const kickPreload = () => {
1571
- nexradPreloadInteractionRef.current = null;
1572
- if (preloadCancelled.v) {
1573
- return;
1574
- }
1575
- const cur = nexradControllerRef.current;
1576
- if (!cur) {
1577
- return;
1578
- }
1579
- const s = core.state;
1580
- if (!s.isNexrad || !s.nexradSite || s.nexradTimestamp == null) {
1581
- return;
1582
- }
1583
- const coreTs = Array.isArray(s.availableNexradTimestamps) ? s.availableNexradTimestamps : [];
1584
- const mergedTimestamps = coreTs.length > 0 ? coreTs : nexradTimelineSnapshot.length > 0 ? nexradTimelineSnapshot : [];
1585
- const preloadState = {
1586
- ...s,
1587
- availableNexradTimestamps: mergedTimestamps
1588
- };
1589
- cur.preloadAllAvailable(preloadState);
1590
- };
1591
- if (typeof queueMicrotask === 'function') {
1592
- queueMicrotask(kickPreload);
1593
- } else {
1594
- setTimeout(kickPreload, 0);
1595
- }
1596
- }
1597
- } else if (NEXRAD_NATIVE && (!newState.isNexrad || !newState.nexradSite)) {
1598
- nexradPreloadInteractionRef.current?.cancel?.();
1599
- nexradPreloadInteractionRef.current = null;
1600
- nexradControllerRef.current?.destroy();
1601
- nexradControllerRef.current = null;
1059
+ !e.isNexrad && !e.isSatellite ? it(e) : Q && e.isNexrad ? Ie(e) : ie && e.isSatellite && (ae.current = !0);
1060
+ } else if (!e.isNexrad && (e.forecastHour !== l.current.forecastHour || e.isMRMS && e.mrmsTimestamp !== l.current.mrmsTimestamp)) {
1061
+ const i = yt(e);
1062
+ i || (Z("timelineGpuUpdateMiss", {
1063
+ isMRMS: e.isMRMS,
1064
+ variable: e.variable,
1065
+ mrmsTimestamp: e.mrmsTimestamp,
1066
+ forecastHour: e.forecastHour
1067
+ }), ne.current = !1, it(e)), i && e.opacity !== Ve.opacity && Me(u => ({
1068
+ ...u,
1069
+ opacity: e.opacity
1070
+ }));
1602
1071
  }
1603
- if (SATELLITE_NATIVE && newState.isSatellite) {
1604
- satBridgeWarn('handleStateChange satellite', {
1605
- satelliteInstrumentId: newState.satelliteInstrumentId ?? null,
1606
- satelliteSectorLabel: newState.satelliteSectorLabel ?? null,
1607
- satelliteChannel: newState.satelliteChannel ?? null,
1608
- timelineKeys: Object.keys(newState.satelliteTimeToFileMap || {}).length,
1609
- refHasSync: Boolean(satelliteLayerRef.current?.syncSatellite)
1072
+ if (Q && e.isNexrad ? Ie(e) : Q && !e.isNexrad && (X.current?.destroy(), X.current = null), ie && e.isSatellite) {
1073
+ Ee("handleStateChange \u2192 satellite", {
1074
+ satelliteInstrumentId: e.satelliteInstrumentId ?? null,
1075
+ satelliteSectorLabel: e.satelliteSectorLabel ?? null,
1076
+ satelliteChannel: e.satelliteChannel ?? null,
1077
+ timelineKeys: Object.keys(e.satelliteTimeToFileMap || {}).length,
1078
+ refHasSync: !!Ne.current?.syncSatellite
1610
1079
  });
1611
- const satCtl = ensureSatelliteController();
1612
- if (satCtl) {
1613
- hasInitialLoad.current = true;
1614
- void satCtl.sync(newState);
1615
- } else {
1616
- satBridgeWarn('handleStateChange satellite: ensureSatelliteController returned null', {});
1617
- }
1618
- if (!newState.satelliteInstrumentId && typeof __DEV__ !== 'undefined' && __DEV__) {
1619
- console.warn('[AguaceroWX][satellite] isSatellite is true but satelliteInstrumentId is missing — native sync still runs; timeline may be empty until core sets instrument.');
1620
- }
1621
- } else if (SATELLITE_NATIVE && !newState.isSatellite) {
1622
- satelliteControllerRef.current?.destroy();
1623
- satelliteControllerRef.current = null;
1624
- }
1625
- previousStateRef.current = newState;
1080
+ const i = at();
1081
+ i ? (ae.current = !0, i.sync(e)) : Ee("handleStateChange satellite: ensureSatelliteController returned null", {}), !e.satelliteInstrumentId && typeof __DEV__ < "u" && __DEV__ && console.warn("[AguaceroWX][satellite] isSatellite is true but satelliteInstrumentId is missing \u2014 native sync still runs; timeline may be empty until core sets instrument.");
1082
+ } else ie && !e.isSatellite && (re.current?.destroy(), re.current = null);
1083
+ l.current = e;
1626
1084
  };
1627
- handleStateChangeRef.current = handleStateChange;
1628
- const stableHandler = newState => {
1629
- lastEmittedStateForInspectRef.current = newState;
1630
- setNexradSitesMapVisible(Boolean(newState.isNexrad && newState.nexradShowSitesPicker !== false));
1631
- // OPTIMIZATION: If playing (high speed), prioritize MAP update and skip debounce
1632
- if (newState.isPlaying) {
1633
- // 1. Update Map FIRST (Native Enqueue)
1634
- if (handleStateChangeRef.current) {
1635
- handleStateChangeRef.current(newState);
1636
- }
1637
-
1638
- // 2. Update UI Slider SECOND
1639
- // This ensures the heavy map frame is processing while React reconciles the slider
1640
- props.onStateChange?.(newState);
1641
- if (debounceTimeoutRef.current) {
1642
- clearTimeout(debounceTimeoutRef.current);
1643
- debounceTimeoutRef.current = null;
1644
- }
1085
+ he.current = r;
1086
+ const a = e => {
1087
+ if (st(!!(e.isNexrad && e.nexradShowSitesPicker !== !1)), e.isPlaying) {
1088
+ he.current && he.current(e), m.onStateChange?.(e), le.current && (clearTimeout(le.current), le.current = null);
1645
1089
  return;
1646
1090
  }
1647
-
1648
- // --- Existing Logic for scrubbing/paused ---
1649
-
1650
- // 1. Immediate Slider Update for responsiveness
1651
- props.onStateChange?.(newState);
1652
- if (debounceTimeoutRef.current) {
1653
- clearTimeout(debounceTimeoutRef.current);
1654
- }
1655
- const prevStable = previousStateRef.current;
1656
- const sameTimelineStable = prevStable && (prevStable.isNexrad ? newState.nexradTimestamp === prevStable.nexradTimestamp && newState.nexradSite === prevStable.nexradSite && newState.nexradProduct === prevStable.nexradProduct && Number(newState.nexradTilt) === Number(prevStable.nexradTilt) && newState.nexradDurationValue === prevStable.nexradDurationValue && nexradObsTimelineSig(newState) === nexradObsTimelineSig(prevStable) : prevStable.isSatellite ? newState.satelliteTimestamp === prevStable.satelliteTimestamp && newState.satelliteInstrumentId === prevStable.satelliteInstrumentId && newState.satelliteSectorLabel === prevStable.satelliteSectorLabel && newState.satelliteChannel === prevStable.satelliteChannel && newState.satelliteDurationValue === prevStable.satelliteDurationValue && satelliteObsTimelineSig(newState) === satelliteObsTimelineSig(prevStable) : newState.forecastHour === prevStable.forecastHour && newState.mrmsTimestamp === prevStable.mrmsTimestamp);
1657
- const sameModeStable = prevStable && (newState.isSatellite ? newState.satelliteInstrumentId === prevStable.satelliteInstrumentId && newState.satelliteSectorLabel === prevStable.satelliteSectorLabel && newState.satelliteChannel === prevStable.satelliteChannel : newState.model === prevStable.model && newState.isMRMS === prevStable.isMRMS);
1658
-
1659
- // Opacity and Play state changes should be immediate for the native layer too
1660
- const isOpacityOnlyChange = prevStable && sameTimelineStable && sameModeStable && newState.opacity !== prevStable.opacity && newState.variable === prevStable.variable && newState.units === prevStable.units;
1661
- const isPlayStateOnlyChange = prevStable && sameTimelineStable && sameModeStable && newState.isPlaying !== prevStable.isPlaying && newState.variable === prevStable.variable && newState.units === prevStable.units && newState.opacity === prevStable.opacity;
1662
- if (isOpacityOnlyChange || isPlayStateOnlyChange || !previousStateRef.current) {
1663
- if (handleStateChangeRef.current) {
1664
- handleStateChangeRef.current(newState);
1665
- }
1091
+ m.onStateChange?.(e), le.current && clearTimeout(le.current);
1092
+ const o = l.current,
1093
+ F = o && (o.isNexrad ? e.nexradTimestamp === o.nexradTimestamp && e.nexradSite === o.nexradSite && e.nexradProduct === o.nexradProduct && Number(e.nexradTilt) === Number(o.nexradTilt) : o.isSatellite ? e.satelliteTimestamp === o.satelliteTimestamp && e.satelliteInstrumentId === o.satelliteInstrumentId && e.satelliteSectorLabel === o.satelliteSectorLabel && e.satelliteChannel === o.satelliteChannel && e.satelliteDurationValue === o.satelliteDurationValue && ue(e) === ue(o) : e.forecastHour === o.forecastHour && e.mrmsTimestamp === o.mrmsTimestamp),
1094
+ s = o && (e.isSatellite ? e.satelliteInstrumentId === o.satelliteInstrumentId && e.satelliteSectorLabel === o.satelliteSectorLabel && e.satelliteChannel === o.satelliteChannel : e.model === o.model && e.isMRMS === o.isMRMS),
1095
+ w = o && F && s && e.opacity !== o.opacity && e.variable === o.variable && e.units === o.units,
1096
+ N = o && F && s && e.isPlaying !== o.isPlaying && e.variable === o.variable && e.units === o.units && e.opacity === o.opacity;
1097
+ if (w || N || !l.current) {
1098
+ he.current && he.current(e);
1666
1099
  return;
1667
1100
  }
1668
- debounceTimeoutRef.current = setTimeout(() => {
1669
- if (handleStateChangeRef.current) {
1670
- handleStateChangeRef.current(newState);
1671
- }
1672
- debounceTimeoutRef.current = null;
1673
- }, 16); // ~60fps map updates
1101
+ le.current = setTimeout(() => {
1102
+ he.current && he.current(e), le.current = null;
1103
+ }, 16);
1674
1104
  };
1675
- core.on('state:change', stableHandler);
1676
- return () => {
1677
- core.off('state:change', stableHandler);
1678
- if (debounceTimeoutRef.current) {
1679
- clearTimeout(debounceTimeoutRef.current);
1680
- }
1681
- if (NEXRAD_NATIVE) {
1682
- nexradPreloadInteractionRef.current?.cancel?.();
1683
- nexradPreloadInteractionRef.current = null;
1684
- nexradControllerRef.current?.destroy();
1685
- nexradControllerRef.current = null;
1686
- }
1687
- if (SATELLITE_NATIVE) {
1688
- satelliteControllerRef.current?.destroy();
1689
- satelliteControllerRef.current = null;
1690
- }
1691
- };
1692
- }, [core, ensureNexradController, ensureSatelliteController]);
1693
- useEffect(() => {
1694
- return () => {
1695
- preloadedDataCache.current.clear(); // This drops JS references
1696
- hasInitialLoad.current = false;
1697
- lastProcessedState.current = null;
1698
- // Native cleanup
1699
- if (gridLayerRef.current && Platform.OS === 'ios') {
1700
- gridLayerRef.current.clearGpuCache();
1701
- }
1702
- if (NEXRAD_NATIVE) {
1703
- nexradPreloadInteractionRef.current?.cancel?.();
1704
- nexradPreloadInteractionRef.current = null;
1705
- nexradControllerRef.current?.destroy();
1706
- nexradControllerRef.current = null;
1707
- }
1708
- if (SATELLITE_NATIVE) {
1709
- satelliteControllerRef.current?.destroy();
1710
- satelliteControllerRef.current = null;
1711
- }
1105
+ return t.on("state:change", a), () => {
1106
+ t.off("state:change", a), le.current && clearTimeout(le.current), Q && (X.current?.destroy(), X.current = null), ie && (re.current?.destroy(), re.current = null);
1712
1107
  };
1108
+ }, [t, at, Ie]), j(() => () => {
1109
+ W.current.clear(), ae.current = !1, He.current = null, p.current && se.OS === "ios" && p.current.clearGpuCache(), Q && (X.current?.destroy(), X.current = null), ie && (re.current?.destroy(), re.current = null);
1713
1110
  }, []);
1714
- const lastInspectorUpdateRef = useRef(0);
1715
- const INSPECTOR_THROTTLE_MS = 50;
1716
- useEffect(() => {
1717
- if (!core || !inspectorEnabled) {
1718
- return;
1719
- }
1720
- const handleMapMove = center => {
1721
- if (!center || !Array.isArray(center) || center.length !== 2) {
1722
- return;
1723
- }
1724
-
1725
- // Throttle updates
1726
- const now = Date.now();
1727
- if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
1728
- return;
1729
- }
1730
- lastInspectorUpdateRef.current = now;
1731
- const [longitude, latitude] = center;
1732
- if (NEXRAD_NATIVE && core.state?.isNexrad) {
1733
- onInspect?.(getNexradInspectPayloadAtRef.current(longitude, latitude));
1734
- return;
1735
- }
1736
- void getValueAtPointRef.current(longitude, latitude).then(payload => {
1737
- onInspect?.(payload);
1111
+ const ot = V(0),
1112
+ bt = 50;
1113
+ j(() => {
1114
+ if (!t || !g) return;
1115
+ const r = a => {
1116
+ if (!a || !Array.isArray(a) || a.length !== 2) return;
1117
+ const e = Date.now();
1118
+ if (e - ot.current < bt) return;
1119
+ ot.current = e;
1120
+ const [o, F] = a;
1121
+ We.current(o, F).then(s => {
1122
+ I?.(s);
1738
1123
  });
1739
1124
  };
1740
- core.on('map:move', handleMapMove);
1741
- if (context && context.getCenter) {
1742
- const center = context.getCenter();
1743
- if (center) {
1744
- handleMapMove(center);
1745
- }
1125
+ if (t.on("map:move", r), _e && _e.getCenter) {
1126
+ const a = _e.getCenter();
1127
+ a && r(a);
1746
1128
  }
1747
1129
  return () => {
1748
- core.off('map:move', handleMapMove);
1749
- };
1750
- }, [inspectorEnabled, onInspect, core, context]);
1751
- useEffect(() => {
1752
- if (!core || !inspectorEnabled) {
1753
- return;
1754
- }
1755
- const triggerReinspection = () => {
1756
- const mapRef = mapRegistry.getMap();
1757
- const center = mapRef?._currentCenter;
1758
- if (center && Array.isArray(center) && center.length === 2) {
1759
- const [longitude, latitude] = center;
1760
- if (NEXRAD_NATIVE && core?.state?.isNexrad) {
1761
- onInspect?.(getNexradInspectPayloadAtRef.current(longitude, latitude));
1762
- } else {
1763
- getValueAtPointRef.current(longitude, latitude).then(payload => {
1764
- onInspect?.(payload);
1765
- });
1766
- }
1767
- }
1130
+ t.off("map:move", r);
1768
1131
  };
1769
-
1770
- // Small delay to ensure data is loaded before re-inspecting
1771
- const timer = setTimeout(triggerReinspection, 100);
1772
- return () => clearTimeout(timer);
1773
- }, [core?.state?.nexradTimestamp, core?.state?.isNexrad, core?.state?.nexradSite, core?.state?.nexradProduct, core?.state?.nexradTilt, core?.state?.nexradDataSource, core?.state?.nexradStormRelative, core?.state?.variable, core?.state?.model, core?.state?.forecastHour, core?.state?.mrmsTimestamp, core?.state?.units, core?.state?.opacity, inspectorEnabled, onInspect]);
1774
- useEffect(() => {
1775
- if (!core) {
1776
- return;
1777
- }
1778
- const handleCameraChange = center => {
1779
- if (core && center) {
1780
- core.setMapCenter(center);
1132
+ }, [g, I, t, _e]), j(() => {
1133
+ if (!t || !g) return;
1134
+ const r = setTimeout(() => {
1135
+ const a = Ue.getMap()?._currentCenter;
1136
+ if (a && Array.isArray(a) && a.length === 2) {
1137
+ const [e, o] = a;
1138
+ We.current(e, o).then(F => {
1139
+ I?.(F);
1140
+ });
1781
1141
  }
1142
+ }, 100);
1143
+ return () => clearTimeout(r);
1144
+ }, [t?.state?.nexradTimestamp, t?.state?.isNexrad, t?.state?.nexradSite, t?.state?.nexradProduct, t?.state?.nexradTilt, t?.state?.nexradDataSource, t?.state?.nexradStormRelative, t?.state?.variable, t?.state?.model, t?.state?.forecastHour, t?.state?.mrmsTimestamp, t?.state?.units, t?.state?.opacity, g, I]), j(() => {
1145
+ if (!t) return;
1146
+ const r = e => {
1147
+ t && e && t.setMapCenter(e);
1782
1148
  };
1783
-
1784
- // Register with the global registry
1785
- mapRegistry.addCameraListener(handleCameraChange);
1786
-
1787
- // Try to get initial center
1788
- const mapRef = mapRegistry.getMap();
1789
- if (mapRef?._currentCenter) {
1790
- handleCameraChange(mapRef._currentCenter);
1791
- }
1792
- return () => {
1793
- mapRegistry.removeCameraListener(handleCameraChange);
1794
- };
1795
- }, [core]);
1796
- useEffect(() => {
1797
- core.initialize({
1798
- autoRefresh: false
1799
- }); // <-- add the argument
1800
- return () => {
1801
- core.destroy();
1149
+ Ue.addCameraListener(r);
1150
+ const a = Ue.getMap();
1151
+ return a?._currentCenter && r(a._currentCenter), () => {
1152
+ Ue.removeCameraListener(r);
1802
1153
  };
1803
- }, [core]);
1804
- const gridBelowId = belowIDFromProps ?? context?.weatherBeforeLayerId ?? 'AML_-_terrain';
1805
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(GridRenderLayer, {
1806
- ref: gridLayerRef,
1807
- opacity: renderProps.opacity,
1808
- dataRange: renderProps.dataRange,
1809
- belowID: gridBelowId
1810
- }), NEXRAD_NATIVE ? /*#__PURE__*/React.createElement(NexradRadarLayer, {
1811
- ref: nexradLayerRef,
1812
- belowID: gridBelowId
1813
- }) : null, SATELLITE_NATIVE ? /*#__PURE__*/React.createElement(SatelliteLayer, {
1814
- ref: satelliteLayerRef,
1815
- belowID: gridBelowId
1816
- }) : null, /*#__PURE__*/React.createElement(NwsAlertsOverlay, {
1817
- core: core,
1818
- watchesWarnings: watchesWarningsOptions,
1819
- onNwsAlertClick: onNwsAlertClick
1820
- }), nexradSitesMapVisible ? /*#__PURE__*/React.createElement(NexradSitesMapLayer, {
1821
- visible: true,
1822
- belowLayerID: gridBelowId,
1823
- onSelectSite: siteId => void core.setNexradSite(siteId)
1154
+ }, [t]), j(() => (t.initialize({
1155
+ autoRefresh: !1
1156
+ }), () => {
1157
+ t.destroy();
1158
+ }), [t]);
1159
+ const Oe = Te ?? _e?.weatherBeforeLayerId ?? "AML_-_terrain";
1160
+ return /*#__PURE__*/be.createElement(be.Fragment, null, /*#__PURE__*/be.createElement(_t, {
1161
+ ref: p,
1162
+ opacity: Ve.opacity,
1163
+ dataRange: Ve.dataRange,
1164
+ belowID: Oe
1165
+ }), Q ? /*#__PURE__*/be.createElement(Nt, {
1166
+ ref: rt,
1167
+ belowID: Oe
1168
+ }) : null, ie ? /*#__PURE__*/be.createElement(Dt, {
1169
+ ref: Ne,
1170
+ belowID: Oe
1171
+ }) : null, /*#__PURE__*/be.createElement(Pt, {
1172
+ core: t,
1173
+ watchesWarnings: gt,
1174
+ onNwsAlertClick: Ge
1175
+ }), St ? /*#__PURE__*/be.createElement(It, {
1176
+ visible: !0,
1177
+ belowLayerID: Oe,
1178
+ onSelectSite: r => void t.setNexradSite(r)
1824
1179
  }) : null);
1825
1180
  });
1826
- WeatherLayerManager.getAvailableVariables = options => {
1827
- if (!options || !options.apiKey) {
1828
- return [];
1829
- }
1830
- const core = new AguaceroCore({
1831
- apiKey: options.apiKey
1832
- });
1833
- return core.getAvailableVariables('mrms');
1834
- };
1181
+ WeatherLayerManager.getAvailableVariables = m => !m || !m.apiKey ? [] : new je({
1182
+ apiKey: m.apiKey
1183
+ }).getAvailableVariables("mrms");
1835
1184
  //# sourceMappingURL=WeatherLayerManager.js.map