pragma Singleton import QtQuick import Quickshell import Quickshell.Hyprland import Quickshell.Io QtObject { id: manager property bool shellOpen: false property bool quickSettingsOpen: false property bool appLauncherOpen: false property bool powerMenuOpen: false property var appUsageCounts: ({}) property string appUsagePath: { var homeDir = Quickshell.env("HOME"); return homeDir ? homeDir + "/.local/share/deltarunequickshell/apps.json" : ""; } property bool appUsageLoaded: false property var windowRequests: ({}) property var quickSettingsPayload: ({}) property var globals: ({}) signal shellOpened signal shellClosed signal quickSettingsOpened signal quickSettingsClosed signal appLauncherOpened signal appLauncherClosed signal powerMenuOpened signal powerMenuClosed signal windowRequested(string name, var payload) function openShell() { if (!shellOpen) { console.log("ShellStateManager: openShell"); Hyprland.dispatch("submap deltarune"); shellOpen = true; shellOpened(); } } function closeShell() { if (shellOpen) { console.log("ShellStateManager: closeShell"); Hyprland.dispatch("submap reset"); if (quickSettingsOpen) { closeQuickSettings(); } if (appLauncherOpen) { closeAppLauncher(); } if (powerMenuOpen) { closePowerMenu(); } shellOpen = false; shellClosed(); } } function toggleShell() { shellOpen ? closeShell() : openShell(); } function requestWindow(name, payload) { console.log("ShellStateManager: requestWindow", name, payload); windowRequests[name] = { payload: payload, timestamp: Date.now() }; windowRequested(name, payload); } function openQuickSettings(payload) { var normalizedPayload = payload || ({}); quickSettingsPayload = normalizedPayload; console.log("ShellStateManager: openQuickSettings", normalizedPayload); if (appLauncherOpen) { closeAppLauncher(); } if (powerMenuOpen) { closePowerMenu(); } if (!quickSettingsOpen) { quickSettingsOpen = true; quickSettingsOpened(); } requestWindow("quickSettings", normalizedPayload); } function closeQuickSettings() { if (quickSettingsOpen) { console.log("ShellStateManager: closeQuickSettings"); quickSettingsOpen = false; quickSettingsClosed(); } } function toggleQuickSettings(payload) { quickSettingsOpen ? closeQuickSettings() : openQuickSettings(payload); } function openAppLauncher(payload) { var normalizedPayload = payload || ({}); console.log("ShellStateManager: openAppLauncher", normalizedPayload); if (quickSettingsOpen) { closeQuickSettings(); } if (powerMenuOpen) { closePowerMenu(); } if (!appLauncherOpen) { appLauncherOpen = true; appLauncherOpened(); } requestWindow("appLauncher", normalizedPayload); } function closeAppLauncher() { if (appLauncherOpen) { console.log("ShellStateManager: closeAppLauncher"); appLauncherOpen = false; appLauncherClosed(); } } function toggleAppLauncher(payload) { appLauncherOpen ? closeAppLauncher() : openAppLauncher(payload); } function openPowerMenu(payload) { var normalizedPayload = payload || ({}); console.log("ShellStateManager: openPowerMenu", normalizedPayload); if (quickSettingsOpen) { closeQuickSettings(); } if (appLauncherOpen) { closeAppLauncher(); } if (!powerMenuOpen) { powerMenuOpen = true; powerMenuOpened(); } requestWindow("powerMenu", normalizedPayload); } function closePowerMenu() { if (powerMenuOpen) { console.log("ShellStateManager: closePowerMenu"); powerMenuOpen = false; powerMenuClosed(); } } function togglePowerMenu(payload) { powerMenuOpen ? closePowerMenu() : openPowerMenu(payload); } function bumpAppUsage(id) { if (!id) return; var updated = Object.assign({}, appUsageCounts); updated[id] = (updated[id] || 0) + 1; appUsageCounts = updated; } function persistAppUsage() { if (!appUsageLoaded) return; if (!appUsageFile || !appUsageAdapter) return; appUsageAdapter.counts = appUsageCounts || ({}); appUsageFile.writeAdapter(); } onAppUsageCountsChanged: persistAppUsage() property FileView appUsageFile: FileView { id: appUsageFile path: manager.appUsagePath watchChanges: true onFileChanged: reload() onLoaded: { if (appUsageAdapter) { manager.appUsageCounts = appUsageAdapter.counts || ({}); } manager.appUsageLoaded = true; } onLoadFailed: { manager.appUsageLoaded = true; manager.persistAppUsage(); } JsonAdapter { id: appUsageAdapter property var counts: ({}) } } function setGlobal(key, value) { globals[key] = value; } function global(key, defaultValue) { return globals.hasOwnProperty(key) ? globals[key] : defaultValue; } }