Files
Panama/config/dot/quickshell/services/ThemeProfiles.qml
T

109 lines
4.3 KiB
QML

pragma Singleton
import Quickshell
import QtQuick
import qs.config
import "ThemeProfileModel.js" as ThemeProfileModel
Singleton {
id: root
readonly property var customProfiles: ThemeProfileModel.validCustomProfiles(
DesktopPreferences.get("themeProfiles"))
readonly property var curatedAccents: ThemeProfileModel.curatedAccents()
readonly property var profiles: ThemeProfileModel.profileCatalog(root.customProfiles)
readonly property string activeId: DesktopPreferences.get("themeProfileId") || "moon"
readonly property var activeProfile: ThemeProfileModel.findProfile(
root.customProfiles, root.activeId) || ThemeProfileModel.shippedProfiles()[0]
readonly property string activeAccentName: ThemeProfileModel.curatedNameForProfile(
root.activeProfile)
property bool reconciling: false
function commitActive(profile: var): bool {
if (!profile)
return false;
// Scheme first: if another control changed it, the reconciliation hook
// may briefly select Day/Moon before this final stable profile id lands.
const schemeAccepted = SystemSettings.commitPreference("colorScheme", profile.scheme);
const profileAccepted = SystemSettings.commitPreference("themeProfileId", profile.id);
return schemeAccepted && profileAccepted;
}
function selectProfile(id: string): bool {
return root.commitActive(ThemeProfileModel.findProfile(root.customProfiles, id));
}
// Editing a shipped profile creates a saved custom copy. Editing a custom
// profile updates only that record. ThemeProfileModel enforces both rules,
// leaving this singleton responsible only for validated preference routing.
function setAccentPair(accent: string, secondary: string): bool {
const result = ThemeProfileModel.editProfile(root.customProfiles, root.activeProfile, {
accent: accent,
secondary: secondary
});
if (!result.profile)
return false;
if (!SystemSettings.commitPreference("themeProfiles", result.profiles))
return false;
return SystemSettings.commitPreference("themeProfileId", result.profile.id);
}
function saveProfile(name: string): bool {
const result = ThemeProfileModel.createCustomProfile(root.customProfiles, {
name: name,
scheme: root.activeProfile.scheme,
accent: root.activeProfile.accent,
secondary: root.activeProfile.secondary
});
if (!result.profile)
return false;
if (!SystemSettings.commitPreference("themeProfiles", result.profiles))
return false;
return SystemSettings.commitPreference("themeProfileId", result.profile.id);
}
function deleteProfile(id: string): bool {
const result = ThemeProfileModel.deleteProfile(root.customProfiles, id);
if (!result.removed)
return false;
if (!SystemSettings.commitPreference("themeProfiles", result.profiles))
return false;
if (root.activeId === id)
return root.selectProfile(DesktopPreferences.get("colorScheme") === "light" ? "day" : "moon");
return true;
}
function useCuratedAccent(name: string): bool {
const scheme = DesktopPreferences.get("colorScheme") === "light" ? "light" : "dark";
const pair = ThemeProfileModel.curatedPair(name, scheme);
const shipped = ThemeProfileModel.matchingShippedProfile(
scheme, pair.accent, pair.secondary);
const accepted = shipped
? root.commitActive(shipped)
: root.setAccentPair(pair.accent, pair.secondary);
if (accepted)
SystemSettings.commitPreference("accentName", name);
return accepted;
}
function reconcileScheme(): void {
if (root.reconciling)
return;
const scheme = DesktopPreferences.get("colorScheme") === "light" ? "light" : "dark";
if (root.activeProfile.scheme === scheme)
return;
root.reconciling = true;
SystemSettings.commitPreference("themeProfileId", scheme === "light" ? "day" : "moon");
root.reconciling = false;
}
Component.onCompleted: root.reconcileScheme()
Connections {
target: DesktopPreferences
function onRevisionChanged(): void { root.reconcileScheme(); }
}
}