diff --git a/libs/windy-sounding/CHANGELOG.md b/libs/windy-sounding/CHANGELOG.md index 089a229f..a4bdce9b 100644 --- a/libs/windy-sounding/CHANGELOG.md +++ b/libs/windy-sounding/CHANGELOG.md @@ -1,5 +1,11 @@ # Release history +## 4.1.2 - Jul 19, 2024 + +- Prevent an infinite loop when height === 0 +- Better handling of burst of wheel events +- Refresh windy data cache on re-render + ## 4.1.1 - July 17, 2024 - Do not throw when remote config can not be loaded diff --git a/libs/windy-sounding/package-lock.json b/libs/windy-sounding/package-lock.json index 4c821685..b7a48f76 100644 --- a/libs/windy-sounding/package-lock.json +++ b/libs/windy-sounding/package-lock.json @@ -1,12 +1,12 @@ { "name": "windy-plugin-fxc-soundings", - "version": "4.1.0", + "version": "4.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "windy-plugin-fxc-soundings", - "version": "4.1.0", + "version": "4.1.2", "license": "MIT", "dependencies": { "@reduxjs/toolkit": "^2.2.6", diff --git a/libs/windy-sounding/package.json b/libs/windy-sounding/package.json index 44e160ef..6c1ab339 100644 --- a/libs/windy-sounding/package.json +++ b/libs/windy-sounding/package.json @@ -1,6 +1,6 @@ { "name": "windy-plugin-fxc-soundings", - "version": "4.1.1", + "version": "4.1.2", "type": "module", "private": true, "description": "Alternative sounding graphs with custom features for PG/HG pilots.", diff --git a/libs/windy-sounding/src/components/skewt.tsx b/libs/windy-sounding/src/components/skewt.tsx index b3a8c6b1..73feb14d 100644 --- a/libs/windy-sounding/src/components/skewt.tsx +++ b/libs/windy-sounding/src/components/skewt.tsx @@ -202,8 +202,12 @@ function DryAdiabatic({ pressureToPxScale: Scale; pathGenerator: (points: [x: number, y: number][]) => string; }) { + if (height === 0) { + // prevent an infinite loop when height === 0. + return; + } const points: [x: number, y: number][] = []; - const stepPx = height / 15; + const stepPx = height / 20; for (let y = height; y > -stepPx; y -= stepPx) { const p = pressureToPxScale.invert(y); const t = atm.dryLapse(p, temp, pressure); @@ -226,9 +230,13 @@ function WetAdiabatic({ pressureToPxScale: Scale; pathGenerator: (points: [x: number, y: number][]) => string; }) { + if (height === 0) { + // prevent an infinite loop when height === 0. + return; + } const points: [x: number, y: number][] = []; let previousPressure = pressure; - const stepPx = height / 15; + const stepPx = height / 20; for (let y = height; y > -stepPx; y -= stepPx) { const p = pressureToPxScale.invert(y); temp += (p - previousPressure) * atm.wetTempGradient(p, temp); @@ -252,6 +260,10 @@ function IsoHume({ pressureToPxScale: Scale; pathGenerator: (points: [x: number, y: number][]) => string; }) { + if (height === 0) { + // prevent an infinite loop when height === 0. + return; + } const points: [x: number, y: number][] = []; const mixingRatio = atm.mixingRatio(atm.saturationVaporPressure(temp), pressure); const stepPx = height; diff --git a/libs/windy-sounding/src/containers/containers.tsx b/libs/windy-sounding/src/containers/containers.tsx index c8539524..6d516bd0 100644 --- a/libs/windy-sounding/src/containers/containers.tsx +++ b/libs/windy-sounding/src/containers/containers.tsx @@ -30,6 +30,8 @@ export function Plugin() { fetchStatus, availableVersion, isWindyDataAvailableAtCurrentTime, + modelName, + location, } = useSelector((state: RootState) => { const modelName = pluginSlice.selModelName(state); const location = pluginSlice.selLocation(state); @@ -55,6 +57,10 @@ export function Plugin() { }; }, shallowEqual); + if (startHeight === 0) { + return; + } + // Resizable height on mobile. const [mobileHeight, setMobileHeight] = useState(); const height = mobileHeight ?? startHeight; @@ -63,6 +69,8 @@ export function Plugin() { let heightOnStartDrag = 0; const dispatch: AppDispatch = useDispatch(); + // Fetch data when the cache has expired. + dispatch(forecastSlice.fetchForecast({ modelName, location })); const selectFavorite = useCallback((location: LatLon) => { dispatch(changeLocation(location)); centerMap(location); @@ -110,7 +118,10 @@ export function Plugin() { size, }; dispatch(updateTime(step)); - ignoreWheelEventUntilMs = Date.now() + (size === 'day' ? 500 : 10); + ignoreWheelEventUntilMs = timeMs + (size === 'day' ? 600 : 50); + } else if (ignoreWheelEventUntilMs < timeMs + 50) { + // Ignore bursts of events (windows/mac). + ignoreWheelEventUntilMs += 10; } e.stopImmediatePropagation(); e.preventDefault(); diff --git a/libs/windy-sounding/src/redux/forecast-slice.ts b/libs/windy-sounding/src/redux/forecast-slice.ts index 8294bc37..377529ed 100644 --- a/libs/windy-sounding/src/redux/forecast-slice.ts +++ b/libs/windy-sounding/src/redux/forecast-slice.ts @@ -181,7 +181,7 @@ export const fetchForecast = createAsyncThunk { - // Prevent fetching again while loading. + // Prevent fetching again while loading or when data is already cached. const { modelName, location } = modelAndLocation; const state = api.getState(); const pluginStatus = pluginSlice.selStatus(state); @@ -189,7 +189,11 @@ export const fetchForecast = createAsyncThunk { const key = windyDataKey(modelName, location); - return isDataCached(state[slice.name], key) ? state[slice.name].data[key] : undefined; + return isWindyDataCached(state[slice.name], key) ? state[slice.name].data[key] : undefined; }; /** diff --git a/libs/windy-sounding/src/redux/plugin-slice.ts b/libs/windy-sounding/src/redux/plugin-slice.ts index d91fa8ba..a2175be4 100644 --- a/libs/windy-sounding/src/redux/plugin-slice.ts +++ b/libs/windy-sounding/src/redux/plugin-slice.ts @@ -36,8 +36,8 @@ type PluginState = { const initialState: PluginState = { favorites: [], isZoomedIn: true, - width: 0, - height: 0, + width: 100, + height: 100, location: { lat: 0, lon: 0 }, modelName: 'ecmwf', timeMs: windyStore.get('timestamp'),