diff --git a/public/sw.js b/public/sw.js
index 0029938..778b806 100644
--- a/public/sw.js
+++ b/public/sw.js
@@ -3,7 +3,7 @@
//
// This value is rewritten automatically before each build so deployed clients
// refresh to the newest shell and cached assets.
-const CACHE_NAME = 'radioplayer-pwa-v5-1777473175316';
+const CACHE_NAME = 'radioplayer-pwa-v5-1777474420392';
const STATION_SYNC_CACHE_NAME = 'radioplayer-station-sync-v1';
const MANAGED_CATALOG_CACHE_NAME = 'radioplayer-managed-catalog-v1';
const RADIO_BROWSER_API_ENDPOINT = 'https://de1.api.radio-browser.info/json/stations/search';
@@ -377,10 +377,23 @@ async function refreshManagedCatalogCache() {
const response = await fetch(url, { cache: 'no-store' });
if (isCacheableResponse(response)) {
await managedCatalogCache.put(url, response);
+ return { updated: true, error: null };
}
+
+ return {
+ updated: false,
+ error: `Unexpected managed catalog response: ${response.status} ${response.statusText}`.trim(),
+ };
} catch {
// Network unavailable — keep existing cache as-is.
}
+
+ return { updated: false, error: 'Managed catalog request failed.' };
+}
+
+async function notifyClients(message) {
+ const clients = await self.clients.matchAll({ type: 'window', includeUncontrolled: true });
+ await Promise.allSettled(clients.map((client) => client.postMessage(message)));
}
async function respondWithManagedCatalog(request) {
@@ -530,7 +543,23 @@ self.addEventListener('activate', (event) => {
self.addEventListener('sync', (event) => {
if (event.tag !== STATION_SYNC_TAG) return;
- event.waitUntil(syncRadioStations('background-sync'));
+ event.waitUntil(
+ syncRadioStations('background-sync')
+ .then((meta) => notifyClients({
+ type: 'station-catalog-updated',
+ reason: 'background-sync',
+ meta,
+ }))
+ .catch(async (error) => {
+ await notifyClients({
+ type: 'station-catalog-update-failed',
+ reason: 'background-sync',
+ error: error instanceof Error ? error.message : 'Unknown error',
+ failedAt: new Date().toISOString(),
+ });
+ throw error;
+ })
+ );
});
self.addEventListener('message', (event) => {
@@ -544,6 +573,14 @@ self.addEventListener('message', (event) => {
? await syncRadioStations('country-selection-update', syncSettings.selectedCountryCodes)
: null;
+ if (syncResult) {
+ await notifyClients({
+ type: 'station-catalog-updated',
+ reason: 'country-selection-update',
+ meta: syncResult,
+ });
+ }
+
event.ports?.[0]?.postMessage({
ok: true,
selectedCountryCodes: syncSettings.selectedCountryCodes,
@@ -560,11 +597,43 @@ self.addEventListener('message', (event) => {
self.addEventListener('periodicsync', (event) => {
if (event.tag === STATION_PERIODIC_SYNC_TAG) {
- event.waitUntil(syncRadioStations('periodic-sync'));
+ event.waitUntil(
+ syncRadioStations('periodic-sync')
+ .then((meta) => notifyClients({
+ type: 'station-catalog-updated',
+ reason: 'periodic-sync',
+ meta,
+ }))
+ .catch(async (error) => {
+ await notifyClients({
+ type: 'station-catalog-update-failed',
+ reason: 'periodic-sync',
+ error: error instanceof Error ? error.message : 'Unknown error',
+ failedAt: new Date().toISOString(),
+ });
+ throw error;
+ })
+ );
return;
}
if (event.tag === MANAGED_CATALOG_PERIODIC_SYNC_TAG) {
- event.waitUntil(refreshManagedCatalogCache());
+ event.waitUntil(
+ refreshManagedCatalogCache().then((result) => {
+ if (!result.updated) {
+ return notifyClients({
+ type: 'managed-catalog-update-failed',
+ reason: 'periodic-sync',
+ error: result.error || 'Unknown error',
+ failedAt: new Date().toISOString(),
+ });
+ }
+
+ return notifyClients({
+ type: 'managed-catalog-updated',
+ reason: 'periodic-sync',
+ });
+ })
+ );
}
});
diff --git a/src/App.jsx b/src/App.jsx
index e3e7807..f39ca8f 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -199,6 +199,11 @@ function TrackInfo() {
+
+
+
+
+
Output: