@aguacerowx/react-native 0.0.33 → 0.0.34

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 (411) hide show
  1. package/README.md +126 -126
  2. package/aguacerowx-react-native.podspec +38 -38
  3. package/android/build.gradle +107 -107
  4. package/android/src/main/AndroidManifest.xml +6 -6
  5. package/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  6. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -672
  7. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  8. package/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  9. package/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  10. package/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  11. package/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  12. package/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  13. package/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  14. package/android/src/main/res/raw/fragment_shader.glsl +188 -161
  15. package/android/src/main/res/raw/vertex_shader.glsl +19 -19
  16. package/index.js +2 -2
  17. package/ios/AguaceroPackage.m +18 -18
  18. package/ios/FragmentUniforms.swift +15 -15
  19. package/ios/GridRenderLayer.swift +1004 -986
  20. package/ios/GridRenderLayerBridge.swift +36 -36
  21. package/ios/GridRenderLayerManager.mm +157 -157
  22. package/ios/GridRenderLayerView.h +30 -30
  23. package/ios/GridRenderLayerView.m +216 -216
  24. package/ios/InspectorDataCache.swift +65 -65
  25. package/ios/InspectorModule.m +9 -9
  26. package/ios/InspectorModule.swift +63 -63
  27. package/ios/Shaders.metal +327 -190
  28. package/ios/WeatherFrameProcessorModule.m +15 -15
  29. package/ios/WeatherFrameProcessorModule.swift +103 -103
  30. package/ios/compiled-shaders/Shaders-device.metallib +0 -0
  31. package/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  32. package/lib/commonjs/README.md +126 -126
  33. package/lib/commonjs/aguacerowx-react-native.podspec +38 -38
  34. package/lib/commonjs/android/build.gradle +107 -107
  35. package/lib/commonjs/android/src/main/AndroidManifest.xml +6 -6
  36. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  37. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -672
  38. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  39. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  40. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  41. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  42. package/lib/commonjs/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  43. package/lib/commonjs/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  44. package/lib/commonjs/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  45. package/lib/commonjs/android/src/main/res/raw/fragment_shader.glsl +188 -161
  46. package/lib/commonjs/android/src/main/res/raw/vertex_shader.glsl +19 -19
  47. package/lib/commonjs/babel.config.js.map +1 -1
  48. package/lib/commonjs/index.js.map +1 -1
  49. package/lib/commonjs/ios/AguaceroPackage.m +18 -18
  50. package/lib/commonjs/ios/FragmentUniforms.swift +15 -15
  51. package/lib/commonjs/ios/GridRenderLayer.swift +1004 -986
  52. package/lib/commonjs/ios/GridRenderLayerBridge.swift +36 -36
  53. package/lib/commonjs/ios/GridRenderLayerManager.mm +157 -157
  54. package/lib/commonjs/ios/GridRenderLayerView.h +30 -30
  55. package/lib/commonjs/ios/GridRenderLayerView.m +216 -216
  56. package/lib/commonjs/ios/InspectorDataCache.swift +65 -65
  57. package/lib/commonjs/ios/InspectorModule.m +9 -9
  58. package/lib/commonjs/ios/InspectorModule.swift +63 -63
  59. package/lib/commonjs/ios/Shaders.metal +327 -190
  60. package/lib/commonjs/ios/WeatherFrameProcessorModule.m +15 -15
  61. package/lib/commonjs/ios/WeatherFrameProcessorModule.swift +103 -103
  62. package/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  63. package/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  64. package/lib/commonjs/package.json +72 -72
  65. package/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
  66. package/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  67. package/lib/commonjs/scripts/compile-shaders.sh +38 -38
  68. package/lib/commonjs/src/AguaceroContext.js.map +1 -1
  69. package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  70. package/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
  71. package/lib/commonjs/src/MapManager.js.map +1 -1
  72. package/lib/commonjs/src/MapRegistry.js.map +1 -1
  73. package/lib/commonjs/src/StyleApplicator.js +6 -6
  74. package/lib/commonjs/src/StyleApplicator.js.map +1 -1
  75. package/lib/commonjs/src/WeatherLayerManager.js +2 -2
  76. package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  77. package/lib/commonjs/tsconfig.json +23 -23
  78. package/lib/module/README.md +126 -126
  79. package/lib/module/aguacerowx-react-native.podspec +38 -38
  80. package/lib/module/android/build.gradle +107 -107
  81. package/lib/module/android/src/main/AndroidManifest.xml +6 -6
  82. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/AguaceroPackage.java +33 -33
  83. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayer.java +688 -672
  84. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderLayerView.java +304 -304
  85. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/GridRenderManager.java +125 -125
  86. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/InspectorModule.java +71 -71
  87. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/ShaderUtils.java +106 -106
  88. package/lib/module/android/src/main/java/com/aguacerowx/reactnative/WeatherFrameProcessorModule.java +151 -151
  89. package/lib/module/android/src/main/res/raw/debug_fragment_shader.glsl +12 -12
  90. package/lib/module/android/src/main/res/raw/debug_vertex_shader.glsl +12 -12
  91. package/lib/module/android/src/main/res/raw/fragment_shader.glsl +188 -161
  92. package/lib/module/android/src/main/res/raw/vertex_shader.glsl +19 -19
  93. package/lib/module/babel.config.js.map +1 -1
  94. package/lib/module/index.js.map +1 -1
  95. package/lib/module/ios/AguaceroPackage.m +18 -18
  96. package/lib/module/ios/FragmentUniforms.swift +15 -15
  97. package/lib/module/ios/GridRenderLayer.swift +1004 -986
  98. package/lib/module/ios/GridRenderLayerBridge.swift +36 -36
  99. package/lib/module/ios/GridRenderLayerManager.mm +157 -157
  100. package/lib/module/ios/GridRenderLayerView.h +30 -30
  101. package/lib/module/ios/GridRenderLayerView.m +216 -216
  102. package/lib/module/ios/InspectorDataCache.swift +65 -65
  103. package/lib/module/ios/InspectorModule.m +9 -9
  104. package/lib/module/ios/InspectorModule.swift +63 -63
  105. package/lib/module/ios/Shaders.metal +327 -190
  106. package/lib/module/ios/WeatherFrameProcessorModule.m +15 -15
  107. package/lib/module/ios/WeatherFrameProcessorModule.swift +103 -103
  108. package/lib/module/ios/compiled-shaders/Shaders-device.metallib +0 -0
  109. package/lib/module/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  110. package/lib/module/lib/commonjs/README.md +126 -126
  111. package/lib/module/lib/commonjs/aguacerowx-react-native.podspec +38 -38
  112. package/lib/module/lib/commonjs/babel.config.js.map +1 -1
  113. package/lib/module/lib/commonjs/index.js.map +1 -1
  114. package/lib/module/lib/commonjs/package.json +72 -72
  115. package/lib/module/lib/commonjs/react-native-builder-bob.config.js.map +1 -1
  116. package/lib/module/lib/commonjs/scripts/compile-shaders.js.map +1 -1
  117. package/lib/module/lib/commonjs/src/AguaceroContext.js.map +1 -1
  118. package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  119. package/lib/module/lib/commonjs/src/GridRenderLayerNativeComponent.js.map +1 -1
  120. package/lib/module/lib/commonjs/src/MapManager.js.map +1 -1
  121. package/lib/module/lib/commonjs/src/MapRegistry.js.map +1 -1
  122. package/lib/module/lib/commonjs/src/StyleApplicator.js +6 -6
  123. package/lib/module/lib/commonjs/src/StyleApplicator.js.map +1 -1
  124. package/lib/module/lib/commonjs/src/WeatherLayerManager.js +2 -2
  125. package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  126. package/lib/module/lib/commonjs/tsconfig.json +23 -23
  127. package/lib/module/package.json +72 -72
  128. package/lib/module/react-native-builder-bob.config.js.map +1 -1
  129. package/lib/module/scripts/compile-shaders.js.map +1 -1
  130. package/lib/module/scripts/compile-shaders.sh +38 -38
  131. package/lib/module/src/AguaceroContext.js.map +1 -1
  132. package/lib/module/src/GridRenderLayer.js.map +1 -1
  133. package/lib/module/src/GridRenderLayerNativeComponent.js.map +1 -1
  134. package/lib/module/src/MapManager.js.map +1 -1
  135. package/lib/module/src/MapRegistry.js.map +1 -1
  136. package/lib/module/src/StyleApplicator.js +6 -6
  137. package/lib/module/src/StyleApplicator.js.map +1 -1
  138. package/lib/module/src/WeatherLayerManager.js +2 -2
  139. package/lib/module/src/WeatherLayerManager.js.map +1 -1
  140. package/lib/module/tsconfig.json +23 -23
  141. package/package.json +72 -72
  142. package/src/AguaceroContext.js +3 -3
  143. package/src/GridRenderLayer.js +215 -215
  144. package/src/GridRenderLayerNativeComponent.ts +15 -15
  145. package/src/MapManager.js +218 -218
  146. package/src/MapRegistry.js +34 -34
  147. package/src/StyleApplicator.js +240 -240
  148. package/src/WeatherLayerManager.js +1151 -1151
  149. package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/results.bin +0 -1
  150. package/android/build/.transforms/42e9b8fa82d77a1c205db5bf0d0ed519/transformed/classes/classes_dex/classes.dex +0 -0
  151. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/results.bin +0 -1
  152. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/AguaceroPackage.dex +0 -0
  153. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/BuildConfig.dex +0 -0
  154. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.dex +0 -0
  155. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayer.dex +0 -0
  156. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderLayerView.dex +0 -0
  157. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/GridRenderManager.dex +0 -0
  158. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/InspectorModule.dex +0 -0
  159. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/ShaderUtils.dex +0 -0
  160. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/aguacerowx/reactnative/WeatherFrameProcessorModule.dex +0 -0
  161. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.dex +0 -0
  162. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.dex +0 -0
  163. package/android/build/.transforms/c8ab78b63f2cc835ac936d58e29a17ab/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  164. package/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  165. package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  166. package/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  167. package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  168. package/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  169. package/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  170. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  171. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  172. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  173. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  174. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  175. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  176. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  177. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  178. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  179. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  180. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  181. package/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  182. package/android/build/generated/source/codegen/schema.json +0 -1
  183. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  184. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  185. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  186. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  187. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  188. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  189. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  190. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  191. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  192. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  193. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  194. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  195. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  196. package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  197. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  198. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  199. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  200. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  201. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  202. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  203. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  204. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  205. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  206. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  207. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  208. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  209. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  210. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  211. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  212. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  213. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  214. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  215. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  216. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  217. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
  218. package/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  219. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  220. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  221. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  222. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  223. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  224. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  225. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  226. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  227. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  228. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  229. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  230. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  231. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  232. package/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  233. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/AguaceroPackage.class.uniqueId1 +0 -0
  234. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId2 +0 -0
  235. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId3 +0 -0
  236. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId4 +0 -0
  237. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderManager.class.uniqueId0 +0 -0
  238. package/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/InspectorModule.class.uniqueId5 +0 -0
  239. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  240. package/lib/commonjs/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  241. package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  242. package/lib/commonjs/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  243. package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  244. package/lib/commonjs/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  245. package/lib/commonjs/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  246. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  247. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  248. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  249. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  250. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  251. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  252. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  253. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  254. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  255. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  256. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  257. package/lib/commonjs/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  258. package/lib/commonjs/android/build/generated/source/codegen/schema.json +0 -1
  259. package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  260. package/lib/commonjs/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  261. package/lib/commonjs/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  262. package/lib/commonjs/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  263. package/lib/commonjs/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  264. package/lib/commonjs/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  265. package/lib/commonjs/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  266. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  267. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  268. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  269. package/lib/commonjs/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  270. package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  271. package/lib/commonjs/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  272. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  273. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  274. package/lib/commonjs/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  275. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  276. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  277. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  278. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  279. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  280. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  281. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  282. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  283. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  284. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  285. package/lib/commonjs/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  286. package/lib/commonjs/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  287. package/lib/commonjs/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  288. package/lib/commonjs/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  289. package/lib/commonjs/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  290. package/lib/commonjs/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  291. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  292. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  293. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
  294. package/lib/commonjs/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  295. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  296. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  297. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  298. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  299. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  300. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  301. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  302. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  303. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  304. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  305. package/lib/commonjs/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  306. package/lib/commonjs/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  307. package/lib/commonjs/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  308. package/lib/commonjs/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  309. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/AguaceroPackage.class.uniqueId1 +0 -0
  310. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId2 +0 -0
  311. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId3 +0 -0
  312. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId4 +0 -0
  313. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderManager.class.uniqueId0 +0 -0
  314. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/InspectorModule.class.uniqueId5 +0 -0
  315. package/lib/commonjs/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  316. package/lib/module/android/build/generated/source/buildConfig/debug/com/aguacerowx/reactnative/BuildConfig.java +0 -10
  317. package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.java +0 -43
  318. package/lib/module/android/build/generated/source/codegen/java/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.java +0 -22
  319. package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec-generated.cpp +0 -22
  320. package/lib/module/android/build/generated/source/codegen/jni/AguaceroWxReactNativeSpec.h +0 -24
  321. package/lib/module/android/build/generated/source/codegen/jni/CMakeLists.txt +0 -28
  322. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI-generated.cpp +0 -17
  323. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/AguaceroWxReactNativeSpecJSI.h +0 -19
  324. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.cpp +0 -22
  325. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ComponentDescriptors.h +0 -24
  326. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.cpp +0 -16
  327. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/EventEmitters.h +0 -23
  328. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.cpp +0 -62
  329. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/Props.h +0 -40
  330. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.cpp +0 -17
  331. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/ShadowNodes.h +0 -32
  332. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.cpp +0 -16
  333. package/lib/module/android/build/generated/source/codegen/jni/react/renderer/components/AguaceroWxReactNativeSpec/States.h +0 -20
  334. package/lib/module/android/build/generated/source/codegen/schema.json +0 -1
  335. package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +0 -8
  336. package/lib/module/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +0 -18
  337. package/lib/module/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +0 -6
  338. package/lib/module/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +0 -1
  339. package/lib/module/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  340. package/lib/module/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  341. package/lib/module/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -4
  342. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_fragment_shader.glsl.flat +0 -0
  343. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_debug_vertex_shader.glsl.flat +0 -0
  344. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_fragment_shader.glsl.flat +0 -0
  345. package/lib/module/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/raw_vertex_shader.glsl.flat +0 -0
  346. package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -5
  347. package/lib/module/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  348. package/lib/module/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +0 -2
  349. package/lib/module/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  350. package/lib/module/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +0 -2
  351. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  352. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  353. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  354. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  355. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  356. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  357. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  358. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  359. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  360. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  361. package/lib/module/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  362. package/lib/module/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -6
  363. package/lib/module/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +0 -8
  364. package/lib/module/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +0 -8
  365. package/lib/module/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +0 -1
  366. package/lib/module/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  367. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_fragment_shader.glsl +0 -13
  368. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/debug_vertex_shader.glsl +0 -13
  369. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/fragment_shader.glsl +0 -162
  370. package/lib/module/android/build/intermediates/packaged_res/debug/packageDebugResources/raw/vertex_shader.glsl +0 -20
  371. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/AguaceroPackage.class +0 -0
  372. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/BuildConfig.class +0 -0
  373. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer$VertexInfo.class +0 -0
  374. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayer.class +0 -0
  375. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderLayerView.class +0 -0
  376. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/GridRenderManager.class +0 -0
  377. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/InspectorModule.class +0 -0
  378. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/ShaderUtils.class +0 -0
  379. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/aguacerowx/reactnative/WeatherFrameProcessorModule.class +0 -0
  380. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerDelegate.class +0 -0
  381. package/lib/module/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/facebook/react/viewmanagers/GridRenderLayerManagerInterface.class +0 -0
  382. package/lib/module/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  383. package/lib/module/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -5
  384. package/lib/module/android/build/outputs/logs/manifest-merger-debug-report.txt +0 -17
  385. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/AguaceroPackage.class.uniqueId1 +0 -0
  386. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer$VertexInfo.class.uniqueId2 +0 -0
  387. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayer.class.uniqueId3 +0 -0
  388. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderLayerView.class.uniqueId4 +0 -0
  389. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/GridRenderManager.class.uniqueId0 +0 -0
  390. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/InspectorModule.class.uniqueId5 +0 -0
  391. package/lib/module/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  392. package/lib/module/lib/commonjs/android/build.gradle +0 -108
  393. package/lib/module/lib/commonjs/android/src/main/AndroidManifest.xml +0 -7
  394. package/lib/module/lib/commonjs/ios/AguaceroPackage.m +0 -19
  395. package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +0 -16
  396. package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +0 -986
  397. package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -37
  398. package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +0 -158
  399. package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +0 -31
  400. package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +0 -217
  401. package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +0 -66
  402. package/lib/module/lib/commonjs/ios/InspectorModule.m +0 -10
  403. package/lib/module/lib/commonjs/ios/InspectorModule.swift +0 -64
  404. package/lib/module/lib/commonjs/ios/Shaders.metal +0 -191
  405. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +0 -16
  406. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +0 -104
  407. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  408. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-simulator.metallib +0 -0
  409. package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec-generated.mm +0 -0
  410. package/lib/module/lib/commonjs/ios/generated/AguaceroWxReactNativeSpec.h +0 -0
  411. package/lib/module/lib/commonjs/scripts/compile-shaders.sh +0 -39
@@ -1,1152 +1,1152 @@
1
- // packages/react-native/src/WeatherLayerManager.js
2
-
3
- import React, { useState, useRef, useContext, useEffect, forwardRef, useImperativeHandle, useMemo } from 'react';
4
- import { AguaceroCore, getUnitConversionFunction, DICTIONARIES } from '@aguacerowx/javascript-sdk';
5
- import { AguaceroContext } from './AguaceroContext';
6
- import { GridRenderLayer } from './GridRenderLayer';
7
- import { fromByteArray } from 'base64-js';
8
- import { Platform, NativeModules } from 'react-native';
9
- import { mapRegistry } from './MapRegistry';
10
-
11
- function findLatestModelRun(modelsData, modelName) {
12
- const model = modelsData?.[modelName];
13
- if (!model) return null;
14
- const availableDates = Object.keys(model).sort((a, b) => b.localeCompare(a));
15
- for (const date of availableDates) {
16
- const runs = model[date];
17
- if (!runs) continue;
18
- const availableRuns = Object.keys(runs).sort((a, b) => b.localeCompare(a));
19
- if (availableRuns.length > 0) return { date: date, run: availableRuns[0] };
20
- }
21
- return null;
22
- }
23
- const { WeatherFrameProcessorModule, InspectorModule } = NativeModules;
24
-
25
- /**
26
- * A helper function to generate the raw RGBA byte buffer for the colormap texture.
27
- */
28
- const _generateColormapBytes = (colormap) => {
29
- const width = 256;
30
- const data = new Uint8Array(width * 4);
31
- const stops = colormap.reduce((acc, _, i) => (i % 2 === 0 ? [...acc, { value: colormap[i], color: colormap[i + 1] }] : acc), []);
32
-
33
- if (stops.length === 0) return data;
34
-
35
- const minVal = stops[0].value;
36
- const maxVal = stops[stops.length - 1].value;
37
-
38
- const hexToRgb = (hex) => {
39
- const r = parseInt(hex.slice(1, 3), 16);
40
- const g = parseInt(hex.slice(3, 5), 16);
41
- const b = parseInt(hex.slice(5, 7), 16);
42
- return [r, g, b];
43
- };
44
-
45
- for (let i = 0; i < width; i++) {
46
- const val = minVal + (i / (width - 1)) * (maxVal - minVal);
47
- let lower = stops[0];
48
- let upper = stops[stops.length - 1];
49
- for (let j = 0; j < stops.length - 1; j++) {
50
- if (val >= stops[j].value && val <= stops[j + 1].value) {
51
- lower = stops[j];
52
- upper = stops[j + 1];
53
- break;
54
- }
55
- }
56
- const t = (val - lower.value) / (upper.value - lower.value || 1);
57
- const lowerRgb = hexToRgb(lower.color);
58
- const upperRgb = hexToRgb(upper.color);
59
- const rgb = lowerRgb.map((c, idx) => c * (1 - t) + upperRgb[idx] * t);
60
-
61
- const offset = i * 4;
62
- data[offset + 0] = Math.round(rgb[0]);
63
- data[offset + 1] = Math.round(rgb[1]);
64
- data[offset + 2] = Math.round(rgb[2]);
65
- data[offset + 3] = 255;
66
- }
67
- return data;
68
- };
69
-
70
- AguaceroCore.prototype.setMapCenter = function(center) {
71
- this.emit('map:move', center);
72
- };
73
-
74
- export const WeatherLayerManager = forwardRef((props, ref) => {
75
- const {
76
- inspectorEnabled,
77
- onInspect,
78
- apiKey,
79
- customColormaps,
80
- initialMode,
81
- initialVariable,
82
- autoRefresh,
83
- autoRefreshInterval,
84
- initialModel,
85
- ...restProps
86
- } = props;
87
- const context = useContext(AguaceroContext);
88
-
89
- // Create the core here instead of getting it from context
90
- const core = useMemo(() => new AguaceroCore({
91
- apiKey: apiKey,
92
- customColormaps: customColormaps,
93
- // ADD: Pass layerOptions to the core's constructor
94
- layerOptions: {
95
- mode: initialMode,
96
- variable: initialVariable,
97
- model: initialModel
98
- }
99
- }), [apiKey]);
100
-
101
- const gridLayerRef = useRef(null);
102
- const currentGridDataRef = useRef(null);
103
- const autoRefreshIntervalId = useRef(null);
104
-
105
- // Cache for preloaded grid data - stores the processed data ready for GPU upload
106
- const preloadedDataCache = useRef(new Map());
107
-
108
- // Store geometry and colormap that don't change with forecast hour
109
- const cachedGeometry = useRef(null);
110
- const cachedColormap = useRef(null);
111
- const cachedDataRange = useRef([0, 1]);
112
-
113
- // Track if we've done the initial load
114
- const hasInitialLoad = useRef(false);
115
- const hasPreloadedRef = useRef(false);
116
-
117
- // Track the last state we processed to avoid redundant updates
118
- const lastProcessedState = useRef(null);
119
- const previousStateRef = useRef(null);
120
-
121
- const [renderProps, setRenderProps] = useState({
122
- opacity: 1,
123
- dataRange: [0, 1]
124
- });
125
-
126
- useImperativeHandle(ref, () => {
127
- const setAutoRefresh = (enabled, intervalSeconds) => {
128
- if (autoRefreshIntervalId.current) {
129
- clearInterval(autoRefreshIntervalId.current);
130
- autoRefreshIntervalId.current = null;
131
- }
132
- if (enabled) {
133
- const effectiveInterval = (intervalSeconds || autoRefreshInterval || 30) * 1000;
134
- // Run once immediately, then start the interval
135
- _checkForUpdates();
136
- autoRefreshIntervalId.current = setInterval(_checkForUpdates, effectiveInterval);
137
- }
138
- };
139
- return {
140
- play: () => {
141
- core.play();
142
- },
143
- pause: () => {
144
- core.pause();
145
- },
146
- togglePlay: () => {
147
- core.togglePlay();
148
- },
149
- step: (direction) => {
150
- core.step(direction);
151
- },
152
- setPlaybackSpeed: (speed) => {
153
- if (speed > 0) {
154
- core.playbackSpeed = speed;
155
- if (core.isPlaying) {
156
- core.pause();
157
- core.play();
158
- }
159
- }
160
- },
161
- setOpacity: (opacity) => core.setOpacity(opacity),
162
- setUnits: (units) => core.setUnits(units),
163
- switchMode: (options) => core.switchMode(options),
164
- getAvailableVariables: (model) => core.getAvailableVariables(model),
165
- getVariableDisplayName: (code) => core.getVariableDisplayName(code),
166
- setRun: (runString) => core.setState({ run: runString.split(':')[1] }),
167
- setState: (newState) => core.setState(newState),
168
- setMRMSTimestamp: (timestamp) => core.setMRMSTimestamp(timestamp),
169
- setSmoothing: (enabled) => {
170
- if (gridLayerRef.current) {
171
- gridLayerRef.current.setSmoothing(enabled);
172
- }
173
- },
174
- setAutoRefresh,
175
- refreshData: () => {
176
- _checkForUpdates();
177
- },
178
- };
179
- }, [core, autoRefreshInterval, _checkForUpdates]);
180
-
181
- const preloadAllFramesToDisk = async (state) => {
182
- if (hasPreloadedRef.current) {
183
- return;
184
- }
185
-
186
- const { isMRMS, model, date, run, variable, units, availableHours, availableTimestamps, forecastHour, mrmsTimestamp } = state;
187
-
188
- // CRITICAL: Don't start preloading if we don't have a valid current frame
189
- if (isMRMS && (mrmsTimestamp == null || !availableTimestamps || availableTimestamps.length === 0)) {
190
- hasPreloadedRef.current = false;
191
- return;
192
- }
193
-
194
- if (!isMRMS && (forecastHour == null || !availableHours || availableHours.length === 0)) {
195
- hasPreloadedRef.current = false;
196
- return;
197
- }
198
-
199
- // Only mark as "has preloaded" after validation passes
200
- hasPreloadedRef.current = true;
201
-
202
- // Fix the current forecast hour if it's invalid for this variable/model combo
203
- let effectiveForecastHour = forecastHour;
204
- if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
205
- const validHours = availableHours.filter(hour => hour !== 0);
206
- effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
207
- }
208
-
209
- if (!cachedGeometry.current || !cachedColormap.current) {
210
- const gridModel = isMRMS ? 'mrms' : model;
211
- const { corners, gridDef } = core._getGridCornersAndDef(gridModel);
212
- gridLayerRef.current.updateGeometry(corners, gridDef);
213
- cachedGeometry.current = { model: gridModel, variable };
214
-
215
- const { colormap, baseUnit } = core._getColormapForVariable(variable);
216
- const toUnit = core._getTargetUnit(baseUnit, units);
217
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
218
- let dataRange;
219
- if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
220
- dataRange = isMRMS ? [5, 380] : [5, 380];
221
- } else {
222
- dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
223
- }
224
- const colormapBytes = _generateColormapBytes(finalColormap);
225
- const colormapAsBase64 = fromByteArray(colormapBytes);
226
-
227
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
228
- cachedColormap.current = { key: `${variable}-${units}` };
229
- cachedDataRange.current = dataRange;
230
-
231
- setRenderProps({ opacity: state.opacity, dataRange: dataRange });
232
- hasInitialLoad.current = true;
233
- }
234
-
235
- // Apply the same filtering logic as in AguaceroCore._emitStateChange
236
- let filteredHours = availableHours;
237
- if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && availableHours && availableHours.length > 0) {
238
- filteredHours = availableHours.filter(hour => hour !== 0);
239
- }
240
-
241
- const allFrames = isMRMS ? availableTimestamps : filteredHours;
242
- if (!allFrames || allFrames.length === 0) {
243
- return;
244
- }
245
-
246
- const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
247
-
248
- // Double-check currentFrame is valid
249
- if (currentFrame == null) {
250
- hasPreloadedRef.current = false;
251
- }
252
-
253
- // Reverse the frame order to load from last to first
254
- const reversedFrames = [...allFrames].reverse();
255
- const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
256
-
257
- const { corners, gridDef } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
258
- const { nx, ny } = gridDef.grid_params;
259
-
260
- // Load the current frame FIRST and WAIT for it before continuing
261
- const currentCacheKey = isMRMS ? `mrms-${currentFrame}-${variable}` : `${model}-${date}-${run}-${currentFrame}-${variable}`;
262
-
263
- if (!preloadedDataCache.current.has(currentCacheKey)) {
264
- let resourcePath;
265
- if (isMRMS) {
266
- const frameDate = new Date(currentFrame * 1000);
267
- const y = frameDate.getUTCFullYear();
268
- const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
269
- const d = frameDate.getUTCDate().toString().padStart(2, '0');
270
- resourcePath = `/grids/mrms/${y}${m}${d}/${currentFrame}/0/${variable}/0`;
271
- } else {
272
- resourcePath = `/grids/${model}/${date}/${run}/${currentFrame}/${variable}/0`;
273
- }
274
-
275
- const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
276
- const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
277
-
278
- try {
279
- const result = await WeatherFrameProcessorModule.processFrame(options);
280
-
281
- if (!result || !result.filePath) {
282
- return;
283
- }
284
-
285
- const { baseUnit } = core._getColormapForVariable(variable);
286
-
287
- const toUnit = core._getTargetUnit(baseUnit, units);
288
-
289
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
290
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
291
-
292
- let dataScale = result.scale;
293
- let dataOffset = result.offset;
294
-
295
- let convertedScale = dataScale;
296
- let convertedOffset = dataOffset;
297
-
298
- if (serverDataUnit !== baseUnit) {
299
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
300
- if (conversionFunc) {
301
- if (result.scaleType === 'sqrt') {
302
- const physicalAtOffset = dataOffset * dataOffset;
303
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
304
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
305
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
306
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
307
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
308
- convertedScale = newOffsetPlusScale - convertedOffset;
309
- } else {
310
- convertedOffset = conversionFunc(dataOffset);
311
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
312
- convertedScale = convertedOffsetPlusScale - convertedOffset;
313
- }
314
- dataScale = convertedScale;
315
- dataOffset = convertedOffset;
316
- }
317
- }
318
-
319
- if (baseUnit !== toUnit) {
320
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
321
- if (conversionFunc) {
322
- if (result.scaleType === 'sqrt') {
323
- const physicalAtOffset = dataOffset * dataOffset;
324
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
325
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
326
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
327
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
328
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
329
- convertedScale = newOffsetPlusScale - convertedOffset;
330
- } else {
331
- convertedOffset = conversionFunc(dataOffset);
332
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
333
- convertedScale = convertedOffsetPlusScale - convertedOffset;
334
- }
335
- }
336
- }
337
-
338
- const frameData = {
339
- filePath: result.filePath,
340
- nx, ny,
341
- scale: convertedScale,
342
- offset: convertedOffset,
343
- missing: result.missing,
344
- corners,
345
- gridDef,
346
- scaleType: result.scaleType,
347
- originalScale: result.scale,
348
- originalOffset: result.offset
349
- };
350
-
351
- preloadedDataCache.current.set(currentCacheKey, frameData);
352
-
353
- // Update the GPU with the current frame
354
- gridLayerRef.current.updateDataTextureFromFile(
355
- frameData.filePath,
356
- frameData.nx, frameData.ny,
357
- frameData.scale, frameData.offset, frameData.missing,
358
- frameData.scaleType
359
- );
360
-
361
- currentGridDataRef.current = {
362
- nx: frameData.nx,
363
- ny: frameData.ny,
364
- scale: frameData.scale,
365
- offset: frameData.offset,
366
- missing: frameData.missing,
367
- gridDef: frameData.gridDef,
368
- variable: variable,
369
- units: units,
370
- scaleType: frameData.scaleType
371
- };
372
- } catch (error) {
373
- console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${currentFrame}:`, error);
374
- hasPreloadedRef.current = false;
375
- }
376
- }
377
-
378
- // NOW preload the rest of the frames asynchronously
379
- framesToPreload.forEach((frame) => {
380
- const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
381
- if (preloadedDataCache.current.has(cacheKey)) {
382
- return;
383
- }
384
-
385
- let resourcePath;
386
- if (isMRMS) {
387
- const frameDate = new Date(frame * 1000);
388
- const y = frameDate.getUTCFullYear();
389
- const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
390
- const d = frameDate.getUTCDate().toString().padStart(2, '0');
391
- resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${variable}/0`;
392
- } else {
393
- resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
394
- }
395
-
396
- const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
397
- const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
398
-
399
- WeatherFrameProcessorModule.processFrame(options)
400
- .then(result => {
401
- if (!result || !result.filePath) {
402
- console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}: No filePath`);
403
- return;
404
- }
405
-
406
- // ADD: Same two-step conversion as the current frame
407
- const { baseUnit } = core._getColormapForVariable(variable);
408
- const toUnit = core._getTargetUnit(baseUnit, units);
409
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
410
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
411
-
412
- let dataScale = result.scale;
413
- let dataOffset = result.offset;
414
-
415
- let convertedScale = dataScale;
416
- let convertedOffset = dataOffset;
417
-
418
- // Step 1: Convert from server unit to colormap base unit
419
- if (serverDataUnit !== baseUnit) {
420
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
421
- if (conversionFunc) {
422
- if (result.scaleType === 'sqrt') {
423
- const physicalAtOffset = dataOffset * dataOffset;
424
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
425
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
426
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
427
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
428
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
429
- convertedScale = newOffsetPlusScale - convertedOffset;
430
- } else {
431
- convertedOffset = conversionFunc(dataOffset);
432
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
433
- convertedScale = convertedOffsetPlusScale - convertedOffset;
434
- }
435
- dataScale = convertedScale;
436
- dataOffset = convertedOffset;
437
- }
438
- }
439
-
440
- // Step 2: Convert from colormap base unit to target display unit
441
- if (baseUnit !== toUnit) {
442
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
443
- if (conversionFunc) {
444
- if (result.scaleType === 'sqrt') {
445
- const physicalAtOffset = dataOffset * dataOffset;
446
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
447
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
448
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
449
- convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
450
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
451
- convertedScale = newOffsetPlusScale - convertedOffset;
452
- } else {
453
- convertedOffset = conversionFunc(dataOffset);
454
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
455
- convertedScale = convertedOffsetPlusScale - convertedOffset;
456
- }
457
- }
458
- }
459
-
460
- const frameData = {
461
- filePath: result.filePath,
462
- nx, ny,
463
- scale: convertedScale,
464
- offset: convertedOffset,
465
- missing: result.missing,
466
- corners,
467
- gridDef,
468
- scaleType: result.scaleType,
469
- originalScale: result.scale,
470
- originalOffset: result.offset
471
- };
472
-
473
- preloadedDataCache.current.set(cacheKey, frameData);
474
-
475
- if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
476
- const frameInfoForGpu = {
477
- [cacheKey]: {
478
- filePath: frameData.filePath,
479
- nx: frameData.nx,
480
- ny: frameData.ny,
481
- scale: frameData.scale,
482
- offset: frameData.offset,
483
- missing: frameData.missing,
484
- scaleType: frameData.scaleType || 'linear',
485
- originalScale: frameData.originalScale,
486
- originalOffset: frameData.originalOffset
487
- }
488
- };
489
- gridLayerRef.current.primeGpuCache(frameInfoForGpu);
490
- }
491
- })
492
- .catch(error => {
493
- console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}:`, error);
494
- });
495
- });
496
- };
497
-
498
- useEffect(() => {
499
- // This effect manages the auto-refresh based on props
500
- if (autoRefresh) {
501
- const interval = (autoRefreshInterval || 30) * 1000;
502
- _checkForUpdates(); // Run immediately on enable
503
- autoRefreshIntervalId.current = setInterval(_checkForUpdates, interval);
504
- }
505
-
506
- // Cleanup function: this runs when the component unmounts or props change
507
- return () => {
508
- if (autoRefreshIntervalId.current) {
509
- clearInterval(autoRefreshIntervalId.current);
510
- autoRefreshIntervalId.current = null;
511
- }
512
- };
513
- }, [autoRefresh, autoRefreshInterval, _checkForUpdates]);
514
-
515
- const updateGPUWithCachedData = (state) => {
516
- const { model, date, run, forecastHour, variable, units, isMRMS, mrmsTimestamp } = state;
517
-
518
- const cacheKey = isMRMS
519
- ? `mrms-${mrmsTimestamp}-${variable}`
520
- : `${model}-${date}-${run}-${forecastHour}-${variable}`;
521
-
522
- if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
523
- // Get the cached data BEFORE calling setActiveFrame
524
- const cachedData = preloadedDataCache.current.get(cacheKey);
525
-
526
- if (cachedData) {
527
- currentGridDataRef.current = {
528
- nx: cachedData.nx,
529
- ny: cachedData.ny,
530
- scale: cachedData.scale,
531
- offset: cachedData.offset,
532
- missing: cachedData.missing,
533
- gridDef: cachedData.gridDef,
534
- variable: variable,
535
- units: units,
536
- scaleType: cachedData.scaleType
537
- };
538
- }
539
-
540
- // Now call setActiveFrame (which will async update the native cache)
541
- gridLayerRef.current.setActiveFrame(cacheKey);
542
- return true;
543
- }
544
-
545
- const cachedData = preloadedDataCache.current.get(cacheKey);
546
-
547
- if (!cachedData) {
548
- return false;
549
- }
550
-
551
- if (!gridLayerRef.current) {
552
- console.warn(`⚠️ [updateGPUWithCachedData] GridLayer ref not available`); // CHANGED
553
- return false;
554
- }
555
-
556
- if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
557
- gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
558
- cachedGeometry.current = { model: (isMRMS ? 'mrms' : model), variable };
559
- }
560
-
561
- const colormapKey = `${variable}-${units}`;
562
- if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
563
- const { colormap, baseUnit } = core._getColormapForVariable(variable);
564
- const toUnit = core._getTargetUnit(baseUnit, units);
565
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
566
- let dataRange;
567
- if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
568
- if (isMRMS) {
569
- dataRange = [5, 380];
570
- } else {
571
- dataRange = [5, 380];
572
- }
573
- } else {
574
- dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
575
- }
576
- const colormapBytes = _generateColormapBytes(finalColormap);
577
- const colormapAsBase64 = fromByteArray(colormapBytes);
578
-
579
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
580
- cachedColormap.current = { key: colormapKey };
581
- cachedDataRange.current = dataRange;
582
-
583
- setRenderProps(prev => ({ ...prev, dataRange }));
584
- }
585
-
586
- if (cachedData.filePath) {
587
- gridLayerRef.current.updateDataTextureFromFile(
588
- cachedData.filePath,
589
- cachedData.nx, cachedData.ny,
590
- cachedData.scale, cachedData.offset, cachedData.missing,
591
- cachedData.scaleType
592
- );
593
-
594
- // ADD THIS: Update inspector cache for file-based data too
595
- currentGridDataRef.current = {
596
- nx: cachedData.nx,
597
- ny: cachedData.ny,
598
- scale: cachedData.scale,
599
- offset: cachedData.offset,
600
- missing: cachedData.missing,
601
- gridDef: cachedData.gridDef,
602
- variable: variable,
603
- units: units
604
- };
605
- } else if (cachedData.dataAsBase64) {
606
- gridLayerRef.current.updateDataTexture(
607
- cachedData.dataAsBase64,
608
- cachedData.nx, cachedData.ny,
609
- cachedData.scale, cachedData.offset, cachedData.missing,
610
- cachedData.scaleType
611
- );
612
-
613
- // Update the inspector cache when using dataAsBase64
614
- const binaryString = atob(cachedData.dataAsBase64);
615
- const uint8Array = new Uint8Array(binaryString.length);
616
-
617
- for (let i = 0; i < binaryString.length; i++) {
618
- uint8Array[i] = binaryString.charCodeAt(i);
619
- }
620
-
621
- currentGridDataRef.current = {
622
- data: uint8Array,
623
- nx: cachedData.nx,
624
- ny: cachedData.ny,
625
- scale: cachedData.scale,
626
- offset: cachedData.offset,
627
- missing: cachedData.missing,
628
- gridDef: cachedData.gridDef,
629
- variable: variable,
630
- units: units
631
- };
632
- } else {
633
- console.error(`❌ [updateGPUWithCachedData] Cached data has no filePath or dataAsBase64!`);
634
- console.error('❌ [updateGPUWithCachedData] Cached data keys:', Object.keys(cachedData));
635
- return false;
636
- }
637
-
638
- // Update inspector parameters for file-based data too
639
- if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
640
- gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
641
- }
642
- return true;
643
- };
644
-
645
- const handleStateChangeRef = useRef(null);
646
- const debounceTimeoutRef = useRef(null);
647
-
648
- useEffect(() => {
649
- if (core && props.customColormaps) {
650
- core.customColormaps = props.customColormaps;
651
- // Trigger a re-render if we already have data loaded
652
- if (hasInitialLoad.current) {
653
- core._emitStateChange();
654
- }
655
- }
656
- }, [core, props.customColormaps]);
657
-
658
- const getValueAtPoint = async (lng, lat) => {
659
- if (!core) {
660
- console.warn('🔍 [Inspector] Core not available');
661
- return null;
662
- }
663
-
664
- // ADD THIS: Check if we have valid data before attempting inspection
665
- if (!currentGridDataRef.current) {
666
- return null;
667
- }
668
-
669
- try {
670
- const gridIndices = core._getGridIndexFromLngLat(lng, lat);
671
- if (!gridIndices) return null;
672
-
673
- const { i, j } = gridIndices;
674
-
675
- const value = await InspectorModule.getValueAtGridIndex(i, j);
676
-
677
- if (value === null) {
678
- return null;
679
- }
680
-
681
- const { colormap, baseUnit } = core._getColormapForVariable(core.state.variable);
682
- const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
683
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
684
- const minThreshold = finalColormap[0];
685
-
686
- if (value < minThreshold) {
687
- return null;
688
- }
689
-
690
- // Filter out values below the minimum threshold (matching shader behavior)
691
- if (value < minThreshold) {
692
- return null;
693
- }
694
-
695
- // Also check if value is NaN or effectively missing
696
- if (!isFinite(value)) {
697
- return null;
698
- }
699
-
700
- return {
701
- value: value,
702
- unit: displayUnit,
703
- variable: {
704
- code: core.state.variable,
705
- name: core.getVariableDisplayName(core.state.variable)
706
- },
707
- lngLat: { lng, lat }
708
- };
709
- } catch (error) {
710
- console.error('🔍 [Inspector] Error:', error);
711
- return null;
712
- }
713
- };
714
-
715
- const _checkForUpdates = useMemo(() => async () => {
716
- if (!core) return;
717
- const { isMRMS, model: currentModel, variable: currentVariable, date, run } = core.state;
718
-
719
- if (isMRMS) {
720
- // --- MRMS LOGIC WITH PRE-LOADING ---
721
- const oldTimestamps = new Set(core.mrmsStatus?.[currentVariable] || []);
722
- const mrmsStatus = await core.fetchMRMSStatus(true);
723
- const newTimestamps = mrmsStatus?.[currentVariable] || [];
724
- if (newTimestamps.length === 0) return;
725
-
726
- const newTimestampsToPreload = newTimestamps.filter(ts => !oldTimestamps.has(ts));
727
-
728
- if (newTimestampsToPreload.length > 0) {
729
- core.mrmsStatus = mrmsStatus;
730
- core._emitStateChange(); // Update UI slider without changing selection
731
-
732
- const { corners, gridDef } = core._getGridCornersAndDef('mrms');
733
- const { nx, ny } = gridDef.grid_params;
734
-
735
- newTimestampsToPreload.forEach(frame => {
736
- const cacheKey = `mrms-${frame}-${currentVariable}`;
737
- if (preloadedDataCache.current.has(cacheKey)) return;
738
-
739
- const frameDate = new Date(frame * 1000);
740
- const y = frameDate.getUTCFullYear(), m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0'), d = frameDate.getUTCDate().toString().padStart(2, '0');
741
-
742
- // --- THIS IS THE FIX ---
743
- // Changed 'variable' to 'currentVariable'
744
- const resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${currentVariable}/0`;
745
- // --- END FIX ---
746
-
747
- const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
748
-
749
- WeatherFrameProcessorModule.processFrame({ url, apiKey: core.apiKey, bundleId: core.bundleId })
750
- .then(result => {
751
- if (!result || !result.filePath) return;
752
- const frameData = { filePath: result.filePath, nx, ny, scale: result.scale, offset: result.offset, missing: result.missing, corners, gridDef, scaleType: result.scaleType, originalScale: result.scale, originalOffset: result.offset };
753
- preloadedDataCache.current.set(cacheKey, frameData);
754
- if (Platform.OS === 'ios' && gridLayerRef.current?.primeGpuCache) {
755
- gridLayerRef.current.primeGpuCache({ [cacheKey]: frameData });
756
- }
757
- }).catch(error => console.warn(`[Auto-Refresh] Failed to preload frame ${frame}:`, error));
758
- });
759
-
760
- const newTimestampsSet = new Set(newTimestamps);
761
- oldTimestamps.forEach(oldTs => {
762
- if (!newTimestampsSet.has(oldTs)) {
763
- const cacheKey = `mrms-${oldTs}-${currentVariable}`;
764
- preloadedDataCache.current.delete(cacheKey);
765
- }
766
- });
767
- }
768
- } else {
769
- // --- MODEL LOGIC ---
770
- const modelStatus = await core.fetchModelStatus(true);
771
- const latestRun = findLatestModelRun(modelStatus, currentModel);
772
- if (!latestRun) return;
773
-
774
- const currentRunKey = `${date}:${run}`;
775
- const latestRunKey = `${latestRun.date}:${latestRun.run}`;
776
-
777
- if (latestRunKey > currentRunKey) {
778
- // This preserves the current forecastHour while changing the run
779
- await core.setState({
780
- date: latestRun.date,
781
- run: latestRun.run,
782
- });
783
- }
784
- }
785
- }, [core]);
786
-
787
- useEffect(() => {
788
- if (!core) {
789
- console.warn('⚠️ [useEffect] Core is not available yet');
790
- return;
791
- }
792
-
793
- const handleStateChange = async (newState) => {
794
- props.onStateChange?.(newState);
795
-
796
- if (!previousStateRef.current) {
797
- previousStateRef.current = core.state;
798
- }
799
-
800
- const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
801
-
802
- if (variableChanged && gridLayerRef.current?.setVariable) {
803
- gridLayerRef.current.setVariable(newState.variable);
804
- }
805
-
806
- const stateKey = `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
807
-
808
- const isOpacityOnlyChange =
809
- hasInitialLoad.current &&
810
- newState.opacity !== renderProps.opacity &&
811
- newState.variable === previousStateRef.current?.variable &&
812
- newState.forecastHour === previousStateRef.current?.forecastHour &&
813
- newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
814
- newState.model === previousStateRef.current?.model &&
815
- newState.units === previousStateRef.current?.units;
816
-
817
- const isPlayStateOnlyChange =
818
- hasInitialLoad.current &&
819
- newState.isPlaying !== previousStateRef.current?.isPlaying &&
820
- newState.variable === previousStateRef.current?.variable &&
821
- newState.forecastHour === previousStateRef.current?.forecastHour &&
822
- newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
823
- newState.model === previousStateRef.current?.model &&
824
- newState.units === previousStateRef.current?.units &&
825
- newState.opacity === previousStateRef.current?.opacity;
826
-
827
- if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
828
- previousStateRef.current = newState;
829
- return;
830
- }
831
-
832
- if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
833
- lastProcessedState.current = stateKey;
834
- }
835
-
836
- if (isOpacityOnlyChange) {
837
- setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
838
- previousStateRef.current = newState;
839
- return;
840
- }
841
-
842
- if (isPlayStateOnlyChange) {
843
- previousStateRef.current = newState;
844
- return;
845
- }
846
-
847
- const isUnitsOnlyChange =
848
- hasInitialLoad.current &&
849
- newState.model === previousStateRef.current.model &&
850
- newState.isMRMS === previousStateRef.current.isMRMS &&
851
- newState.variable === previousStateRef.current.variable &&
852
- newState.date === previousStateRef.current.date &&
853
- newState.run === previousStateRef.current.run &&
854
- newState.forecastHour === previousStateRef.current.forecastHour &&
855
- newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
856
- newState.units !== previousStateRef.current.units;
857
-
858
- if (isUnitsOnlyChange) {
859
- const { variable, units, isMRMS, mrmsTimestamp, model, date, run, forecastHour } = newState;
860
- const oldCacheKey = isMRMS
861
- ? `mrms-${mrmsTimestamp}-${variable}`
862
- : `${model}-${date}-${run}-${forecastHour}-${variable}`;
863
-
864
- const cachedData = preloadedDataCache.current.get(oldCacheKey);
865
-
866
- if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
867
- const { baseUnit } = core._getColormapForVariable(variable);
868
- const toUnit = core._getTargetUnit(baseUnit, units);
869
- const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
870
- const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
871
-
872
- let dataScale = cachedData.originalScale;
873
- let dataOffset = cachedData.originalOffset;
874
-
875
- if (serverDataUnit !== baseUnit) {
876
- const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
877
- if (conversionFunc) {
878
- if (cachedData.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
- const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
884
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
885
- dataScale = newOffsetPlusScale - newOffset;
886
- dataOffset = newOffset;
887
- } else {
888
- const convertedOffset = conversionFunc(dataOffset);
889
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
890
- dataScale = convertedOffsetPlusScale - convertedOffset;
891
- dataOffset = convertedOffset;
892
- }
893
- }
894
- }
895
-
896
- if (baseUnit !== toUnit) {
897
- const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
898
- if (conversionFunc) {
899
- if (cachedData.scaleType === 'sqrt') {
900
- const physicalAtOffset = dataOffset * dataOffset;
901
- const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
902
- const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
903
- const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
904
- const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
905
- const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
906
- dataScale = newOffsetPlusScale - newOffset;
907
- dataOffset = newOffset;
908
- } else {
909
- const convertedOffset = conversionFunc(dataOffset);
910
- const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
911
- dataScale = convertedOffsetPlusScale - convertedOffset;
912
- dataOffset = convertedOffset;
913
- }
914
- }
915
- }
916
-
917
- const { colormap } = core._getColormapForVariable(variable);
918
- const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
919
- let dataRange = (variable === 'ptypeRefl' || variable === 'ptypeRate') ? [5, 380] : [finalColormap[0], finalColormap[finalColormap.length - 2]];
920
- const colormapBytes = _generateColormapBytes(finalColormap);
921
- const colormapAsBase64 = fromByteArray(colormapBytes);
922
-
923
- gridLayerRef.current.updateColormapTexture(colormapAsBase64);
924
- cachedColormap.current = { key: `${variable}-${units}` };
925
- cachedDataRange.current = dataRange;
926
- setRenderProps(prev => ({ ...prev, dataRange, opacity: newState.opacity }));
927
-
928
- if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
929
- const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0;
930
- gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue);
931
- }
932
-
933
- const newCacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
934
- preloadedDataCache.current.set(newCacheKey, { ...cachedData, scale: dataScale, offset: dataOffset });
935
- }
936
-
937
- previousStateRef.current = newState;
938
- return;
939
- }
940
-
941
- const needsFullLoad =
942
- !hasInitialLoad.current ||
943
- newState.model !== previousStateRef.current.model ||
944
- newState.isMRMS !== previousStateRef.current.isMRMS ||
945
- newState.variable !== previousStateRef.current.variable ||
946
- newState.date !== previousStateRef.current.date ||
947
- newState.run !== previousStateRef.current.run;
948
-
949
- if (needsFullLoad) {
950
- if (gridLayerRef.current) {
951
- gridLayerRef.current.setVariable(newState.variable);
952
- gridLayerRef.current.clear();
953
- if (Platform.OS === 'ios' && gridLayerRef.current.clearGpuCache) {
954
- gridLayerRef.current.clearGpuCache();
955
- }
956
- }
957
- hasPreloadedRef.current = false;
958
- preloadedDataCache.current.clear();
959
- cachedGeometry.current = null;
960
- cachedColormap.current = null;
961
- currentGridDataRef.current = null;
962
- WeatherFrameProcessorModule.cancelAllFrames();
963
-
964
- if (!newState.variable) {
965
- previousStateRef.current = newState;
966
- return;
967
- }
968
- preloadAllFramesToDisk(newState);
969
- } else if (newState.forecastHour !== previousStateRef.current.forecastHour || (newState.isMRMS && newState.mrmsTimestamp !== previousStateRef.current.mrmsTimestamp)) {
970
- const success = updateGPUWithCachedData(newState);
971
- if (success && newState.opacity !== renderProps.opacity) {
972
- setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
973
- }
974
- }
975
-
976
- previousStateRef.current = newState;
977
- };
978
- // --- END REPLACEMENT ---
979
-
980
- handleStateChangeRef.current = handleStateChange;
981
-
982
- const stableHandler = (newState) => {
983
- const isOpacityOnlyChange =
984
- previousStateRef.current &&
985
- newState.opacity !== previousStateRef.current.opacity &&
986
- newState.variable === previousStateRef.current.variable &&
987
- newState.forecastHour === previousStateRef.current.forecastHour &&
988
- newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
989
- newState.model === previousStateRef.current.model &&
990
- newState.units === previousStateRef.current.units &&
991
- newState.date === previousStateRef.current.date &&
992
- newState.run === previousStateRef.current.run;
993
-
994
- if (isOpacityOnlyChange) {
995
- if (handleStateChangeRef.current) {
996
- handleStateChangeRef.current(newState);
997
- }
998
- return;
999
- }
1000
-
1001
- if (debounceTimeoutRef.current) {
1002
- clearTimeout(debounceTimeoutRef.current);
1003
- }
1004
-
1005
- debounceTimeoutRef.current = setTimeout(() => {
1006
- if (handleStateChangeRef.current) {
1007
- handleStateChangeRef.current(newState);
1008
- }
1009
- debounceTimeoutRef.current = null;
1010
- }, 50);
1011
- };
1012
-
1013
- core.on('state:change', stableHandler);
1014
-
1015
- return () => {
1016
- core.off('state:change', stableHandler);
1017
- if (debounceTimeoutRef.current) {
1018
- clearTimeout(debounceTimeoutRef.current);
1019
- }
1020
- };
1021
- }, [core]);
1022
-
1023
- useEffect(() => {
1024
- return () => {
1025
- preloadedDataCache.current.clear();
1026
- hasInitialLoad.current = false;
1027
- lastProcessedState.current = null;
1028
- };
1029
- }, []);
1030
-
1031
- const lastInspectorUpdateRef = useRef(0);
1032
- const INSPECTOR_THROTTLE_MS = 50;
1033
-
1034
- useEffect(() => {
1035
- if (!core || !inspectorEnabled) {
1036
- return;
1037
- }
1038
-
1039
- const handleMapMove = async (center) => {
1040
- if (!center || !Array.isArray(center) || center.length !== 2) {
1041
- return;
1042
- }
1043
-
1044
- // Throttle updates
1045
- const now = Date.now();
1046
- if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
1047
- return;
1048
- }
1049
- lastInspectorUpdateRef.current = now;
1050
-
1051
- const [longitude, latitude] = center;
1052
-
1053
- const payload = await getValueAtPoint(longitude, latitude);
1054
- onInspect?.(payload);
1055
- };
1056
-
1057
- core.on('map:move', handleMapMove);
1058
-
1059
- if (context && context.getCenter) {
1060
- const center = context.getCenter();
1061
- if (center) {
1062
- handleMapMove(center);
1063
- }
1064
- }
1065
-
1066
- return () => {
1067
- core.off('map:move', handleMapMove);
1068
- };
1069
- }, [inspectorEnabled, onInspect, core, context]);
1070
-
1071
- useEffect(() => {
1072
- if (!core || !inspectorEnabled) {
1073
- return;
1074
- }
1075
-
1076
- const triggerReinspection = () => {
1077
- const mapRef = mapRegistry.getMap();
1078
- const center = mapRef?._currentCenter;
1079
-
1080
- if (center && Array.isArray(center) && center.length === 2) {
1081
- const [longitude, latitude] = center;
1082
-
1083
- getValueAtPoint(longitude, latitude).then(payload => {
1084
- onInspect?.(payload);
1085
- });
1086
- }
1087
- };
1088
-
1089
- // Small delay to ensure data is loaded before re-inspecting
1090
- const timer = setTimeout(triggerReinspection, 100);
1091
-
1092
- return () => clearTimeout(timer);
1093
- }, [
1094
- core?.state?.variable,
1095
- core?.state?.model,
1096
- core?.state?.forecastHour,
1097
- core?.state?.mrmsTimestamp,
1098
- core?.state?.units,
1099
- inspectorEnabled,
1100
- onInspect
1101
- ]);
1102
-
1103
- useEffect(() => {
1104
- if (!core) {
1105
- return;
1106
- }
1107
-
1108
- const handleCameraChange = (center) => {
1109
- if (core && center) {
1110
- core.setMapCenter(center);
1111
- }
1112
- };
1113
-
1114
- // Register with the global registry
1115
- mapRegistry.addCameraListener(handleCameraChange);
1116
-
1117
- // Try to get initial center
1118
- const mapRef = mapRegistry.getMap();
1119
- if (mapRef?._currentCenter) {
1120
- handleCameraChange(mapRef._currentCenter);
1121
- }
1122
-
1123
- return () => {
1124
- mapRegistry.removeCameraListener(handleCameraChange);
1125
- };
1126
- }, [core]);
1127
-
1128
- useEffect(() => {
1129
- core.initialize();
1130
- return () => {
1131
- core.destroy();
1132
- };
1133
- }, [core]);
1134
-
1135
- return (
1136
- <GridRenderLayer
1137
- ref={gridLayerRef}
1138
- opacity={renderProps.opacity}
1139
- dataRange={renderProps.dataRange}
1140
- belowID="AML_-_terrain"
1141
- />
1142
- );
1143
- });
1144
-
1145
- WeatherLayerManager.getAvailableVariables = (options) => {
1146
- if (!options || !options.apiKey) {
1147
- console.error("API key must be provided to get available variables.");
1148
- return [];
1149
- }
1150
- const core = new AguaceroCore({ apiKey: options.apiKey });
1151
- return core.getAvailableVariables('mrms');
1
+ // packages/react-native/src/WeatherLayerManager.js
2
+
3
+ import React, { useState, useRef, useContext, useEffect, forwardRef, useImperativeHandle, useMemo } from 'react';
4
+ import { AguaceroCore, getUnitConversionFunction, DICTIONARIES } from '@aguacerowx/javascript-sdk';
5
+ import { AguaceroContext } from './AguaceroContext';
6
+ import { GridRenderLayer } from './GridRenderLayer';
7
+ import { fromByteArray } from 'base64-js';
8
+ import { Platform, NativeModules } from 'react-native';
9
+ import { mapRegistry } from './MapRegistry';
10
+
11
+ function findLatestModelRun(modelsData, modelName) {
12
+ const model = modelsData?.[modelName];
13
+ if (!model) return null;
14
+ const availableDates = Object.keys(model).sort((a, b) => b.localeCompare(a));
15
+ for (const date of availableDates) {
16
+ const runs = model[date];
17
+ if (!runs) continue;
18
+ const availableRuns = Object.keys(runs).sort((a, b) => b.localeCompare(a));
19
+ if (availableRuns.length > 0) return { date: date, run: availableRuns[0] };
20
+ }
21
+ return null;
22
+ }
23
+ const { WeatherFrameProcessorModule, InspectorModule } = NativeModules;
24
+
25
+ /**
26
+ * A helper function to generate the raw RGBA byte buffer for the colormap texture.
27
+ */
28
+ const _generateColormapBytes = (colormap) => {
29
+ const width = 256;
30
+ const data = new Uint8Array(width * 4);
31
+ const stops = colormap.reduce((acc, _, i) => (i % 2 === 0 ? [...acc, { value: colormap[i], color: colormap[i + 1] }] : acc), []);
32
+
33
+ if (stops.length === 0) return data;
34
+
35
+ const minVal = stops[0].value;
36
+ const maxVal = stops[stops.length - 1].value;
37
+
38
+ const hexToRgb = (hex) => {
39
+ const r = parseInt(hex.slice(1, 3), 16);
40
+ const g = parseInt(hex.slice(3, 5), 16);
41
+ const b = parseInt(hex.slice(5, 7), 16);
42
+ return [r, g, b];
43
+ };
44
+
45
+ for (let i = 0; i < width; i++) {
46
+ const val = minVal + (i / (width - 1)) * (maxVal - minVal);
47
+ let lower = stops[0];
48
+ let upper = stops[stops.length - 1];
49
+ for (let j = 0; j < stops.length - 1; j++) {
50
+ if (val >= stops[j].value && val <= stops[j + 1].value) {
51
+ lower = stops[j];
52
+ upper = stops[j + 1];
53
+ break;
54
+ }
55
+ }
56
+ const t = (val - lower.value) / (upper.value - lower.value || 1);
57
+ const lowerRgb = hexToRgb(lower.color);
58
+ const upperRgb = hexToRgb(upper.color);
59
+ const rgb = lowerRgb.map((c, idx) => c * (1 - t) + upperRgb[idx] * t);
60
+
61
+ const offset = i * 4;
62
+ data[offset + 0] = Math.round(rgb[0]);
63
+ data[offset + 1] = Math.round(rgb[1]);
64
+ data[offset + 2] = Math.round(rgb[2]);
65
+ data[offset + 3] = 255;
66
+ }
67
+ return data;
68
+ };
69
+
70
+ AguaceroCore.prototype.setMapCenter = function(center) {
71
+ this.emit('map:move', center);
72
+ };
73
+
74
+ export const WeatherLayerManager = forwardRef((props, ref) => {
75
+ const {
76
+ inspectorEnabled,
77
+ onInspect,
78
+ apiKey,
79
+ customColormaps,
80
+ initialMode,
81
+ initialVariable,
82
+ autoRefresh,
83
+ autoRefreshInterval,
84
+ initialModel,
85
+ ...restProps
86
+ } = props;
87
+ const context = useContext(AguaceroContext);
88
+
89
+ // Create the core here instead of getting it from context
90
+ const core = useMemo(() => new AguaceroCore({
91
+ apiKey: apiKey,
92
+ customColormaps: customColormaps,
93
+ // ADD: Pass layerOptions to the core's constructor
94
+ layerOptions: {
95
+ mode: initialMode,
96
+ variable: initialVariable,
97
+ model: initialModel
98
+ }
99
+ }), [apiKey]);
100
+
101
+ const gridLayerRef = useRef(null);
102
+ const currentGridDataRef = useRef(null);
103
+ const autoRefreshIntervalId = useRef(null);
104
+
105
+ // Cache for preloaded grid data - stores the processed data ready for GPU upload
106
+ const preloadedDataCache = useRef(new Map());
107
+
108
+ // Store geometry and colormap that don't change with forecast hour
109
+ const cachedGeometry = useRef(null);
110
+ const cachedColormap = useRef(null);
111
+ const cachedDataRange = useRef([0, 1]);
112
+
113
+ // Track if we've done the initial load
114
+ const hasInitialLoad = useRef(false);
115
+ const hasPreloadedRef = useRef(false);
116
+
117
+ // Track the last state we processed to avoid redundant updates
118
+ const lastProcessedState = useRef(null);
119
+ const previousStateRef = useRef(null);
120
+
121
+ const [renderProps, setRenderProps] = useState({
122
+ opacity: 1,
123
+ dataRange: [0, 1]
124
+ });
125
+
126
+ useImperativeHandle(ref, () => {
127
+ const setAutoRefresh = (enabled, intervalSeconds) => {
128
+ if (autoRefreshIntervalId.current) {
129
+ clearInterval(autoRefreshIntervalId.current);
130
+ autoRefreshIntervalId.current = null;
131
+ }
132
+ if (enabled) {
133
+ const effectiveInterval = (intervalSeconds || autoRefreshInterval || 30) * 1000;
134
+ // Run once immediately, then start the interval
135
+ _checkForUpdates();
136
+ autoRefreshIntervalId.current = setInterval(_checkForUpdates, effectiveInterval);
137
+ }
138
+ };
139
+ return {
140
+ play: () => {
141
+ core.play();
142
+ },
143
+ pause: () => {
144
+ core.pause();
145
+ },
146
+ togglePlay: () => {
147
+ core.togglePlay();
148
+ },
149
+ step: (direction) => {
150
+ core.step(direction);
151
+ },
152
+ setPlaybackSpeed: (speed) => {
153
+ if (speed > 0) {
154
+ core.playbackSpeed = speed;
155
+ if (core.isPlaying) {
156
+ core.pause();
157
+ core.play();
158
+ }
159
+ }
160
+ },
161
+ setOpacity: (opacity) => core.setOpacity(opacity),
162
+ setUnits: (units) => core.setUnits(units),
163
+ switchMode: (options) => core.switchMode(options),
164
+ getAvailableVariables: (model) => core.getAvailableVariables(model),
165
+ getVariableDisplayName: (code) => core.getVariableDisplayName(code),
166
+ setRun: (runString) => core.setState({ run: runString.split(':')[1] }),
167
+ setState: (newState) => core.setState(newState),
168
+ setMRMSTimestamp: (timestamp) => core.setMRMSTimestamp(timestamp),
169
+ setSmoothing: (enabled) => {
170
+ if (gridLayerRef.current) {
171
+ gridLayerRef.current.setSmoothing(enabled);
172
+ }
173
+ },
174
+ setAutoRefresh,
175
+ refreshData: () => {
176
+ _checkForUpdates();
177
+ },
178
+ };
179
+ }, [core, autoRefreshInterval, _checkForUpdates]);
180
+
181
+ const preloadAllFramesToDisk = async (state) => {
182
+ if (hasPreloadedRef.current) {
183
+ return;
184
+ }
185
+
186
+ const { isMRMS, model, date, run, variable, units, availableHours, availableTimestamps, forecastHour, mrmsTimestamp } = state;
187
+
188
+ // CRITICAL: Don't start preloading if we don't have a valid current frame
189
+ if (isMRMS && (mrmsTimestamp == null || !availableTimestamps || availableTimestamps.length === 0)) {
190
+ hasPreloadedRef.current = false;
191
+ return;
192
+ }
193
+
194
+ if (!isMRMS && (forecastHour == null || !availableHours || availableHours.length === 0)) {
195
+ hasPreloadedRef.current = false;
196
+ return;
197
+ }
198
+
199
+ // Only mark as "has preloaded" after validation passes
200
+ hasPreloadedRef.current = true;
201
+
202
+ // Fix the current forecast hour if it's invalid for this variable/model combo
203
+ let effectiveForecastHour = forecastHour;
204
+ if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
205
+ const validHours = availableHours.filter(hour => hour !== 0);
206
+ effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
207
+ }
208
+
209
+ if (!cachedGeometry.current || !cachedColormap.current) {
210
+ const gridModel = isMRMS ? 'mrms' : model;
211
+ const { corners, gridDef } = core._getGridCornersAndDef(gridModel);
212
+ gridLayerRef.current.updateGeometry(corners, gridDef);
213
+ cachedGeometry.current = { model: gridModel, variable };
214
+
215
+ const { colormap, baseUnit } = core._getColormapForVariable(variable);
216
+ const toUnit = core._getTargetUnit(baseUnit, units);
217
+ const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
218
+ let dataRange;
219
+ if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
220
+ dataRange = isMRMS ? [5, 380] : [5, 380];
221
+ } else {
222
+ dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
223
+ }
224
+ const colormapBytes = _generateColormapBytes(finalColormap);
225
+ const colormapAsBase64 = fromByteArray(colormapBytes);
226
+
227
+ gridLayerRef.current.updateColormapTexture(colormapAsBase64);
228
+ cachedColormap.current = { key: `${variable}-${units}` };
229
+ cachedDataRange.current = dataRange;
230
+
231
+ setRenderProps({ opacity: state.opacity, dataRange: dataRange });
232
+ hasInitialLoad.current = true;
233
+ }
234
+
235
+ // Apply the same filtering logic as in AguaceroCore._emitStateChange
236
+ let filteredHours = availableHours;
237
+ if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && availableHours && availableHours.length > 0) {
238
+ filteredHours = availableHours.filter(hour => hour !== 0);
239
+ }
240
+
241
+ const allFrames = isMRMS ? availableTimestamps : filteredHours;
242
+ if (!allFrames || allFrames.length === 0) {
243
+ return;
244
+ }
245
+
246
+ const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
247
+
248
+ // Double-check currentFrame is valid
249
+ if (currentFrame == null) {
250
+ hasPreloadedRef.current = false;
251
+ }
252
+
253
+ // Reverse the frame order to load from last to first
254
+ const reversedFrames = [...allFrames].reverse();
255
+ const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
256
+
257
+ const { corners, gridDef } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
258
+ const { nx, ny } = gridDef.grid_params;
259
+
260
+ // Load the current frame FIRST and WAIT for it before continuing
261
+ const currentCacheKey = isMRMS ? `mrms-${currentFrame}-${variable}` : `${model}-${date}-${run}-${currentFrame}-${variable}`;
262
+
263
+ if (!preloadedDataCache.current.has(currentCacheKey)) {
264
+ let resourcePath;
265
+ if (isMRMS) {
266
+ const frameDate = new Date(currentFrame * 1000);
267
+ const y = frameDate.getUTCFullYear();
268
+ const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
269
+ const d = frameDate.getUTCDate().toString().padStart(2, '0');
270
+ resourcePath = `/grids/mrms/${y}${m}${d}/${currentFrame}/0/${variable}/0`;
271
+ } else {
272
+ resourcePath = `/grids/${model}/${date}/${run}/${currentFrame}/${variable}/0`;
273
+ }
274
+
275
+ const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
276
+ const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
277
+
278
+ try {
279
+ const result = await WeatherFrameProcessorModule.processFrame(options);
280
+
281
+ if (!result || !result.filePath) {
282
+ return;
283
+ }
284
+
285
+ const { baseUnit } = core._getColormapForVariable(variable);
286
+
287
+ const toUnit = core._getTargetUnit(baseUnit, units);
288
+
289
+ const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
290
+ const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
291
+
292
+ let dataScale = result.scale;
293
+ let dataOffset = result.offset;
294
+
295
+ let convertedScale = dataScale;
296
+ let convertedOffset = dataOffset;
297
+
298
+ if (serverDataUnit !== baseUnit) {
299
+ const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
300
+ if (conversionFunc) {
301
+ if (result.scaleType === 'sqrt') {
302
+ const physicalAtOffset = dataOffset * dataOffset;
303
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
304
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
305
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
306
+ convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
307
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
308
+ convertedScale = newOffsetPlusScale - convertedOffset;
309
+ } else {
310
+ convertedOffset = conversionFunc(dataOffset);
311
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
312
+ convertedScale = convertedOffsetPlusScale - convertedOffset;
313
+ }
314
+ dataScale = convertedScale;
315
+ dataOffset = convertedOffset;
316
+ }
317
+ }
318
+
319
+ if (baseUnit !== toUnit) {
320
+ const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
321
+ if (conversionFunc) {
322
+ if (result.scaleType === 'sqrt') {
323
+ const physicalAtOffset = dataOffset * dataOffset;
324
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
325
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
326
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
327
+ convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
328
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
329
+ convertedScale = newOffsetPlusScale - convertedOffset;
330
+ } else {
331
+ convertedOffset = conversionFunc(dataOffset);
332
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
333
+ convertedScale = convertedOffsetPlusScale - convertedOffset;
334
+ }
335
+ }
336
+ }
337
+
338
+ const frameData = {
339
+ filePath: result.filePath,
340
+ nx, ny,
341
+ scale: convertedScale,
342
+ offset: convertedOffset,
343
+ missing: result.missing,
344
+ corners,
345
+ gridDef,
346
+ scaleType: result.scaleType,
347
+ originalScale: result.scale,
348
+ originalOffset: result.offset
349
+ };
350
+
351
+ preloadedDataCache.current.set(currentCacheKey, frameData);
352
+
353
+ // Update the GPU with the current frame
354
+ gridLayerRef.current.updateDataTextureFromFile(
355
+ frameData.filePath,
356
+ frameData.nx, frameData.ny,
357
+ frameData.scale, frameData.offset, frameData.missing,
358
+ frameData.scaleType
359
+ );
360
+
361
+ currentGridDataRef.current = {
362
+ nx: frameData.nx,
363
+ ny: frameData.ny,
364
+ scale: frameData.scale,
365
+ offset: frameData.offset,
366
+ missing: frameData.missing,
367
+ gridDef: frameData.gridDef,
368
+ variable: variable,
369
+ units: units,
370
+ scaleType: frameData.scaleType
371
+ };
372
+ } catch (error) {
373
+ console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${currentFrame}:`, error);
374
+ hasPreloadedRef.current = false;
375
+ }
376
+ }
377
+
378
+ // NOW preload the rest of the frames asynchronously
379
+ framesToPreload.forEach((frame) => {
380
+ const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
381
+ if (preloadedDataCache.current.has(cacheKey)) {
382
+ return;
383
+ }
384
+
385
+ let resourcePath;
386
+ if (isMRMS) {
387
+ const frameDate = new Date(frame * 1000);
388
+ const y = frameDate.getUTCFullYear();
389
+ const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
390
+ const d = frameDate.getUTCDate().toString().padStart(2, '0');
391
+ resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${variable}/0`;
392
+ } else {
393
+ resourcePath = `/grids/${model}/${date}/${run}/${frame}/${variable}/0`;
394
+ }
395
+
396
+ const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
397
+ const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
398
+
399
+ WeatherFrameProcessorModule.processFrame(options)
400
+ .then(result => {
401
+ if (!result || !result.filePath) {
402
+ console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}: No filePath`);
403
+ return;
404
+ }
405
+
406
+ // ADD: Same two-step conversion as the current frame
407
+ const { baseUnit } = core._getColormapForVariable(variable);
408
+ const toUnit = core._getTargetUnit(baseUnit, units);
409
+ const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
410
+ const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
411
+
412
+ let dataScale = result.scale;
413
+ let dataOffset = result.offset;
414
+
415
+ let convertedScale = dataScale;
416
+ let convertedOffset = dataOffset;
417
+
418
+ // Step 1: Convert from server unit to colormap base unit
419
+ if (serverDataUnit !== baseUnit) {
420
+ const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
421
+ if (conversionFunc) {
422
+ if (result.scaleType === 'sqrt') {
423
+ const physicalAtOffset = dataOffset * dataOffset;
424
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
425
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
426
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
427
+ convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
428
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
429
+ convertedScale = newOffsetPlusScale - convertedOffset;
430
+ } else {
431
+ convertedOffset = conversionFunc(dataOffset);
432
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
433
+ convertedScale = convertedOffsetPlusScale - convertedOffset;
434
+ }
435
+ dataScale = convertedScale;
436
+ dataOffset = convertedOffset;
437
+ }
438
+ }
439
+
440
+ // Step 2: Convert from colormap base unit to target display unit
441
+ if (baseUnit !== toUnit) {
442
+ const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
443
+ if (conversionFunc) {
444
+ if (result.scaleType === 'sqrt') {
445
+ const physicalAtOffset = dataOffset * dataOffset;
446
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
447
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
448
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
449
+ convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
450
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
451
+ convertedScale = newOffsetPlusScale - convertedOffset;
452
+ } else {
453
+ convertedOffset = conversionFunc(dataOffset);
454
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
455
+ convertedScale = convertedOffsetPlusScale - convertedOffset;
456
+ }
457
+ }
458
+ }
459
+
460
+ const frameData = {
461
+ filePath: result.filePath,
462
+ nx, ny,
463
+ scale: convertedScale,
464
+ offset: convertedOffset,
465
+ missing: result.missing,
466
+ corners,
467
+ gridDef,
468
+ scaleType: result.scaleType,
469
+ originalScale: result.scale,
470
+ originalOffset: result.offset
471
+ };
472
+
473
+ preloadedDataCache.current.set(cacheKey, frameData);
474
+
475
+ if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
476
+ const frameInfoForGpu = {
477
+ [cacheKey]: {
478
+ filePath: frameData.filePath,
479
+ nx: frameData.nx,
480
+ ny: frameData.ny,
481
+ scale: frameData.scale,
482
+ offset: frameData.offset,
483
+ missing: frameData.missing,
484
+ scaleType: frameData.scaleType || 'linear',
485
+ originalScale: frameData.originalScale,
486
+ originalOffset: frameData.originalOffset
487
+ }
488
+ };
489
+ gridLayerRef.current.primeGpuCache(frameInfoForGpu);
490
+ }
491
+ })
492
+ .catch(error => {
493
+ console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${frame}:`, error);
494
+ });
495
+ });
496
+ };
497
+
498
+ useEffect(() => {
499
+ // This effect manages the auto-refresh based on props
500
+ if (autoRefresh) {
501
+ const interval = (autoRefreshInterval || 30) * 1000;
502
+ _checkForUpdates(); // Run immediately on enable
503
+ autoRefreshIntervalId.current = setInterval(_checkForUpdates, interval);
504
+ }
505
+
506
+ // Cleanup function: this runs when the component unmounts or props change
507
+ return () => {
508
+ if (autoRefreshIntervalId.current) {
509
+ clearInterval(autoRefreshIntervalId.current);
510
+ autoRefreshIntervalId.current = null;
511
+ }
512
+ };
513
+ }, [autoRefresh, autoRefreshInterval, _checkForUpdates]);
514
+
515
+ const updateGPUWithCachedData = (state) => {
516
+ const { model, date, run, forecastHour, variable, units, isMRMS, mrmsTimestamp } = state;
517
+
518
+ const cacheKey = isMRMS
519
+ ? `mrms-${mrmsTimestamp}-${variable}`
520
+ : `${model}-${date}-${run}-${forecastHour}-${variable}`;
521
+
522
+ if (Platform.OS === 'ios' && gridLayerRef.current.setActiveFrame) {
523
+ // Get the cached data BEFORE calling setActiveFrame
524
+ const cachedData = preloadedDataCache.current.get(cacheKey);
525
+
526
+ if (cachedData) {
527
+ currentGridDataRef.current = {
528
+ nx: cachedData.nx,
529
+ ny: cachedData.ny,
530
+ scale: cachedData.scale,
531
+ offset: cachedData.offset,
532
+ missing: cachedData.missing,
533
+ gridDef: cachedData.gridDef,
534
+ variable: variable,
535
+ units: units,
536
+ scaleType: cachedData.scaleType
537
+ };
538
+ }
539
+
540
+ // Now call setActiveFrame (which will async update the native cache)
541
+ gridLayerRef.current.setActiveFrame(cacheKey);
542
+ return true;
543
+ }
544
+
545
+ const cachedData = preloadedDataCache.current.get(cacheKey);
546
+
547
+ if (!cachedData) {
548
+ return false;
549
+ }
550
+
551
+ if (!gridLayerRef.current) {
552
+ console.warn(`⚠️ [updateGPUWithCachedData] GridLayer ref not available`); // CHANGED
553
+ return false;
554
+ }
555
+
556
+ if (!cachedGeometry.current || cachedGeometry.current.model !== (isMRMS ? 'mrms' : model) || cachedGeometry.current.variable !== variable) {
557
+ gridLayerRef.current.updateGeometry(cachedData.corners, cachedData.gridDef);
558
+ cachedGeometry.current = { model: (isMRMS ? 'mrms' : model), variable };
559
+ }
560
+
561
+ const colormapKey = `${variable}-${units}`;
562
+ if (!cachedColormap.current || cachedColormap.current.key !== colormapKey) {
563
+ const { colormap, baseUnit } = core._getColormapForVariable(variable);
564
+ const toUnit = core._getTargetUnit(baseUnit, units);
565
+ const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
566
+ let dataRange;
567
+ if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
568
+ if (isMRMS) {
569
+ dataRange = [5, 380];
570
+ } else {
571
+ dataRange = [5, 380];
572
+ }
573
+ } else {
574
+ dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
575
+ }
576
+ const colormapBytes = _generateColormapBytes(finalColormap);
577
+ const colormapAsBase64 = fromByteArray(colormapBytes);
578
+
579
+ gridLayerRef.current.updateColormapTexture(colormapAsBase64);
580
+ cachedColormap.current = { key: colormapKey };
581
+ cachedDataRange.current = dataRange;
582
+
583
+ setRenderProps(prev => ({ ...prev, dataRange }));
584
+ }
585
+
586
+ if (cachedData.filePath) {
587
+ gridLayerRef.current.updateDataTextureFromFile(
588
+ cachedData.filePath,
589
+ cachedData.nx, cachedData.ny,
590
+ cachedData.scale, cachedData.offset, cachedData.missing,
591
+ cachedData.scaleType
592
+ );
593
+
594
+ // ADD THIS: Update inspector cache for file-based data too
595
+ currentGridDataRef.current = {
596
+ nx: cachedData.nx,
597
+ ny: cachedData.ny,
598
+ scale: cachedData.scale,
599
+ offset: cachedData.offset,
600
+ missing: cachedData.missing,
601
+ gridDef: cachedData.gridDef,
602
+ variable: variable,
603
+ units: units
604
+ };
605
+ } else if (cachedData.dataAsBase64) {
606
+ gridLayerRef.current.updateDataTexture(
607
+ cachedData.dataAsBase64,
608
+ cachedData.nx, cachedData.ny,
609
+ cachedData.scale, cachedData.offset, cachedData.missing,
610
+ cachedData.scaleType
611
+ );
612
+
613
+ // Update the inspector cache when using dataAsBase64
614
+ const binaryString = atob(cachedData.dataAsBase64);
615
+ const uint8Array = new Uint8Array(binaryString.length);
616
+
617
+ for (let i = 0; i < binaryString.length; i++) {
618
+ uint8Array[i] = binaryString.charCodeAt(i);
619
+ }
620
+
621
+ currentGridDataRef.current = {
622
+ data: uint8Array,
623
+ nx: cachedData.nx,
624
+ ny: cachedData.ny,
625
+ scale: cachedData.scale,
626
+ offset: cachedData.offset,
627
+ missing: cachedData.missing,
628
+ gridDef: cachedData.gridDef,
629
+ variable: variable,
630
+ units: units
631
+ };
632
+ } else {
633
+ console.error(`❌ [updateGPUWithCachedData] Cached data has no filePath or dataAsBase64!`);
634
+ console.error('❌ [updateGPUWithCachedData] Cached data keys:', Object.keys(cachedData));
635
+ return false;
636
+ }
637
+
638
+ // Update inspector parameters for file-based data too
639
+ if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
640
+ gridLayerRef.current.updateDataParameters(cachedData.scale, cachedData.offset, cachedData.missing);
641
+ }
642
+ return true;
643
+ };
644
+
645
+ const handleStateChangeRef = useRef(null);
646
+ const debounceTimeoutRef = useRef(null);
647
+
648
+ useEffect(() => {
649
+ if (core && props.customColormaps) {
650
+ core.customColormaps = props.customColormaps;
651
+ // Trigger a re-render if we already have data loaded
652
+ if (hasInitialLoad.current) {
653
+ core._emitStateChange();
654
+ }
655
+ }
656
+ }, [core, props.customColormaps]);
657
+
658
+ const getValueAtPoint = async (lng, lat) => {
659
+ if (!core) {
660
+ console.warn('🔍 [Inspector] Core not available');
661
+ return null;
662
+ }
663
+
664
+ // ADD THIS: Check if we have valid data before attempting inspection
665
+ if (!currentGridDataRef.current) {
666
+ return null;
667
+ }
668
+
669
+ try {
670
+ const gridIndices = core._getGridIndexFromLngLat(lng, lat);
671
+ if (!gridIndices) return null;
672
+
673
+ const { i, j } = gridIndices;
674
+
675
+ const value = await InspectorModule.getValueAtGridIndex(i, j);
676
+
677
+ if (value === null) {
678
+ return null;
679
+ }
680
+
681
+ const { colormap, baseUnit } = core._getColormapForVariable(core.state.variable);
682
+ const displayUnit = core._getTargetUnit(baseUnit, core.state.units);
683
+ const finalColormap = core._convertColormapUnits(colormap, baseUnit, displayUnit);
684
+ const minThreshold = finalColormap[0];
685
+
686
+ if (value < minThreshold) {
687
+ return null;
688
+ }
689
+
690
+ // Filter out values below the minimum threshold (matching shader behavior)
691
+ if (value < minThreshold) {
692
+ return null;
693
+ }
694
+
695
+ // Also check if value is NaN or effectively missing
696
+ if (!isFinite(value)) {
697
+ return null;
698
+ }
699
+
700
+ return {
701
+ value: value,
702
+ unit: displayUnit,
703
+ variable: {
704
+ code: core.state.variable,
705
+ name: core.getVariableDisplayName(core.state.variable)
706
+ },
707
+ lngLat: { lng, lat }
708
+ };
709
+ } catch (error) {
710
+ console.error('🔍 [Inspector] Error:', error);
711
+ return null;
712
+ }
713
+ };
714
+
715
+ const _checkForUpdates = useMemo(() => async () => {
716
+ if (!core) return;
717
+ const { isMRMS, model: currentModel, variable: currentVariable, date, run } = core.state;
718
+
719
+ if (isMRMS) {
720
+ // --- MRMS LOGIC WITH PRE-LOADING ---
721
+ const oldTimestamps = new Set(core.mrmsStatus?.[currentVariable] || []);
722
+ const mrmsStatus = await core.fetchMRMSStatus(true);
723
+ const newTimestamps = mrmsStatus?.[currentVariable] || [];
724
+ if (newTimestamps.length === 0) return;
725
+
726
+ const newTimestampsToPreload = newTimestamps.filter(ts => !oldTimestamps.has(ts));
727
+
728
+ if (newTimestampsToPreload.length > 0) {
729
+ core.mrmsStatus = mrmsStatus;
730
+ core._emitStateChange(); // Update UI slider without changing selection
731
+
732
+ const { corners, gridDef } = core._getGridCornersAndDef('mrms');
733
+ const { nx, ny } = gridDef.grid_params;
734
+
735
+ newTimestampsToPreload.forEach(frame => {
736
+ const cacheKey = `mrms-${frame}-${currentVariable}`;
737
+ if (preloadedDataCache.current.has(cacheKey)) return;
738
+
739
+ const frameDate = new Date(frame * 1000);
740
+ const y = frameDate.getUTCFullYear(), m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0'), d = frameDate.getUTCDate().toString().padStart(2, '0');
741
+
742
+ // --- THIS IS THE FIX ---
743
+ // Changed 'variable' to 'currentVariable'
744
+ const resourcePath = `/grids/mrms/${y}${m}${d}/${frame}/0/${currentVariable}/0`;
745
+ // --- END FIX ---
746
+
747
+ const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
748
+
749
+ WeatherFrameProcessorModule.processFrame({ url, apiKey: core.apiKey, bundleId: core.bundleId })
750
+ .then(result => {
751
+ if (!result || !result.filePath) return;
752
+ const frameData = { filePath: result.filePath, nx, ny, scale: result.scale, offset: result.offset, missing: result.missing, corners, gridDef, scaleType: result.scaleType, originalScale: result.scale, originalOffset: result.offset };
753
+ preloadedDataCache.current.set(cacheKey, frameData);
754
+ if (Platform.OS === 'ios' && gridLayerRef.current?.primeGpuCache) {
755
+ gridLayerRef.current.primeGpuCache({ [cacheKey]: frameData });
756
+ }
757
+ }).catch(error => console.warn(`[Auto-Refresh] Failed to preload frame ${frame}:`, error));
758
+ });
759
+
760
+ const newTimestampsSet = new Set(newTimestamps);
761
+ oldTimestamps.forEach(oldTs => {
762
+ if (!newTimestampsSet.has(oldTs)) {
763
+ const cacheKey = `mrms-${oldTs}-${currentVariable}`;
764
+ preloadedDataCache.current.delete(cacheKey);
765
+ }
766
+ });
767
+ }
768
+ } else {
769
+ // --- MODEL LOGIC ---
770
+ const modelStatus = await core.fetchModelStatus(true);
771
+ const latestRun = findLatestModelRun(modelStatus, currentModel);
772
+ if (!latestRun) return;
773
+
774
+ const currentRunKey = `${date}:${run}`;
775
+ const latestRunKey = `${latestRun.date}:${latestRun.run}`;
776
+
777
+ if (latestRunKey > currentRunKey) {
778
+ // This preserves the current forecastHour while changing the run
779
+ await core.setState({
780
+ date: latestRun.date,
781
+ run: latestRun.run,
782
+ });
783
+ }
784
+ }
785
+ }, [core]);
786
+
787
+ useEffect(() => {
788
+ if (!core) {
789
+ console.warn('⚠️ [useEffect] Core is not available yet');
790
+ return;
791
+ }
792
+
793
+ const handleStateChange = async (newState) => {
794
+ props.onStateChange?.(newState);
795
+
796
+ if (!previousStateRef.current) {
797
+ previousStateRef.current = core.state;
798
+ }
799
+
800
+ const variableChanged = !previousStateRef.current || newState.variable !== previousStateRef.current.variable;
801
+
802
+ if (variableChanged && gridLayerRef.current?.setVariable) {
803
+ gridLayerRef.current.setVariable(newState.variable);
804
+ }
805
+
806
+ const stateKey = `${newState.model}-${newState.variable}-${newState.date}-${newState.run}-${newState.forecastHour}-${newState.units}-${newState.mrmsTimestamp}`;
807
+
808
+ const isOpacityOnlyChange =
809
+ hasInitialLoad.current &&
810
+ newState.opacity !== renderProps.opacity &&
811
+ newState.variable === previousStateRef.current?.variable &&
812
+ newState.forecastHour === previousStateRef.current?.forecastHour &&
813
+ newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
814
+ newState.model === previousStateRef.current?.model &&
815
+ newState.units === previousStateRef.current?.units;
816
+
817
+ const isPlayStateOnlyChange =
818
+ hasInitialLoad.current &&
819
+ newState.isPlaying !== previousStateRef.current?.isPlaying &&
820
+ newState.variable === previousStateRef.current?.variable &&
821
+ newState.forecastHour === previousStateRef.current?.forecastHour &&
822
+ newState.mrmsTimestamp === previousStateRef.current?.mrmsTimestamp &&
823
+ newState.model === previousStateRef.current?.model &&
824
+ newState.units === previousStateRef.current?.units &&
825
+ newState.opacity === previousStateRef.current?.opacity;
826
+
827
+ if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
828
+ previousStateRef.current = newState;
829
+ return;
830
+ }
831
+
832
+ if (!isOpacityOnlyChange && !isPlayStateOnlyChange) {
833
+ lastProcessedState.current = stateKey;
834
+ }
835
+
836
+ if (isOpacityOnlyChange) {
837
+ setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
838
+ previousStateRef.current = newState;
839
+ return;
840
+ }
841
+
842
+ if (isPlayStateOnlyChange) {
843
+ previousStateRef.current = newState;
844
+ return;
845
+ }
846
+
847
+ const isUnitsOnlyChange =
848
+ hasInitialLoad.current &&
849
+ newState.model === previousStateRef.current.model &&
850
+ newState.isMRMS === previousStateRef.current.isMRMS &&
851
+ newState.variable === previousStateRef.current.variable &&
852
+ newState.date === previousStateRef.current.date &&
853
+ newState.run === previousStateRef.current.run &&
854
+ newState.forecastHour === previousStateRef.current.forecastHour &&
855
+ newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
856
+ newState.units !== previousStateRef.current.units;
857
+
858
+ if (isUnitsOnlyChange) {
859
+ const { variable, units, isMRMS, mrmsTimestamp, model, date, run, forecastHour } = newState;
860
+ const oldCacheKey = isMRMS
861
+ ? `mrms-${mrmsTimestamp}-${variable}`
862
+ : `${model}-${date}-${run}-${forecastHour}-${variable}`;
863
+
864
+ const cachedData = preloadedDataCache.current.get(oldCacheKey);
865
+
866
+ if (cachedData && cachedData.originalScale !== undefined && cachedData.originalOffset !== undefined) {
867
+ const { baseUnit } = core._getColormapForVariable(variable);
868
+ const toUnit = core._getTargetUnit(baseUnit, units);
869
+ const fieldInfo = DICTIONARIES?.fld?.[variable] || {};
870
+ const serverDataUnit = fieldInfo.defaultUnit || baseUnit;
871
+
872
+ let dataScale = cachedData.originalScale;
873
+ let dataOffset = cachedData.originalOffset;
874
+
875
+ if (serverDataUnit !== baseUnit) {
876
+ const conversionFunc = getUnitConversionFunction(serverDataUnit, baseUnit);
877
+ if (conversionFunc) {
878
+ if (cachedData.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
+ const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
884
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
885
+ dataScale = newOffsetPlusScale - newOffset;
886
+ dataOffset = newOffset;
887
+ } else {
888
+ const convertedOffset = conversionFunc(dataOffset);
889
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
890
+ dataScale = convertedOffsetPlusScale - convertedOffset;
891
+ dataOffset = convertedOffset;
892
+ }
893
+ }
894
+ }
895
+
896
+ if (baseUnit !== toUnit) {
897
+ const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
898
+ if (conversionFunc) {
899
+ if (cachedData.scaleType === 'sqrt') {
900
+ const physicalAtOffset = dataOffset * dataOffset;
901
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
902
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
903
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
904
+ const newOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
905
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
906
+ dataScale = newOffsetPlusScale - newOffset;
907
+ dataOffset = newOffset;
908
+ } else {
909
+ const convertedOffset = conversionFunc(dataOffset);
910
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
911
+ dataScale = convertedOffsetPlusScale - convertedOffset;
912
+ dataOffset = convertedOffset;
913
+ }
914
+ }
915
+ }
916
+
917
+ const { colormap } = core._getColormapForVariable(variable);
918
+ const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
919
+ let dataRange = (variable === 'ptypeRefl' || variable === 'ptypeRate') ? [5, 380] : [finalColormap[0], finalColormap[finalColormap.length - 2]];
920
+ const colormapBytes = _generateColormapBytes(finalColormap);
921
+ const colormapAsBase64 = fromByteArray(colormapBytes);
922
+
923
+ gridLayerRef.current.updateColormapTexture(colormapAsBase64);
924
+ cachedColormap.current = { key: `${variable}-${units}` };
925
+ cachedDataRange.current = dataRange;
926
+ setRenderProps(prev => ({ ...prev, dataRange, opacity: newState.opacity }));
927
+
928
+ if (gridLayerRef.current && gridLayerRef.current.updateDataParameters) {
929
+ const scaleTypeValue = cachedData.scaleType === 'sqrt' ? 1 : 0;
930
+ gridLayerRef.current.updateDataParameters(dataScale, dataOffset, cachedData.missing, scaleTypeValue);
931
+ }
932
+
933
+ const newCacheKey = isMRMS ? `mrms-${mrmsTimestamp}-${variable}` : `${model}-${date}-${run}-${forecastHour}-${variable}`;
934
+ preloadedDataCache.current.set(newCacheKey, { ...cachedData, scale: dataScale, offset: dataOffset });
935
+ }
936
+
937
+ previousStateRef.current = newState;
938
+ return;
939
+ }
940
+
941
+ const needsFullLoad =
942
+ !hasInitialLoad.current ||
943
+ newState.model !== previousStateRef.current.model ||
944
+ newState.isMRMS !== previousStateRef.current.isMRMS ||
945
+ newState.variable !== previousStateRef.current.variable ||
946
+ newState.date !== previousStateRef.current.date ||
947
+ newState.run !== previousStateRef.current.run;
948
+
949
+ if (needsFullLoad) {
950
+ if (gridLayerRef.current) {
951
+ gridLayerRef.current.setVariable(newState.variable);
952
+ gridLayerRef.current.clear();
953
+ if (Platform.OS === 'ios' && gridLayerRef.current.clearGpuCache) {
954
+ gridLayerRef.current.clearGpuCache();
955
+ }
956
+ }
957
+ hasPreloadedRef.current = false;
958
+ preloadedDataCache.current.clear();
959
+ cachedGeometry.current = null;
960
+ cachedColormap.current = null;
961
+ currentGridDataRef.current = null;
962
+ WeatherFrameProcessorModule.cancelAllFrames();
963
+
964
+ if (!newState.variable) {
965
+ previousStateRef.current = newState;
966
+ return;
967
+ }
968
+ preloadAllFramesToDisk(newState);
969
+ } else if (newState.forecastHour !== previousStateRef.current.forecastHour || (newState.isMRMS && newState.mrmsTimestamp !== previousStateRef.current.mrmsTimestamp)) {
970
+ const success = updateGPUWithCachedData(newState);
971
+ if (success && newState.opacity !== renderProps.opacity) {
972
+ setRenderProps(prev => ({ ...prev, opacity: newState.opacity }));
973
+ }
974
+ }
975
+
976
+ previousStateRef.current = newState;
977
+ };
978
+ // --- END REPLACEMENT ---
979
+
980
+ handleStateChangeRef.current = handleStateChange;
981
+
982
+ const stableHandler = (newState) => {
983
+ const isOpacityOnlyChange =
984
+ previousStateRef.current &&
985
+ newState.opacity !== previousStateRef.current.opacity &&
986
+ newState.variable === previousStateRef.current.variable &&
987
+ newState.forecastHour === previousStateRef.current.forecastHour &&
988
+ newState.mrmsTimestamp === previousStateRef.current.mrmsTimestamp &&
989
+ newState.model === previousStateRef.current.model &&
990
+ newState.units === previousStateRef.current.units &&
991
+ newState.date === previousStateRef.current.date &&
992
+ newState.run === previousStateRef.current.run;
993
+
994
+ if (isOpacityOnlyChange) {
995
+ if (handleStateChangeRef.current) {
996
+ handleStateChangeRef.current(newState);
997
+ }
998
+ return;
999
+ }
1000
+
1001
+ if (debounceTimeoutRef.current) {
1002
+ clearTimeout(debounceTimeoutRef.current);
1003
+ }
1004
+
1005
+ debounceTimeoutRef.current = setTimeout(() => {
1006
+ if (handleStateChangeRef.current) {
1007
+ handleStateChangeRef.current(newState);
1008
+ }
1009
+ debounceTimeoutRef.current = null;
1010
+ }, 50);
1011
+ };
1012
+
1013
+ core.on('state:change', stableHandler);
1014
+
1015
+ return () => {
1016
+ core.off('state:change', stableHandler);
1017
+ if (debounceTimeoutRef.current) {
1018
+ clearTimeout(debounceTimeoutRef.current);
1019
+ }
1020
+ };
1021
+ }, [core]);
1022
+
1023
+ useEffect(() => {
1024
+ return () => {
1025
+ preloadedDataCache.current.clear();
1026
+ hasInitialLoad.current = false;
1027
+ lastProcessedState.current = null;
1028
+ };
1029
+ }, []);
1030
+
1031
+ const lastInspectorUpdateRef = useRef(0);
1032
+ const INSPECTOR_THROTTLE_MS = 50;
1033
+
1034
+ useEffect(() => {
1035
+ if (!core || !inspectorEnabled) {
1036
+ return;
1037
+ }
1038
+
1039
+ const handleMapMove = async (center) => {
1040
+ if (!center || !Array.isArray(center) || center.length !== 2) {
1041
+ return;
1042
+ }
1043
+
1044
+ // Throttle updates
1045
+ const now = Date.now();
1046
+ if (now - lastInspectorUpdateRef.current < INSPECTOR_THROTTLE_MS) {
1047
+ return;
1048
+ }
1049
+ lastInspectorUpdateRef.current = now;
1050
+
1051
+ const [longitude, latitude] = center;
1052
+
1053
+ const payload = await getValueAtPoint(longitude, latitude);
1054
+ onInspect?.(payload);
1055
+ };
1056
+
1057
+ core.on('map:move', handleMapMove);
1058
+
1059
+ if (context && context.getCenter) {
1060
+ const center = context.getCenter();
1061
+ if (center) {
1062
+ handleMapMove(center);
1063
+ }
1064
+ }
1065
+
1066
+ return () => {
1067
+ core.off('map:move', handleMapMove);
1068
+ };
1069
+ }, [inspectorEnabled, onInspect, core, context]);
1070
+
1071
+ useEffect(() => {
1072
+ if (!core || !inspectorEnabled) {
1073
+ return;
1074
+ }
1075
+
1076
+ const triggerReinspection = () => {
1077
+ const mapRef = mapRegistry.getMap();
1078
+ const center = mapRef?._currentCenter;
1079
+
1080
+ if (center && Array.isArray(center) && center.length === 2) {
1081
+ const [longitude, latitude] = center;
1082
+
1083
+ getValueAtPoint(longitude, latitude).then(payload => {
1084
+ onInspect?.(payload);
1085
+ });
1086
+ }
1087
+ };
1088
+
1089
+ // Small delay to ensure data is loaded before re-inspecting
1090
+ const timer = setTimeout(triggerReinspection, 100);
1091
+
1092
+ return () => clearTimeout(timer);
1093
+ }, [
1094
+ core?.state?.variable,
1095
+ core?.state?.model,
1096
+ core?.state?.forecastHour,
1097
+ core?.state?.mrmsTimestamp,
1098
+ core?.state?.units,
1099
+ inspectorEnabled,
1100
+ onInspect
1101
+ ]);
1102
+
1103
+ useEffect(() => {
1104
+ if (!core) {
1105
+ return;
1106
+ }
1107
+
1108
+ const handleCameraChange = (center) => {
1109
+ if (core && center) {
1110
+ core.setMapCenter(center);
1111
+ }
1112
+ };
1113
+
1114
+ // Register with the global registry
1115
+ mapRegistry.addCameraListener(handleCameraChange);
1116
+
1117
+ // Try to get initial center
1118
+ const mapRef = mapRegistry.getMap();
1119
+ if (mapRef?._currentCenter) {
1120
+ handleCameraChange(mapRef._currentCenter);
1121
+ }
1122
+
1123
+ return () => {
1124
+ mapRegistry.removeCameraListener(handleCameraChange);
1125
+ };
1126
+ }, [core]);
1127
+
1128
+ useEffect(() => {
1129
+ core.initialize();
1130
+ return () => {
1131
+ core.destroy();
1132
+ };
1133
+ }, [core]);
1134
+
1135
+ return (
1136
+ <GridRenderLayer
1137
+ ref={gridLayerRef}
1138
+ opacity={renderProps.opacity}
1139
+ dataRange={renderProps.dataRange}
1140
+ belowID="AML_-_terrain"
1141
+ />
1142
+ );
1143
+ });
1144
+
1145
+ WeatherLayerManager.getAvailableVariables = (options) => {
1146
+ if (!options || !options.apiKey) {
1147
+ console.error("API key must be provided to get available variables.");
1148
+ return [];
1149
+ }
1150
+ const core = new AguaceroCore({ apiKey: options.apiKey });
1151
+ return core.getAvailableVariables('mrms');
1152
1152
  };