@aguacerowx/react-native 0.0.37 → 0.0.38

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