feat: add global weather support
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m54s
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m54s
This commit is contained in:
@@ -142,17 +142,22 @@ export function SettingsPage() {
|
||||
const selectedStation = stations?.find((station) => station.id === selectedStationId)
|
||||
?? stations?.find((station) => station.id === DEFAULT_STATION_ID)
|
||||
?? stations?.[0];
|
||||
const activeLocation = selectedLocation?.stationId === selectedStation?.id ? selectedLocation : null;
|
||||
const activeLocation = selectedLocation;
|
||||
const selectedRegion = activeLocation?.region ?? "PL";
|
||||
const stationPosition = selectedStation
|
||||
? locateSynopStations(stations ?? [], positions).find((station) => station.id === selectedStation.id)
|
||||
: null;
|
||||
const notificationLatitude = Number.isFinite(activeLocation?.latitude) ? activeLocation?.latitude : stationPosition?.latitude ?? null;
|
||||
const notificationLongitude = Number.isFinite(activeLocation?.longitude) ? activeLocation?.longitude : stationPosition?.longitude ?? null;
|
||||
const notificationLocationName = activeLocation?.name ?? selectedStation?.name ?? null;
|
||||
const notificationCountyTeryt = activeLocation?.countyTeryt ?? null;
|
||||
const selectedProvince = getProvinceForSelection(selectedLocation?.province, selectedStationId ?? DEFAULT_STATION_ID);
|
||||
const effectiveProvince = provinceMode === "manual" ? manualProvince : selectedProvince;
|
||||
const effectiveProvinceLabel = effectiveProvince ? formatProvinceName(effectiveProvince, language) : t("settings.notifications.noProvince");
|
||||
const notificationTimezone = activeLocation?.timezone ?? (selectedRegion === "PL" ? "Europe/Warsaw" : null);
|
||||
const notificationCountyTeryt = selectedRegion === "PL" ? activeLocation?.countyTeryt ?? null : null;
|
||||
const selectedProvince = selectedRegion === "PL" ? getProvinceForSelection(selectedLocation?.province, selectedStationId ?? DEFAULT_STATION_ID) : null;
|
||||
const effectiveProvince = selectedRegion === "PL" ? provinceMode === "manual" ? manualProvince : selectedProvince : null;
|
||||
const canUseOfficialWarnings = selectedRegion === "PL" && Boolean(effectiveProvince);
|
||||
const effectiveProvinceLabel = selectedRegion === "GLOBAL"
|
||||
? t("settings.notifications.globalRegion")
|
||||
: effectiveProvince ? formatProvinceName(effectiveProvince, language) : t("settings.notifications.noProvince");
|
||||
const manualProvinceValue = manualProvince ?? selectedProvince ?? "mazowieckie";
|
||||
|
||||
useEffect(() => {
|
||||
@@ -173,7 +178,7 @@ export function SettingsPage() {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!notificationsEnabled || !vapidPublicKey || !effectiveProvince || notificationStatus !== "granted") return;
|
||||
if (!notificationsEnabled || !vapidPublicKey || notificationStatus !== "granted") return;
|
||||
const province = effectiveProvince;
|
||||
let cancelled = false;
|
||||
|
||||
@@ -182,11 +187,14 @@ export function SettingsPage() {
|
||||
const subscription = await registration?.pushManager.getSubscription();
|
||||
if (!subscription || cancelled) return;
|
||||
await savePushSubscription(subscription, province, language, {
|
||||
region: selectedRegion,
|
||||
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
||||
morningBriefEnabled,
|
||||
tomorrowBriefEnabled,
|
||||
latitude: notificationLatitude,
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
timezone: notificationTimezone,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
@@ -197,7 +205,7 @@ export function SettingsPage() {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [effectiveProvince, language, morningBriefEnabled, notificationCountyTeryt, notificationLatitude, notificationLocationName, notificationLongitude, notificationStatus, notificationsEnabled, temperatureUnit, tomorrowBriefEnabled, vapidPublicKey, windSpeedUnit]);
|
||||
}, [canUseOfficialWarnings, effectiveProvince, language, morningBriefEnabled, notificationCountyTeryt, notificationLatitude, notificationLocationName, notificationLongitude, notificationStatus, notificationsEnabled, notificationTimezone, selectedRegion, temperatureUnit, tomorrowBriefEnabled, vapidPublicKey, windSpeedUnit]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!provinceDropdownOpen) return;
|
||||
@@ -229,7 +237,7 @@ export function SettingsPage() {
|
||||
}
|
||||
}, [notificationStatus, t]);
|
||||
|
||||
const canUsePush = Boolean(vapidPublicKey && effectiveProvince && notificationStatus !== "unsupported" && notificationStatus !== "needs-install" && notificationStatus !== "denied" && notificationStatus !== "unconfigured");
|
||||
const canUsePush = Boolean(vapidPublicKey && (selectedRegion === "GLOBAL" || effectiveProvince) && notificationStatus !== "unsupported" && notificationStatus !== "needs-install" && notificationStatus !== "denied" && notificationStatus !== "unconfigured");
|
||||
|
||||
async function getServiceWorkerRegistration() {
|
||||
if (!("serviceWorker" in navigator)) throw new Error("Service worker is not available.");
|
||||
@@ -237,7 +245,7 @@ export function SettingsPage() {
|
||||
}
|
||||
|
||||
async function enableWarningNotifications() {
|
||||
if (!vapidPublicKey || !effectiveProvince) {
|
||||
if (!vapidPublicKey || (selectedRegion === "PL" && !effectiveProvince)) {
|
||||
setNotificationMessage(t("settings.notifications.saveError"));
|
||||
return;
|
||||
}
|
||||
@@ -261,11 +269,14 @@ export function SettingsPage() {
|
||||
applicationServerKey: decodeBase64UrlKey(vapidPublicKey),
|
||||
});
|
||||
await savePushSubscription(subscription, effectiveProvince, language, {
|
||||
region: selectedRegion,
|
||||
officialWarningsEnabled: canUseOfficialWarnings,
|
||||
morningBriefEnabled,
|
||||
tomorrowBriefEnabled,
|
||||
latitude: notificationLatitude,
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
timezone: notificationTimezone,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
@@ -319,17 +330,20 @@ export function SettingsPage() {
|
||||
|
||||
async function updateMorningBriefPreference(enabled: boolean) {
|
||||
setMorningBriefEnabled(enabled);
|
||||
if (!notificationsEnabled || !effectiveProvince || notificationStatus !== "granted") return;
|
||||
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
||||
try {
|
||||
const registration = await navigator.serviceWorker?.getRegistration();
|
||||
const subscription = await registration?.pushManager.getSubscription();
|
||||
if (!subscription) return;
|
||||
await savePushSubscription(subscription, effectiveProvince, language, {
|
||||
region: selectedRegion,
|
||||
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
||||
morningBriefEnabled: enabled,
|
||||
tomorrowBriefEnabled,
|
||||
latitude: notificationLatitude,
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
timezone: notificationTimezone,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
@@ -341,17 +355,20 @@ export function SettingsPage() {
|
||||
|
||||
async function updateTomorrowBriefPreference(enabled: boolean) {
|
||||
setTomorrowBriefEnabled(enabled);
|
||||
if (!notificationsEnabled || !effectiveProvince || notificationStatus !== "granted") return;
|
||||
if (!notificationsEnabled || !canUsePush || notificationStatus !== "granted") return;
|
||||
try {
|
||||
const registration = await navigator.serviceWorker?.getRegistration();
|
||||
const subscription = await registration?.pushManager.getSubscription();
|
||||
if (!subscription) return;
|
||||
await savePushSubscription(subscription, effectiveProvince, language, {
|
||||
region: selectedRegion,
|
||||
officialWarningsEnabled: canUseOfficialWarnings && notificationsEnabled,
|
||||
morningBriefEnabled,
|
||||
tomorrowBriefEnabled: enabled,
|
||||
latitude: notificationLatitude,
|
||||
longitude: notificationLongitude,
|
||||
locationName: notificationLocationName,
|
||||
timezone: notificationTimezone,
|
||||
countyTeryt: notificationCountyTeryt,
|
||||
temperatureUnit,
|
||||
windSpeedUnit,
|
||||
@@ -446,6 +463,7 @@ export function SettingsPage() {
|
||||
type="radio"
|
||||
name="warning-notification-province-mode"
|
||||
checked={provinceMode === "selected"}
|
||||
disabled={selectedRegion === "GLOBAL"}
|
||||
onChange={() => setProvinceMode("selected")}
|
||||
className="mt-1 accent-accent"
|
||||
/>
|
||||
@@ -459,6 +477,7 @@ export function SettingsPage() {
|
||||
type="radio"
|
||||
name="warning-notification-province-mode"
|
||||
checked={provinceMode === "manual"}
|
||||
disabled={selectedRegion === "GLOBAL"}
|
||||
onChange={() => {
|
||||
setProvinceMode("manual");
|
||||
if (!manualProvince) setManualProvince(selectedProvince ?? "mazowieckie");
|
||||
@@ -473,7 +492,7 @@ export function SettingsPage() {
|
||||
aria-label={t("settings.notifications.regionManual")}
|
||||
aria-haspopup="listbox"
|
||||
aria-expanded={provinceDropdownOpen}
|
||||
disabled={provinceMode !== "manual"}
|
||||
disabled={selectedRegion === "GLOBAL" || provinceMode !== "manual"}
|
||||
onBlur={(event) => {
|
||||
if (!event.currentTarget.parentElement?.contains(event.relatedTarget as Node | null)) setProvinceDropdownOpen(false);
|
||||
}}
|
||||
@@ -514,6 +533,11 @@ export function SettingsPage() {
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
{selectedRegion === "GLOBAL" && (
|
||||
<p className="rounded-card border border-border/60 bg-surface px-3 py-3 text-xs leading-5 text-muted">
|
||||
{t("settings.notifications.globalAlertsUnavailable")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -541,9 +565,9 @@ export function SettingsPage() {
|
||||
<span className="min-w-0">
|
||||
<span className="flex items-center gap-2 font-medium">
|
||||
<Bell className="size-3.5 text-accent" aria-hidden="true" />
|
||||
{t("settings.notifications.enable")}
|
||||
{selectedRegion === "GLOBAL" ? t("settings.notifications.enableDevice") : t("settings.notifications.enable")}
|
||||
</span>
|
||||
<span className="mt-0.5 block text-xs leading-5 text-muted">{t("settings.notifications.enableDescription")}</span>
|
||||
<span className="mt-0.5 block text-xs leading-5 text-muted">{selectedRegion === "GLOBAL" ? t("settings.notifications.enableGlobalDescription") : t("settings.notifications.enableDescription")}</span>
|
||||
<span className="mt-2 block text-xs font-semibold text-accent">
|
||||
{isSavingSubscription
|
||||
? t("settings.notifications.saving")
|
||||
|
||||
Reference in New Issue
Block a user