AMeDAS doesn't report apparent temperature directly, so this was
hardcoded null - "Feels like -°" on every location. Wired through the
app's existing computeApparentTemperature() fallback (same convention
FMI/DWD/NWS/SMHI/etc already use for this exact gap) using AMeDAS's
own real temp/humidity/wind, since those are all genuine live
observations, not derived/forecast values.
PranshulGG pointed out the previous fix (resetting alerts/airQuality at
the top of every getWeather() call) caused a visible flash on every
refresh, not just a location switch, since it cleared state before
knowing whether real data was coming back.
Per his suggested approach: onAlerts/onAirQuality now always fire
(never skipped), passing null when no repository resolves for the
location's alertSource/airQualitySource instead of skipping the
callback. handleAlerts/handleAirQuality treat a null result as an
explicit "clear" signal, while a real Success/Error updates normally
exactly as before - so a location with real alerts is never touched
until the actual result arrives (no flash), and a location with no
alert source now correctly clears once that's determined, without
ever clearing eagerly beforehand.
WeatherViewModel.getWeather() reset isError/isUnsupportedSource/
isAirQualityLoading on every fetch, but never alerts or airQuality.
SourceDataRepository.getData() only invokes onAlerts/onAirQuality when
the location's alertSource/airQualitySource resolves to a real
repository - a location with alertSource == NONE (the default for
every location right now, since none of it is auto-selected on
creation) never gets a callback at all, so the previous location's
alerts/air quality stayed on screen indefinitely after switching.
Found while testing JMA's new alerts capability: switching from a
Japan location with real active alerts to one with no alert source
configured kept showing the old alerts. Reproduced and confirmed fixed
on-device.
JMA has its own alerts endpoint (warning/data/warning/{officeCode}.json),
keyed by the same officeCode/class10Code already resolved and cached for
the weather source, so no extra location lookup is needed. Filters out
"no warnings issued"/"cleared" statuses, maps JMA's warning-code enum to
severity (~26 codes across advisory/warning/emergency-warning tiers,
transcribed via Breezy Weather's JmaService.kt, same technique used to
find the hourly-forecast endpoint).
Tested live: Wakkanai, Japan currently has 3 active advisories
(thunderstorm, gale, dense fog), confirmed rendering correctly.
Closes#979. Resolves each location to the nearest of JMA's 142
class10 regions and pulls real numeric hourly temp/wind from the
undocumented jmatile/data/wdist/VPFD endpoint, daily data from the
weekly forecast block, and current conditions from live AMeDAS
station observations. No API key required.
PranshulGG flagged in review that ON_START now also calling getWeather()
could duplicate the fetch setActiveLocation() already triggers during
initial VM setup. Confirmed the concern is real: DisposableEffect(location)
re-subscribes when `location` goes from null to non-null right after cold
start, and Android replays a synthetic ON_START on subscribe when the
lifecycle is already started - so that resubscription does refire ON_START.
Guarded the getWeather() call on uiState.isInitialized (only true after the
first successful fetch completes), so it now only fires on a genuine
resume-from-background, not the cold-start race. Retested both cases on
the AVD: cold start no longer double-fetches, and #1035 still resolves
correctly on reopen after moving.
Two related device-location bugs found while investigating #1035:
- WeatherViewModel only checked/refreshed the device location on manual
pull-to-refresh (isManualRefresh gate), never on app-open, the 45-min
auto-refresh timer, or app-resume from background. Decoupled the check
from isManualRefresh so it always runs for a device-location entry, and
forces a real refetch (via isForceRefresh, not isManualRefresh, which
would still hit the 15-min throttle) only when the position actually
moved. Also wired an immediate check into WeatherAutoRefreshForeground's
existing ON_START observer, since that's the only hook that already
fires on every foreground-resume, not just cold start.
- DeviceLocationProvider.getDeviceLocation() still gated on the old
single-provider selection (getProvider(), preferring NETWORK_PROVIDER)
before ever reaching the dual-provider live-request logic added in the
#938 fix. If that one provider happened to be present-but-disabled
(e.g. "Device only" location mode, or no GMS/network-location backend),
it failed instantly without ever trying GPS. Removed the stale gate.
Tested on an AVD: reproduced #1035 (background app, move >1000m, reopen
without refreshing -> location stayed stale), then confirmed the fix
resolves it end-to-end (name, coordinates, and weather data all update
on reopen, no manual refresh needed). Also confirmed the provider-gate
fix resolves an instant "Current location not found" on a device with
NETWORK_PROVIDER disabled but GPS enabled.