Make settings restore crash-safe

This commit is contained in:
Gabriel Brown
2026-08-18 02:22:23 -04:00
parent 172b099a04
commit 83391e0453
5 changed files with 880 additions and 387 deletions
@@ -25,6 +25,29 @@ Singleton {
property string lastError: ""
property string lastAction: ""
// Narrow service boundaries keep restore sequencing explicit and make it
// possible to verify the real handler in an isolated shell without ever
// calling the daily-driver compositor or wallpaper services.
property var readHomeState: function() {
return {
initialized: HomePreferences.initialized,
favorites: HomePreferences.favorites
};
}
property var resetHome: function() { HomePreferences.resetHomeDefaults(); }
property var initializeHome: function(ids) { HomePreferences.initialize(ids); }
property var aliasHome: function(id, alias) { HomePreferences.setAlias(id, alias); }
property var reloadDesktop: function() { DesktopPreferences.reload(); }
property var applyCompositor: function() { SystemSettings.applyPersistedDisplayPolicy(); }
property var reloadKeybinds: function() { Keybinds.applyReload(); }
property var keybindsReloading: function() { return Keybinds.reloading; }
property var systemBusy: function() { return SystemSettings.busy; }
property var currentWallpaper: function() {
return String(DesktopPreferences.get("wallpaperPath") ?? "");
}
property var applyWallpaper: function(path) { Wallpaper.set(path); }
property var reloadShell: function() { Quickshell.reload(false); }
readonly property bool busy: listQuery.running || actionRun.running
|| applyRestoredState.running || settleReload.running
@@ -62,12 +85,10 @@ Singleton {
}
root.lastAction = actionRun.restoring ? "restored" : "saved";
if (actionRun.restoring) {
const homeReloaded = root.reloadHomeState(actionRun.outputText);
const homeReloaded = root.handleRestoreOutput(actionRun.outputText);
root.lastError = homeReloaded
? ""
: "Desktop settings were restored, but Home favourites could not be reloaded.";
DesktopPreferences.reload();
applyRestoredState.restart();
} else
root.lastError = "";
root.refresh();
@@ -82,9 +103,9 @@ Singleton {
// DesktopPreferences.reload() invalidates reactive shell bindings.
// These services also own state outside QML and need an explicit
// replay: compositor options, Lua-generated binds, and hyprpaper.
SystemSettings.applyPersistedDisplayPolicy();
Keybinds.applyReload();
Wallpaper.set(String(DesktopPreferences.get("wallpaperPath") ?? ""));
root.applyCompositor();
root.reloadKeybinds();
root.applyWallpaper(root.currentWallpaper());
settleReload.attempts = 0;
settleReload.restart();
@@ -101,9 +122,9 @@ Singleton {
// Let the current instances finish their external writes before a
// soft reload replaces them. The cap keeps a failed external tool
// from leaving restored Home state stale indefinitely.
if ((!Keybinds.reloading && !SystemSettings.busy) || attempts >= 30) {
if ((!root.keybindsReloading() && !root.systemBusy()) || attempts >= 30) {
stop();
Quickshell.reload(false);
root.reloadShell();
}
}
}
@@ -123,19 +144,28 @@ Singleton {
}
function serialiseHomeState(): string {
const current = root.readHomeState();
const favorites = [];
for (const favorite of HomePreferences.favorites ?? []) {
for (const favorite of current.favorites ?? []) {
favorites.push({
id: String(favorite.id ?? ""),
alias: String(favorite.alias ?? "")
});
}
return JSON.stringify({
initialized: HomePreferences.initialized,
initialized: current.initialized === true,
favorites: favorites
});
}
function handleRestoreOutput(text: string): bool {
if (!root.reloadHomeState(text))
return false;
root.reloadDesktop();
applyRestoredState.restart();
return true;
}
// Restore output carries the canonical Home state. Reconstructing through
// these methods keeps validation and persistence inside HomePreferences;
// this service never mutates its aliases or private FileView directly.
@@ -170,12 +200,12 @@ Singleton {
if (!data.initialized && ids.length > 0)
return false;
HomePreferences.resetHomeDefaults();
root.resetHome();
if (!data.initialized)
return true;
HomePreferences.initialize(ids);
root.initializeHome(ids);
for (let index = 0; index < ids.length; index++)
HomePreferences.setAlias(ids[index], aliases[index]);
root.aliasHome(ids[index], aliases[index]);
return true;
} catch (error) {
return false;
@@ -183,7 +213,7 @@ Singleton {
}
function resetHomeState(): bool {
HomePreferences.resetHomeDefaults();
root.resetHome();
return true;
}