@aguacerowx/react-native 0.0.25 → 0.0.26

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