Skip to content

Commit 5fdfa35

Browse files
committed
Add automatic backup/restore to HA server (survives cache clear)
Uses Home Assistant's frontend/set_user_data WebSocket API to automatically save favorites and custom stations to the HA server. On card load, if localStorage is empty (cache was cleared), data is automatically restored from the server backup. - Main card: auto-saves on every favorite/custom station change - Both cards: auto-restore on first hass connection if cache empty - Zero configuration needed - works out of the box - Manual JSON backup/restore buttons still available as fallback - Data stored per-user in HA's .storage/frontend.user_data https://claude.ai/code/session_01PHdKi2HPbQoM3EevzgSQFc
1 parent 39b0652 commit 5fdfa35

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

radio-browser-card.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ class RadioBrowserCard extends HTMLElement {
6969
}
7070
}
7171

72+
// On first hass connection, auto-restore from HA server if cache was cleared
73+
if (!oldHass && hass) {
74+
this._autoRestoreFromHA();
75+
}
76+
7277
if (!oldHass || Object.keys(oldHass.states).length !== Object.keys(hass.states).length) {
7378
this.updateMediaPlayers();
7479
}
@@ -93,6 +98,7 @@ class RadioBrowserCard extends HTMLElement {
9398
saveFavorites() {
9499
try {
95100
localStorage.setItem('radio_favorites', JSON.stringify(this._favorites));
101+
this._autoBackupToHA();
96102
} catch (e) {
97103
console.error('Error saving favorites:', e);
98104
}
@@ -111,11 +117,66 @@ class RadioBrowserCard extends HTMLElement {
111117
saveCustomStations() {
112118
try {
113119
localStorage.setItem('radio_custom_stations', JSON.stringify(this._customStations));
120+
this._autoBackupToHA();
114121
} catch (e) {
115122
console.error('Error saving custom stations:', e);
116123
}
117124
}
118125

126+
// Auto-backup to Home Assistant server (survives cache clear)
127+
async _autoBackupToHA() {
128+
if (!this._hass) return;
129+
try {
130+
await this._hass.callWS({
131+
type: 'frontend/set_user_data',
132+
key: 'radio_browser_backup',
133+
value: {
134+
favorites: this._favorites,
135+
custom_stations: this._customStations,
136+
timestamp: Date.now()
137+
}
138+
});
139+
console.log('Auto-backup to HA server OK');
140+
} catch (e) {
141+
console.log('Auto-backup to HA server failed:', e);
142+
}
143+
}
144+
145+
// Auto-restore from Home Assistant server (after cache clear)
146+
async _autoRestoreFromHA() {
147+
if (!this._hass) return;
148+
try {
149+
const result = await this._hass.callWS({
150+
type: 'frontend/get_user_data',
151+
key: 'radio_browser_backup'
152+
});
153+
if (!result || !result.value) return;
154+
155+
const data = result.value;
156+
const localFavs = localStorage.getItem('radio_favorites');
157+
const localCustom = localStorage.getItem('radio_custom_stations');
158+
const hasLocalData = (localFavs && JSON.parse(localFavs).length > 0) ||
159+
(localCustom && JSON.parse(localCustom).length > 0);
160+
161+
// Only restore if localStorage is empty (cache was cleared) and server has data
162+
if (!hasLocalData && (data.favorites?.length > 0 || data.custom_stations?.length > 0)) {
163+
console.log('Cache cleared detected - restoring from HA server backup...');
164+
if (data.favorites?.length > 0) {
165+
this._favorites = data.favorites;
166+
localStorage.setItem('radio_favorites', JSON.stringify(data.favorites));
167+
}
168+
if (data.custom_stations?.length > 0) {
169+
this._customStations = data.custom_stations;
170+
localStorage.setItem('radio_custom_stations', JSON.stringify(data.custom_stations));
171+
}
172+
console.log(`Restored: ${data.favorites?.length || 0} favorites, ${data.custom_stations?.length || 0} custom stations`);
173+
this.updatePlaylist();
174+
}
175+
} catch (e) {
176+
console.log('Auto-restore from HA server not available:', e);
177+
}
178+
}
179+
119180
// YouTube URL handling
120181
parseYouTubeUrl(url) {
121182
// Support various YouTube URL formats
@@ -2600,6 +2661,11 @@ class RadioBrowserCardCompact extends HTMLElement {
26002661
const oldHass = this._hass;
26012662
this._hass = hass;
26022663

2664+
// On first hass connection, auto-restore from HA server if cache was cleared
2665+
if (!oldHass && hass) {
2666+
this._autoRestoreFromHA();
2667+
}
2668+
26032669
if (!oldHass || Object.keys(oldHass.states).length !== Object.keys(hass.states).length) {
26042670
this._updateMediaPlayers();
26052671
}
@@ -2638,6 +2704,37 @@ class RadioBrowserCardCompact extends HTMLElement {
26382704
return all;
26392705
}
26402706

2707+
// Auto-restore from Home Assistant server (after cache clear)
2708+
async _autoRestoreFromHA() {
2709+
if (!this._hass) return;
2710+
try {
2711+
const result = await this._hass.callWS({
2712+
type: 'frontend/get_user_data',
2713+
key: 'radio_browser_backup'
2714+
});
2715+
if (!result || !result.value) return;
2716+
2717+
const data = result.value;
2718+
const localFavs = localStorage.getItem('radio_favorites');
2719+
const localCustom = localStorage.getItem('radio_custom_stations');
2720+
const hasLocalData = (localFavs && JSON.parse(localFavs).length > 0) ||
2721+
(localCustom && JSON.parse(localCustom).length > 0);
2722+
2723+
if (!hasLocalData && (data.favorites?.length > 0 || data.custom_stations?.length > 0)) {
2724+
console.log('Compact card: Restoring from HA server backup...');
2725+
if (data.favorites?.length > 0) {
2726+
localStorage.setItem('radio_favorites', JSON.stringify(data.favorites));
2727+
}
2728+
if (data.custom_stations?.length > 0) {
2729+
localStorage.setItem('radio_custom_stations', JSON.stringify(data.custom_stations));
2730+
}
2731+
this._updateStationSelect();
2732+
}
2733+
} catch (e) {
2734+
console.log('Compact card: Auto-restore not available:', e);
2735+
}
2736+
}
2737+
26412738
// --- State persistence ---
26422739
_saveState() {
26432740
try {

0 commit comments

Comments
 (0)