pragma Singleton // Freedesktop default handlers and session autostart entries. // // The helper owns parsing and atomic desktop-file writes. This singleton keeps // the QML side typed and reactive, and every external command crosses Process // as an argument array. import Quickshell import Quickshell.Io import QtQuick Singleton { id: root property var handlers: ({}) property var autostartEntries: [] property var luaAutostartEntries: [] property string lastError: "" readonly property bool busy: snapshotProcess.running || mutationProcess.running readonly property string helper: Quickshell.shellDir + "/scripts/panama-default-apps" readonly property var supportedRoles: ["browser", "mail", "files", "terminal", "music", "images", "video"] Process { id: snapshotProcess stdout: StdioCollector { onStreamFinished: root.applySnapshot(this.text) } onExited: (exitCode, exitStatus) => { if (exitCode !== 0) root.lastError = "Default applications could not be read. Try refreshing." } } Process { id: mutationProcess onExited: (exitCode, exitStatus) => { if (exitCode !== 0) { root.lastError = "That application setting could not be changed." return; } root.refresh(); } } function applySnapshot(text: string): void { try { const payload = JSON.parse(text); root.handlers = payload.handlers ?? ({}); root.autostartEntries = payload.autostartEntries ?? []; root.luaAutostartEntries = payload.luaAutostartEntries ?? []; root.lastError = ""; } catch (error) { root.lastError = "Default applications returned an unreadable response." } } function refresh(): void { if (root.busy) return; root.lastError = ""; snapshotProcess.exec([root.helper, "snapshot"]); } function knownDesktopId(desktopId: string): bool { if (!/^[A-Za-z0-9][A-Za-z0-9._+-]*\.desktop$/.test(desktopId)) return false; const entries = DesktopEntries.applications.values; return entries.some(entry => { const entryId = String(entry.id ?? ""); return entryId === desktopId || entryId + ".desktop" === desktopId; }); } function setDefault(role: string, desktopId: string): void { if (root.busy) return; if (!root.supportedRoles.includes(role) || !root.knownDesktopId(desktopId)) { root.lastError = "Choose an application from the available list." return; } root.lastError = ""; mutationProcess.exec([root.helper, "set-default", role, desktopId]); } function setAutostart(desktopId: string, enabled: bool): void { if (root.busy) return; const known = root.autostartEntries.some(entry => entry.id === desktopId); if (!known) { root.lastError = "That user autostart entry is no longer available." return; } root.lastError = ""; mutationProcess.exec([root.helper, "set-autostart", desktopId, String(enabled)]); } function addAutostart(desktopId: string): void { if (root.busy) return; if (!root.knownDesktopId(desktopId)) { root.lastError = "Choose an installed application."; return; } root.lastError = ""; mutationProcess.exec([root.helper, "add-autostart", desktopId]); } Component.onCompleted: root.refresh() }