@aguacerowx/react-native 0.0.29 → 0.0.30

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 (39) hide show
  1. package/ios/GridRenderLayer.swift +60 -117
  2. package/ios/GridRenderLayerBridge.swift +0 -1
  3. package/ios/GridRenderLayerView.m +1 -41
  4. package/ios/InspectorModule.swift +2 -2
  5. package/lib/commonjs/ios/GridRenderLayer.swift +60 -117
  6. package/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -1
  7. package/lib/commonjs/ios/GridRenderLayerView.m +1 -41
  8. package/lib/commonjs/ios/InspectorModule.swift +2 -2
  9. package/lib/commonjs/package.json +1 -1
  10. package/lib/commonjs/src/GridRenderLayer.js +0 -2
  11. package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  12. package/lib/commonjs/src/WeatherLayerManager.js +125 -77
  13. package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  14. package/lib/module/ios/GridRenderLayer.swift +60 -117
  15. package/lib/module/ios/GridRenderLayerBridge.swift +0 -1
  16. package/lib/module/ios/GridRenderLayerView.m +1 -41
  17. package/lib/module/ios/InspectorModule.swift +2 -2
  18. package/lib/module/lib/commonjs/android/build.gradle +108 -0
  19. package/lib/module/lib/commonjs/ios/AguaceroPackage.m +19 -0
  20. package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +16 -0
  21. package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +986 -0
  22. package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +158 -0
  23. package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +217 -0
  24. package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
  25. package/lib/module/lib/commonjs/package.json +1 -1
  26. package/lib/module/lib/commonjs/src/GridRenderLayer.js +0 -2
  27. package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
  28. package/lib/module/lib/commonjs/src/WeatherLayerManager.js +125 -77
  29. package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  30. package/lib/module/package.json +1 -1
  31. package/lib/module/src/GridRenderLayer.js +0 -2
  32. package/lib/module/src/GridRenderLayer.js.map +1 -1
  33. package/lib/module/src/WeatherLayerManager.js +125 -77
  34. package/lib/module/src/WeatherLayerManager.js.map +1 -1
  35. package/lib/typescript/src/GridRenderLayer.d.ts.map +1 -1
  36. package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/GridRenderLayer.js +0 -2
  39. package/src/WeatherLayerManager.js +135 -87
@@ -171,30 +171,37 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
171
171
  },
172
172
  setAutoRefresh,
173
173
  refreshData: () => {
174
- console.log('[WeatherLayerManager RN] Manual data refresh triggered.');
175
- // Call the internal update function, which is already in scope
176
174
  _checkForUpdates();
177
175
  },
178
176
  };
179
177
  }, [core, autoRefreshInterval, _checkForUpdates]);
180
178
 
181
- const preloadAllFramesToDisk = (state) => {
182
-
179
+ const preloadAllFramesToDisk = async (state) => {
183
180
  if (hasPreloadedRef.current) {
184
- console.log('✅ [Preload] Gating preload; already initiated for this dataset.');
185
181
  return;
186
182
  }
187
- hasPreloadedRef.current = true;
188
- console.log('🚀 [Preload] Initiating parallel preload for new dataset...');
189
183
 
190
184
  const { isMRMS, model, date, run, variable, units, availableHours, availableTimestamps, forecastHour, mrmsTimestamp } = state;
191
185
 
192
- // NEW: Fix the current forecast hour if it's invalid for this variable/model combo
186
+ // CRITICAL: Don't start preloading if we don't have a valid current frame
187
+ if (isMRMS && (mrmsTimestamp == null || !availableTimestamps || availableTimestamps.length === 0)) {
188
+ hasPreloadedRef.current = false;
189
+ return;
190
+ }
191
+
192
+ if (!isMRMS && (forecastHour == null || !availableHours || availableHours.length === 0)) {
193
+ hasPreloadedRef.current = false;
194
+ return;
195
+ }
196
+
197
+ // Only mark as "has preloaded" after validation passes
198
+ hasPreloadedRef.current = true;
199
+
200
+ // Fix the current forecast hour if it's invalid for this variable/model combo
193
201
  let effectiveForecastHour = forecastHour;
194
202
  if (!isMRMS && variable === 'ptypeRefl' && model === 'hrrr' && forecastHour === 0) {
195
203
  const validHours = availableHours.filter(hour => hour !== 0);
196
204
  effectiveForecastHour = validHours.length > 0 ? validHours[0] : 0;
197
- console.log(`⚠️ [Preload] Correcting invalid hour 0 to ${effectiveForecastHour} for HRRR ptypeRefl`);
198
205
  }
199
206
 
200
207
  if (!cachedGeometry.current || !cachedColormap.current) {
@@ -208,13 +215,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
208
215
  const finalColormap = core._convertColormapUnits(colormap, baseUnit, toUnit);
209
216
  let dataRange;
210
217
  if (variable === 'ptypeRefl' || variable === 'ptypeRate') {
211
- if (isMRMS) {
212
- console.log('🔧 Using MRMS ptype data range: 5-380');
213
- dataRange = [5, 380];
214
- } else {
215
- console.log('🔧 Using Model ptype data range: 5-380');
216
- dataRange = [5, 380];
217
- }
218
+ dataRange = isMRMS ? [5, 380] : [5, 380];
218
219
  } else {
219
220
  dataRange = [finalColormap[0], finalColormap[finalColormap.length - 2]];
220
221
  }
@@ -237,29 +238,120 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
237
238
 
238
239
  const allFrames = isMRMS ? availableTimestamps : filteredHours;
239
240
  if (!allFrames || allFrames.length === 0) {
240
- console.warn('🟡 [preloadAllFramesToDisk] No frames available to download.');
241
241
  return;
242
242
  }
243
243
 
244
244
  const currentFrame = isMRMS ? mrmsTimestamp : effectiveForecastHour;
245
245
 
246
- // --- EDIT: Reverse the frame order to load from last to first ---
246
+ // Double-check currentFrame is valid
247
+ if (currentFrame == null) {
248
+ hasPreloadedRef.current = false;
249
+ return;
250
+ }
251
+
252
+ // Reverse the frame order to load from last to first
247
253
  const reversedFrames = [...allFrames].reverse();
248
254
  const framesToPreload = reversedFrames.filter(frame => frame !== currentFrame);
249
-
250
- // The final array will process the current frame first, then the rest in reverse chronological order.
251
- const prioritizedFrames = [
252
- currentFrame,
253
- ...framesToPreload
254
- ];
255
- // --- END EDIT ---
256
-
257
- console.log(`[Preload] Prioritizing frame: ${currentFrame}. Total frames: ${prioritizedFrames.length}`);
258
255
 
259
256
  const { corners, gridDef } = core._getGridCornersAndDef(isMRMS ? 'mrms' : model);
260
257
  const { nx, ny } = gridDef.grid_params;
261
258
 
262
- prioritizedFrames.forEach((frame, index) => {
259
+ // Load the current frame FIRST and WAIT for it before continuing
260
+ const currentCacheKey = isMRMS ? `mrms-${currentFrame}-${variable}` : `${model}-${date}-${run}-${currentFrame}-${variable}`;
261
+
262
+ if (!preloadedDataCache.current.has(currentCacheKey)) {
263
+ let resourcePath;
264
+ if (isMRMS) {
265
+ const frameDate = new Date(currentFrame * 1000);
266
+ const y = frameDate.getUTCFullYear();
267
+ const m = (frameDate.getUTCMonth() + 1).toString().padStart(2, '0');
268
+ const d = frameDate.getUTCDate().toString().padStart(2, '0');
269
+ resourcePath = `/grids/mrms/${y}${m}${d}/${currentFrame}/0/${variable}/0`;
270
+ } else {
271
+ resourcePath = `/grids/${model}/${date}/${run}/${currentFrame}/${variable}/0`;
272
+ }
273
+
274
+ const url = `${core.baseGridUrl}${resourcePath}?apiKey=${core.apiKey}`;
275
+ const options = { url, apiKey: core.apiKey, bundleId: core.bundleId };
276
+
277
+ try {
278
+ const result = await WeatherFrameProcessorModule.processFrame(options);
279
+
280
+ if (!result || !result.filePath) {
281
+ return;
282
+ }
283
+
284
+ const { baseUnit } = core._getColormapForVariable(variable);
285
+ const toUnit = core._getTargetUnit(baseUnit, units);
286
+
287
+ let dataScale = result.scale;
288
+ let dataOffset = result.offset;
289
+
290
+ let convertedScale = dataScale;
291
+ let convertedOffset = dataOffset;
292
+
293
+ if (baseUnit !== toUnit) {
294
+ const conversionFunc = getUnitConversionFunction(baseUnit, toUnit);
295
+ if (conversionFunc) {
296
+ if (result.scaleType === 'sqrt') {
297
+ const physicalAtOffset = dataOffset * dataOffset;
298
+ const physicalAtOffsetPlusScale = (dataOffset + dataScale) * (dataOffset + dataScale);
299
+ const convertedPhysicalAtOffset = conversionFunc(physicalAtOffset);
300
+ const convertedPhysicalAtOffsetPlusScale = conversionFunc(physicalAtOffsetPlusScale);
301
+ convertedOffset = Math.sqrt(Math.abs(convertedPhysicalAtOffset)) * Math.sign(convertedPhysicalAtOffset);
302
+ const newOffsetPlusScale = Math.sqrt(Math.abs(convertedPhysicalAtOffsetPlusScale)) * Math.sign(convertedPhysicalAtOffsetPlusScale);
303
+ convertedScale = newOffsetPlusScale - convertedOffset;
304
+ } else {
305
+ convertedOffset = conversionFunc(dataOffset);
306
+ const convertedOffsetPlusScale = conversionFunc(dataOffset + dataScale);
307
+ convertedScale = convertedOffsetPlusScale - convertedOffset;
308
+ }
309
+ }
310
+ }
311
+
312
+ const frameData = {
313
+ filePath: result.filePath,
314
+ nx, ny,
315
+ scale: convertedScale,
316
+ offset: convertedOffset,
317
+ missing: result.missing,
318
+ corners,
319
+ gridDef,
320
+ scaleType: result.scaleType,
321
+ originalScale: result.scale,
322
+ originalOffset: result.offset
323
+ };
324
+
325
+ preloadedDataCache.current.set(currentCacheKey, frameData);
326
+
327
+ // Update the GPU with the current frame
328
+ gridLayerRef.current.updateDataTextureFromFile(
329
+ frameData.filePath,
330
+ frameData.nx, frameData.ny,
331
+ frameData.scale, frameData.offset, frameData.missing,
332
+ frameData.scaleType
333
+ );
334
+
335
+ currentGridDataRef.current = {
336
+ nx: frameData.nx,
337
+ ny: frameData.ny,
338
+ scale: frameData.scale,
339
+ offset: frameData.offset,
340
+ missing: frameData.missing,
341
+ gridDef: frameData.gridDef,
342
+ variable: variable,
343
+ units: units,
344
+ scaleType: frameData.scaleType
345
+ };
346
+ } catch (error) {
347
+ console.warn(`⚠️ [preloadAllFramesToDisk] Failed frame ${currentFrame}:`, error);
348
+ hasPreloadedRef.current = false;
349
+ return;
350
+ }
351
+ }
352
+
353
+ // NOW preload the rest of the frames asynchronously
354
+ framesToPreload.forEach((frame) => {
263
355
  const cacheKey = isMRMS ? `mrms-${frame}-${variable}` : `${model}-${date}-${run}-${frame}-${variable}`;
264
356
  if (preloadedDataCache.current.has(cacheKey)) {
265
357
  return;
@@ -329,44 +421,21 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
329
421
 
330
422
  preloadedDataCache.current.set(cacheKey, frameData);
331
423
 
332
- const isCurrentFrame = index === 0;
333
-
334
- if (isCurrentFrame) {
335
- console.log(`🎯 [Preload] Using FAST LANE to process and draw current frame (${frame}) immediately.`);
336
- gridLayerRef.current.updateDataTextureFromFile(
337
- frameData.filePath,
338
- frameData.nx, frameData.ny,
339
- frameData.scale, frameData.offset, frameData.missing,
340
- frameData.scaleType
341
- );
342
-
343
- currentGridDataRef.current = {
344
- nx: frameData.nx,
345
- ny: frameData.ny,
346
- scale: frameData.scale,
347
- offset: frameData.offset,
348
- missing: frameData.missing,
349
- gridDef: frameData.gridDef,
350
- variable: variable,
351
- units: units
424
+ if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
425
+ const frameInfoForGpu = {
426
+ [cacheKey]: {
427
+ filePath: frameData.filePath,
428
+ nx: frameData.nx,
429
+ ny: frameData.ny,
430
+ scale: frameData.scale,
431
+ offset: frameData.offset,
432
+ missing: frameData.missing,
433
+ scaleType: frameData.scaleType || 'linear',
434
+ originalScale: frameData.originalScale,
435
+ originalOffset: frameData.originalOffset
436
+ }
352
437
  };
353
- } else {
354
- if (Platform.OS === 'ios' && gridLayerRef.current.primeGpuCache) {
355
- const frameInfoForGpu = {
356
- [cacheKey]: {
357
- filePath: frameData.filePath,
358
- nx: frameData.nx,
359
- ny: frameData.ny,
360
- scale: frameData.scale,
361
- offset: frameData.offset,
362
- missing: frameData.missing,
363
- scaleType: frameData.scaleType || 'linear',
364
- originalScale: frameData.originalScale,
365
- originalOffset: frameData.originalOffset
366
- }
367
- };
368
- gridLayerRef.current.primeGpuCache(frameInfoForGpu);
369
- }
438
+ gridLayerRef.current.primeGpuCache(frameInfoForGpu);
370
439
  }
371
440
  })
372
441
  .catch(error => {
@@ -415,12 +484,6 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
415
484
  units: units,
416
485
  scaleType: cachedData.scaleType
417
486
  };
418
-
419
- console.log('📱 [iOS] Updated currentGridDataRef for inspector:', {
420
- scale: cachedData.scale,
421
- offset: cachedData.offset,
422
- scaleType: cachedData.scaleType // ADD THIS
423
- });
424
487
  }
425
488
 
426
489
  // Now call setActiveFrame (which will async update the native cache)
@@ -431,8 +494,6 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
431
494
  const cachedData = preloadedDataCache.current.get(cacheKey);
432
495
 
433
496
  if (!cachedData) {
434
- const timeKey = isMRMS ? `timestamp ${mrmsTimestamp}` : `hour +${forecastHour}`;
435
- console.log(`⏳ [updateGPUWithCachedData] Frame not ready yet for ${timeKey}. Still preloading...`); // CHANGED
436
497
  return false;
437
498
  }
438
499
 
@@ -551,7 +612,6 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
551
612
 
552
613
  // ADD THIS: Check if we have valid data before attempting inspection
553
614
  if (!currentGridDataRef.current) {
554
- console.log('🔍 [Inspector] No grid data available');
555
615
  return null;
556
616
  }
557
617
 
@@ -573,7 +633,6 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
573
633
  const minThreshold = finalColormap[0];
574
634
 
575
635
  if (value < minThreshold) {
576
- console.log('🔍 [Inspector] Rejected: below threshold'); // ADD THIS LOG
577
636
  return null;
578
637
  }
579
638
 
@@ -619,7 +678,6 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
619
678
  core.mrmsStatus = mrmsStatus;
620
679
  core._emitStateChange(); // Update UI slider without changing selection
621
680
 
622
- console.log(`[Auto-Refresh] Preloading ${newTimestampsToPreload.length} new MRMS frames.`);
623
681
  const { corners, gridDef } = core._getGridCornersAndDef('mrms');
624
682
  const { nx, ny } = gridDef.grid_params;
625
683
 
@@ -681,11 +739,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
681
739
  return;
682
740
  }
683
741
 
684
- // --- REPLACE THIS ENTIRE FUNCTION ---
685
742
  const handleStateChange = async (newState) => {
686
- // --- FIX 1: Notify the parent component IMMEDIATELY ---
687
- // This ensures the parent UI (like sliders) always gets the latest state,
688
- // including updated lists of available hours or timestamps.
689
743
  props.onStateChange?.(newState);
690
744
 
691
745
  if (!previousStateRef.current) {
@@ -718,12 +772,8 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
718
772
  newState.model === previousStateRef.current?.model &&
719
773
  newState.units === previousStateRef.current?.units &&
720
774
  newState.opacity === previousStateRef.current?.opacity;
721
-
722
- // This gate now correctly prevents only redundant *internal* processing.
723
- // The parent has already been notified.
775
+
724
776
  if (!isOpacityOnlyChange && !isPlayStateOnlyChange && lastProcessedState.current === stateKey) {
725
- // --- FIX 2: Update the previous state ref before returning ---
726
- // This is critical to prevent stale comparisons on the next state change event.
727
777
  previousStateRef.current = newState;
728
778
  return;
729
779
  }
@@ -943,9 +993,7 @@ export const WeatherLayerManager = forwardRef((props, ref) => {
943
993
  };
944
994
  }, [inspectorEnabled, onInspect, core, context]);
945
995
 
946
- // Add this new useEffect after the existing inspector useEffect
947
996
  useEffect(() => {
948
- // Trigger re-inspection when state changes (variable, model, forecast hour, etc.)
949
997
  if (!core || !inspectorEnabled) {
950
998
  return;
951
999
  }