National Alert Browser: browse active weather alerts by service/country#88
Conversation
New feature (behind alertBrowserEnabled flag, default on) to browse active
government weather alerts independent of any saved city, entered from a new
"Weather Alerts" section in the Browse tab.
The centerpiece is a scannable "national digest": raw alert feeds are noisy
(dozens of identical county-level products), so alerts are collapsed by event
type + severity into one row each ("Flood Warning — 29 areas · expires 6 PM"),
sorted extreme-first, with a severity floor (default Severe+) and an NWS
land/marine toggle. Tap a group → affected areas → existing AlertDetailView.
Sources, all normalized into the shared WeatherAlert model so AlertDetailView
and severity coloring work unchanged:
- United States — NWS (api.weather.gov/alerts/active)
- Canada — Environment Canada (api.weather.gc.ca weather-alerts)
- Europe — MeteoAlarm per-country CAP feeds (18 countries)
New files:
- Services/AlertBrowserService.swift — providers, fetch, digest grouping
- Views/AlertBrowserView.swift — region picker, digest, group detail
Edits: AlertSource gains .eccc/.meteoalarm; AlertDetailView link generalized;
alertBrowserEnabled flag + Developer toggle; BrowseCitiesView entry point.
Accessibility: digest rows carry explicit combined labels
("Severe. Flood Warning. 29 areas. Soonest expires 6 PM.") and hints.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
api.weather.gov/alerts/active rejects the "limit" parameter with HTTP 400
("Query parameter 'limit' is not recognized"), which surfaced as "Couldn't
load alerts" for the United States. The endpoint returns all active alerts
with no pagination, so the parameter was unnecessary. Canada (ECCC) and
Europe (MeteoAlarm) were unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Default severity floor is now Moderate+ (was Severe+) so watches — which NWS
tags as Moderate (Tornado Watch, Severe Thunderstorm Watch, Flood/Heat Watch)
— are no longer hidden. "Unknown" severity (Air Quality) sorts below Minor, so
it stays gated to the "All" level and doesn't flood the default view.
- Removed the severity-breakdown summary header. VoiceOver read it as one long
run-on string ("119 active alerts. 43 severe · 41 unknown · …"). The per-event
counts now live on each category button as a prominent trailing number, which
reads cleanly as part of that button's label ("Severe. Flood Warning. 25
areas. Soonest expires 6 PM.").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per testing feedback:
- Removed the severity floor and land/marine filters entirely. The digest now
shows every active alert grouped by severity (Extreme → Unknown), including
marine. Grouping by event type keeps it scannable without a filter.
- Each severity section header now carries its total count and reads as a
heading in VoiceOver ("Extreme, 3 alerts"). This was the missing number the
user expected on the Extreme/Severe/Moderate labels.
- Group rows no longer hide the count behind a possibly-ignored combined label:
the visible number carries its own "N areas" accessibility label, and the
row label drops the now-redundant severity (it's in the section header).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- The Europe country list now shows each country's active-alert count as a trailing badge, loaded concurrently on appear (URLSession caps ~6 conns/host so the ~36 feeds queue politely) and cached 5 min in the service. VoiceOver reads "Italy, 4 alerts" / "Malta, no active alerts". - Expanded MeteoAlarm coverage from 18 to 36 member countries (added Baltics, Balkans, Cyprus, Czechia, Hungary, Iceland, Ireland already present, Israel, Luxembourg, Malta, Moldova, Romania, etc.). Note: none of the alert sources (NWS, ECCC, MeteoAlarm) use the paid Open-Meteo API — all three are free, keyless public services. MeteoAlarm != Open-Meteo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reverts the "remove all filtering" overcorrection. The segmented severity filter (Extreme / Severe+ / Moderate+ / All) and the NWS land/marine toggle are back, defaulting to Moderate+. Each segment's VoiceOver label now carries its count — "Extreme, 3 alerts" (VoiceOver appends "1 of 4") — which is what the user asked for. Category rows and severity section-header counts from the prior fix are kept, so numbers are spoken at every level. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ggle
- Severity buttons are now exclusive, not a floor: "Extreme" shows only
Extreme, "Moderate" shows only Moderate. Only "All" is inclusive (every
alert, including Minor Small Craft Advisories and Unknown-severity Air
Quality). Renamed segments Severe+/Moderate+ -> Severe/Moderate.
- Default is now All so nothing is hidden on open; the buttons narrow to a
single severity to reduce clutter. No data is gated.
- Removed the separate land/marine toggle: Small Craft Advisories are tagged
Minor, so they only surface under All anyway — the severity buttons already
handle marine noise, making the second control redundant.
- Segment VoiceOver labels still carry per-level counts ("Extreme, 3 alerts").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Austria's feed (GeoSphere Austria) supplies English event names as glued compounds — "Heatwarning", "Thunderstormwarning", "Stormwarning", "Rainwarning" — translating the German compound word without a space. Insert the missing space before "warning" so these read "Heat warning", "Thunderstorm warning", etc. Correctly-spaced names from other members are left unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1. Air Quality Alerts (NWS tags them severity "Unknown") now surface as Moderate instead of being stranded in the Unknown bucket. 2. New hazard-type filter (a "Type" menu next to the severity buttons): pick a family — Storms, Tropical, Flooding, Heat, Winter, Wind, Fire, Fog, Marine & Coastal, Air Quality, Other — to see just those alerts across all severities. "Storms" gathers tornado/thunderstorm/severe-weather products that NWS otherwise scatters across Extreme (Tornado Warning), Severe (Severe Thunderstorm Warning) and Moderate (the watches). Only families actually present are offered, each with a count; severity-segment counts respect the chosen type. Default is All types. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sanity-checked the hazard classifier against live Canada (ECCC) and 18
European (MeteoAlarm) feeds: 1,334 alerts were landing in "Other" because
European vocabulary differs from NWS. Fixes:
- Classifier keywords now cover both vocabularies: "high-temperature" -> Heat,
"low-temperature" -> Winter, "lightning" -> Storms, bare "storm" -> Wind.
- New "Rain" hazard family (rain / heavy rain / downpour / showers), which
MeteoAlarm issues heavily and NWS does not.
- Repair broken MeteoAlarm event names: some feeds emit an empty event or a raw
"awareness_type=3, awareness_level=2" dump. Decode the structured
awareness_type ("3; Thunderstorm" or the numeric code) into a real name like
"Thunderstorm warning" so it both displays and classifies correctly.
Result: "Other" fell from 1,334 (35%) to 29 (0.7%) across CA + EU; the only
remainder is Greece's generic unlabeled "Yellow Warning". Distribution now
reads sensibly (Storms 40%, Heat 30%, Wind 13%, Winter 6%, Rain 4%, Fog 3%).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Browse tab now covers more than cities (weather alerts by country, and more to come), so the page title changes from "Browse Cities" to "Weather Browser". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Code review — National Alert BrowserReviewed the diff (NWS/ECCC/MeteoAlarm alert browser behind 1. Dead land/marine filter machinery (cleanup)
The PR description notes the land/marine toggle was dropped — this is its leftover skeleton. Suggest removing 2. Dead
|
- Remove dead land/marine filter machinery (supportsLandMarineFilter, landOnly param, and the unreachable region_type=land branch). - Delete unused selectedAlert @State + .sheet in NationalAlertDigestView (rows navigate via NavigationLink; the group detail owns its own sheet). - Cache the two ISO8601DateFormatters as static singletons in parseISO (was allocating ~600-900 formatters per US load). - Classify hazard families once per render and thread the result through loadedContent/filterControls instead of re-running classify repeatedly. - Derive a stable, content-based id for MeteoAlarm alerts lacking an identifier (was array index → churned ForEach identity on refetch). - Cache shortTime's DateFormatter as a static singleton. - Bump CURRENT_PROJECT_VERSION 1 → 2 (MARKETING_VERSION stays 1.5.8). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Review feedback addressed — resolved in 36a31b2
🤖 Generated with Claude Code |
load() no longer flips to .loading when content is already loaded, so a manual refresh shows the standard .refreshable spinner over the existing rows instead of flashing the full-screen "Loading active alerts…" row. A transient refresh failure now keeps the valid alerts visible rather than replacing them with the failure screen; the failure screen still shows on the initial load when there's nothing to preserve. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NWS areaDesc lists zone-based products (e.g. Special Weather Statements) as bare county/zone names with no state, which read ambiguously — a single statement can span multiple states. Zip areaDesc with the parallel geocode.UGC codes (first two letters = state postal code) and append ", <state>" to each area that lacks one. County-based products that already carry ", OH" are left untouched, and marine-zone prefixes (ANZ, GMZ, …) are skipped via a valid-state-abbreviation set. Adds geocode (UGC/SAME) decoding to NWSAlertProperties. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes #87.
Adds a National Alert Browser to the iOS app: browse active government weather alerts independent of any saved city, by service/country, with a VoiceOver-first digest. Behind the
alertBrowserEnabledfeature flag (default on), reached from a new Weather Alerts section in the Browse tab.What's included
Sources (all free, keyless — none touch the paid Open-Meteo account):
api.weather.govapi.weather.gc.caDigest UI (
NationalAlertDigestView):AlertDetailView.Design: each provider normalizes into the existing
WeatherAlertmodel, soAlertDetailView+ severity coloring + a11y labels are reused. NewAlertSourcecases.eccc/.meteoalarm. No new dependencies.New / changed files
Services/AlertBrowserService.swift(providers, fetch, digest grouping, hazard classifier),Views/AlertBrowserView.swift(region picker, Europe country list, digest, group detail)Models/WeatherAlert.swift(source cases),Views/AlertDetailView.swift(generalized source link),Services/FeatureFlags.swift+Views/DeveloperSettingsView.swift(flag + toggle),Views/BrowseCitiesView.swift(entry point)Notable fixes surfaced during development
/alerts/activerejects alimitparam (HTTP 400) — removed.awareness_type=…event dumps decoded via the structured awareness code.Testing
Follow-ups (not in this PR)
🤖 Generated with Claude Code