@aguacerowx/react-native 0.0.30 → 0.0.31

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