@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.
- package/ios/GridRenderLayer.swift +60 -117
- package/ios/GridRenderLayerBridge.swift +0 -1
- package/ios/GridRenderLayerView.m +1 -41
- package/ios/InspectorModule.swift +2 -2
- package/lib/commonjs/ios/GridRenderLayer.swift +60 -117
- package/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -1
- package/lib/commonjs/ios/GridRenderLayerView.m +1 -41
- package/lib/commonjs/ios/InspectorModule.swift +2 -2
- package/lib/commonjs/package.json +1 -1
- package/lib/commonjs/src/GridRenderLayer.js +0 -2
- package/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/commonjs/src/WeatherLayerManager.js +125 -77
- package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/ios/GridRenderLayer.swift +60 -117
- package/lib/module/ios/GridRenderLayerBridge.swift +0 -1
- package/lib/module/ios/GridRenderLayerView.m +1 -41
- package/lib/module/ios/InspectorModule.swift +2 -2
- package/lib/module/lib/commonjs/android/build.gradle +108 -0
- package/lib/module/lib/commonjs/ios/AguaceroPackage.m +19 -0
- package/lib/module/lib/commonjs/ios/FragmentUniforms.swift +16 -0
- package/lib/module/lib/commonjs/ios/GridRenderLayer.swift +986 -0
- package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +158 -0
- package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +217 -0
- package/lib/module/lib/commonjs/ios/compiled-shaders/Shaders-device.metallib +0 -0
- package/lib/module/lib/commonjs/package.json +1 -1
- package/lib/module/lib/commonjs/src/GridRenderLayer.js +0 -2
- package/lib/module/lib/commonjs/src/GridRenderLayer.js.map +1 -1
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js +125 -77
- package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
- package/lib/module/package.json +1 -1
- package/lib/module/src/GridRenderLayer.js +0 -2
- package/lib/module/src/GridRenderLayer.js.map +1 -1
- package/lib/module/src/WeatherLayerManager.js +125 -77
- package/lib/module/src/WeatherLayerManager.js.map +1 -1
- package/lib/typescript/src/GridRenderLayer.d.ts.map +1 -1
- package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/GridRenderLayer.js +0 -2
- 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
|
-
//
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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
|
-
|
|
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
|
}
|