1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-06-22 11:05:22 -04:00

theme/icons: add separate light/dark path, hot-reload, detect external

DMS maangedand reset
fixes #608
closes #2674
This commit is contained in:
bbedward
2026-06-20 15:23:19 -04:00
parent 4203148cab
commit de91b78943
7 changed files with 417 additions and 37 deletions
+22 -12
View File
@@ -74,6 +74,15 @@ Singleton {
return appId;
}
function themedIconPath(name: string): string {
if (!name)
return "";
const themed = (typeof IconThemeService !== "undefined") ? IconThemeService.resolve(name) : "";
if (themed)
return themed;
return Quickshell.iconPath(name, true);
}
function resolveIconPath(iconName: string): string {
if (!iconName)
return "";
@@ -83,23 +92,24 @@ Singleton {
return toFileUrl(expandTilde(moddedId));
if (moddedId.startsWith("file://"))
return moddedId;
return Quickshell.iconPath(moddedId, true);
return themedIconPath(moddedId);
}
return Quickshell.iconPath(iconName, true) || DesktopService.resolveIconPath(iconName);
return themedIconPath(iconName) || DesktopService.resolveIconPath(iconName);
}
function resolveIconUrl(iconName: string): string {
if (!iconName)
return "";
const moddedId = moddedAppId(iconName);
if (moddedId !== iconName) {
if (moddedId.startsWith("~") || moddedId.startsWith("/"))
return toFileUrl(expandTilde(moddedId));
if (moddedId.startsWith("file://"))
return moddedId;
return "image://icon/" + moddedId;
}
return "image://icon/" + iconName;
const target = (moddedId !== iconName) ? moddedId : iconName;
if (target.startsWith("~") || target.startsWith("/"))
return toFileUrl(expandTilde(target));
if (target.startsWith("file://"))
return target;
const themed = (typeof IconThemeService !== "undefined") ? IconThemeService.resolve(target) : "";
if (themed)
return themed;
return "image://icon/" + target;
}
function getAppIcon(appId: string, desktopEntry: var): string {
@@ -113,10 +123,10 @@ Singleton {
return resolveIconPath(appId);
if (desktopEntry && desktopEntry.icon) {
return Quickshell.iconPath(desktopEntry.icon, true);
return themedIconPath(desktopEntry.icon);
}
const icon = Quickshell.iconPath(appId, true);
const icon = themedIconPath(appId);
if (icon && icon !== "")
return icon;
+92 -8
View File
@@ -487,7 +487,11 @@ Singleton {
property string networkPreference: "auto"
property string iconTheme: "System Default"
property string iconThemeDark: "System Default"
property string iconThemeLight: "System Default"
property bool iconThemePerMode: false
property string lastAppliedIconTheme: ""
readonly property string iconTheme: resolveIconTheme()
property var availableIconThemes: ["System Default"]
property string systemDefaultIconTheme: ""
property bool qt5ctAvailable: false
@@ -1279,14 +1283,67 @@ Singleton {
MangoService.generateLayoutConfig();
}
function resolveIconTheme() {
if (iconThemePerMode && typeof SessionData !== "undefined" && SessionData.isLightMode)
return iconThemeLight;
return iconThemeDark;
}
function applyStoredIconTheme() {
updateGtkIconTheme();
updateQtIconTheme();
updateCosmicIconTheme();
}
function setIconThemeUnmanaged() {
iconThemePerMode = false;
iconThemeDark = "System Default";
iconThemeLight = "System Default";
lastAppliedIconTheme = "";
saveSettings();
}
function checkIconThemeDrift() {
if (isGreeterMode)
return;
if (resolveIconTheme() === "System Default")
return;
if (!lastAppliedIconTheme)
return;
const script = `if command -v gsettings >/dev/null 2>&1; then
gsettings get org.gnome.desktop.interface icon-theme 2>/dev/null | sed "s/'//g"
elif command -v dconf >/dev/null 2>&1; then
dconf read /org/gnome/desktop/interface/icon-theme 2>/dev/null | sed "s/'//g"
fi`;
Proc.runCommand("iconThemeDriftCheck", ["sh", "-c", script], (output, exitCode) => {
const platform = (output || "").trim();
if (!platform)
return;
if (platform === root.lastAppliedIconTheme || platform === root.iconThemeDark || platform === root.iconThemeLight)
return;
root.setIconThemeUnmanaged();
ToastService.showWarning(I18n.tr("Icon theme changed outside DMS; switched to System Default", "shown when an external tool overrides the icon theme DMS applied"));
});
}
Connections {
target: typeof SessionData !== "undefined" ? SessionData : null
function onIsLightModeChanged() {
if (!SessionData.isSwitchingMode)
return;
if (!root.iconThemePerMode)
return;
if (root.iconThemeLight === root.iconThemeDark)
return;
root.applyStoredIconTheme();
root.saveSettings();
}
}
function updateCosmicIconTheme() {
let cosmicThemeName = (iconTheme === "System Default") ? systemDefaultIconTheme : iconTheme;
const resolved = resolveIconTheme();
let cosmicThemeName = (resolved === "System Default") ? systemDefaultIconTheme : resolved;
if (!cosmicThemeName || cosmicThemeName === "System Default") {
const detectScript = `if command -v gsettings >/dev/null 2>&1; then
gsettings get org.gnome.desktop.interface icon-theme 2>/dev/null | sed "s/'//g"
@@ -1322,9 +1379,11 @@ Singleton {
}
function updateGtkIconTheme() {
const gtkThemeName = (iconTheme === "System Default") ? systemDefaultIconTheme : iconTheme;
const resolved = resolveIconTheme();
const gtkThemeName = (resolved === "System Default") ? systemDefaultIconTheme : resolved;
if (gtkThemeName === "System Default" || gtkThemeName === "")
return;
lastAppliedIconTheme = gtkThemeName;
if (typeof DMSService !== "undefined" && DMSService.apiVersion >= 3 && typeof PortalService !== "undefined") {
PortalService.setSystemIconTheme(gtkThemeName);
}
@@ -1349,13 +1408,20 @@ Singleton {
fi
done
if command -v gsettings >/dev/null 2>&1; then
gsettings set org.gnome.desktop.interface icon-theme '${gtkThemeName}' 2>/dev/null || true
elif command -v dconf >/dev/null 2>&1; then
dconf write /org/gnome/desktop/interface/icon-theme "'${gtkThemeName}'" 2>/dev/null || true
fi
pkill -HUP -f 'gtk' 2>/dev/null || true`;
Quickshell.execDetached(["sh", "-lc", configScript]);
}
function updateQtIconTheme() {
const qtThemeName = (iconTheme === "System Default") ? "" : iconTheme;
const resolved = resolveIconTheme();
const qtThemeName = (resolved === "System Default") ? "" : resolved;
if (!qtThemeName)
return;
const home = _homeUrl.replace("file://", "").replace(/'/g, "'\\''");
@@ -1442,6 +1508,9 @@ Singleton {
if (obj?.directionalAnimationMode === 3 && frameMode !== "connected")
frameMode = "connected";
if (obj?.iconTheme !== undefined && obj?.iconThemeDark === undefined)
iconThemeDark = obj.iconTheme;
if (obj?.weatherLocation !== undefined)
_legacyWeatherLocation = obj.weatherLocation;
if (obj?.weatherCoordinates !== undefined)
@@ -1457,6 +1526,7 @@ Singleton {
applyStoredTheme();
updateCompositorCursor();
Processes.detectQtTools();
Qt.callLater(checkIconThemeDrift);
_checkSettingsWritable();
} catch (e) {
@@ -2464,10 +2534,24 @@ Singleton {
}
function setIconTheme(themeName) {
iconTheme = themeName;
updateGtkIconTheme();
updateQtIconTheme();
updateCosmicIconTheme();
const light = iconThemePerMode && typeof SessionData !== "undefined" && SessionData.isLightMode;
setIconThemeForMode(themeName, light);
}
function setIconThemeForMode(themeName, light) {
if (light)
iconThemeLight = themeName;
else
iconThemeDark = themeName;
applyStoredIconTheme();
saveSettings();
if (typeof Theme !== "undefined" && Theme.currentTheme === Theme.dynamic)
Theme.generateSystemThemesFromCurrentTheme();
}
function setIconThemePerMode(enabled) {
iconThemePerMode = enabled;
applyStoredIconTheme();
saveSettings();
if (typeof Theme !== "undefined" && Theme.currentTheme === Theme.dynamic)
Theme.generateSystemThemesFromCurrentTheme();
+4 -1
View File
@@ -244,7 +244,10 @@ var SPEC = {
networkPreference: { def: "auto" },
iconTheme: { def: "System Default", onChange: "applyStoredIconTheme" },
iconThemeDark: { def: "System Default", onChange: "applyStoredIconTheme" },
iconThemeLight: { def: "System Default", onChange: "applyStoredIconTheme" },
iconThemePerMode: { def: false, onChange: "applyStoredIconTheme" },
lastAppliedIconTheme: { def: "" },
availableIconThemes: { def: ["System Default"], persist: false },
systemDefaultIconTheme: { def: "", persist: false },
qt5ctAvailable: { def: false, persist: false },