mirror of
https://github.com/got-feedBack/feedBack-desktop.git
synced 2026-09-11 02:34:10 +00:00
fix(audio-engine): single persistence store for device settings (TLC Part II §4)
The device config was persisted in TWO stores — the main process's file-backed settings AND localStorage['slopsmith-audio-device'] — merged on load by newest-savedAt. A main-side migration/reset left stale localStorage that could win the timestamp race and resurrect wiped settings, and a device re-save from either path re-persisted mute flags captured at that moment, interleaving with the (now-arbitrated) runtime mute writers. The file store is now the only write target. localStorage is treated as a one-time migration source: a strictly-newer browser copy is imported into the file store, then the key is deleted either way — after the first load the file is the single source of truth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
88f881dd1e
commit
f0340ed425
+21
-6
@@ -210,11 +210,14 @@ window.__feedBackDesktopAudioHooks = window.__feedBackDesktopAudioHooks || {};
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveDeviceSettings(settings = captureDeviceSettings()) {
|
function saveDeviceSettings(settings = captureDeviceSettings()) {
|
||||||
|
// Single persistence store (TLC Part II §4): the file-backed settings
|
||||||
|
// are the only writer target. The old parallel localStorage copy meant
|
||||||
|
// a main-side migration/reset could lose the timestamp race against a
|
||||||
|
// stale browser copy and resurrect wiped settings.
|
||||||
const snapshot = {
|
const snapshot = {
|
||||||
...cloneDeviceSettings(settings),
|
...cloneDeviceSettings(settings),
|
||||||
savedAt: Date.now(),
|
savedAt: Date.now(),
|
||||||
};
|
};
|
||||||
try { localStorage.setItem('slopsmith-audio-device', JSON.stringify(snapshot)); } catch (_) {}
|
|
||||||
pendingDeviceSave = pendingDeviceSave
|
pendingDeviceSave = pendingDeviceSave
|
||||||
.catch(() => null)
|
.catch(() => null)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -255,17 +258,29 @@ window.__feedBackDesktopAudioHooks = window.__feedBackDesktopAudioHooks || {};
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn('[audio-engine] Failed to load file-backed device settings:', e);
|
console.warn('[audio-engine] Failed to load file-backed device settings:', e);
|
||||||
}
|
}
|
||||||
|
// Migration only (TLC Part II §4): 'slopsmith-audio-device' was a
|
||||||
|
// second store racing the file on savedAt. Import a strictly-newer
|
||||||
|
// browser copy into the file store ONCE, then delete the key either
|
||||||
|
// way — after this the file is the single source of truth.
|
||||||
let browserSettings = null;
|
let browserSettings = null;
|
||||||
try {
|
try {
|
||||||
const raw = localStorage.getItem('slopsmith-audio-device');
|
const raw = localStorage.getItem('slopsmith-audio-device');
|
||||||
browserSettings = normalizeDeviceSettings(raw ? JSON.parse(raw) : null);
|
browserSettings = normalizeDeviceSettings(raw ? JSON.parse(raw) : null);
|
||||||
} catch { browserSettings = null; }
|
} catch { browserSettings = null; }
|
||||||
if (fileSettings && browserSettings) {
|
if (browserSettings !== null) {
|
||||||
return getDeviceSettingsSavedAt(browserSettings) > getDeviceSettingsSavedAt(fileSettings)
|
const browserNewer = !fileSettings
|
||||||
? browserSettings
|
|| getDeviceSettingsSavedAt(browserSettings) > getDeviceSettingsSavedAt(fileSettings);
|
||||||
: fileSettings;
|
if (browserNewer) {
|
||||||
|
try {
|
||||||
|
if (typeof api.saveDeviceSettings === 'function') await api.saveDeviceSettings(browserSettings);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[audio-engine] device-settings migration save failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try { localStorage.removeItem('slopsmith-audio-device'); } catch (_) {}
|
||||||
|
if (browserNewer) return browserSettings;
|
||||||
}
|
}
|
||||||
return fileSettings || browserSettings;
|
return fileSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasSettingValue(value) {
|
function hasSettingValue(value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user