1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-03 20:32:07 -04:00

refactor(icons): centralize icon resolution into Paths.resolveIconPath/resolveIconUrl (#1880)

Supersedes #1878. Rather than duplicating the moddedAppId + file path
substitution pattern inline across 8 files, this introduces two
centralized functions in Paths.qml:

- resolveIconPath(iconName): for Quickshell.iconPath() callsites,
  with DesktopService.resolveIconPath() fallback
- resolveIconUrl(iconName): for image://icon/ URL callsites

All consumer files now use one-line calls. When no substitutions are
configured, moddedAppId() returns the original name unchanged (zero
cost), so this has no impact on users who don't use the feature.

Affected components:
- AppIconRenderer (8 lines → 1)
- NotificationCard, NotificationPopup, HistoryNotificationCard
- DockContextMenu, AppsDockContextMenu
- LauncherContent, LauncherTab (×3)

Co-authored-by: odtgit <odtgit@taliops.com>
This commit is contained in:
odt
2026-03-01 23:31:51 +01:00
committed by GitHub
parent 537c44e354
commit 0f8e0bc2b4
9 changed files with 39 additions and 26 deletions

View File

@@ -71,19 +71,40 @@ Singleton {
return appId; return appId;
} }
function getAppIcon(appId: string, desktopEntry: var): string { function resolveIconPath(iconName: string): string {
if (appId === "org.quickshell") { if (!iconName) return "";
return Qt.resolvedUrl("../assets/danklogo.svg"); const moddedId = moddedAppId(iconName);
} if (moddedId !== iconName) {
const moddedId = moddedAppId(appId);
if (moddedId !== appId) {
if (moddedId.startsWith("~") || moddedId.startsWith("/")) if (moddedId.startsWith("~") || moddedId.startsWith("/"))
return toFileUrl(expandTilde(moddedId)); return toFileUrl(expandTilde(moddedId));
if (moddedId.startsWith("file://")) if (moddedId.startsWith("file://"))
return moddedId; return moddedId;
return Quickshell.iconPath(moddedId, true); return Quickshell.iconPath(moddedId, true);
} }
return Quickshell.iconPath(iconName, true) || 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;
}
function getAppIcon(appId: string, desktopEntry: var): string {
if (appId === "org.quickshell") {
return Qt.resolvedUrl("../assets/danklogo.svg");
}
const moddedId = moddedAppId(appId);
if (moddedId !== appId)
return resolveIconPath(appId);
if (desktopEntry && desktopEntry.icon) { if (desktopEntry && desktopEntry.icon) {
return Quickshell.iconPath(desktopEntry.icon, true); return Quickshell.iconPath(desktopEntry.icon, true);

View File

@@ -789,7 +789,7 @@ FocusScope {
Image { Image {
width: 40 width: 40
height: 40 height: 40
source: editingApp?.icon ? "image://icon/" + editingApp.icon : "image://icon/application-x-executable" source: Paths.resolveIconUrl(editingApp?.icon || "application-x-executable")
sourceSize.width: 40 sourceSize.width: 40
sourceSize.height: 40 sourceSize.height: 40
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit

View File

@@ -273,7 +273,7 @@ PanelWindow {
IconImage { IconImage {
anchors.fill: parent anchors.fill: parent
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : "" source: modelData.icon ? Paths.resolveIconPath(modelData.icon) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready

View File

@@ -329,7 +329,7 @@ PanelWindow {
IconImage { IconImage {
anchors.fill: parent anchors.fill: parent
source: modelData.icon ? Quickshell.iconPath(modelData.icon, true) : "" source: modelData.icon ? Paths.resolveIconPath(modelData.icon) : ""
smooth: true smooth: true
asynchronous: true asynchronous: true
visible: status === Image.Ready visible: status === Image.Ready

View File

@@ -142,7 +142,7 @@ Rectangle {
return appIcon; return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:")) if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return ""; return "";
return Quickshell.iconPath(appIcon, true); return Paths.resolveIconPath(appIcon);
} }
hasImage: hasNotificationImage hasImage: hasNotificationImage

View File

@@ -220,7 +220,7 @@ Rectangle {
return appIcon; return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:")) if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return ""; return "";
return Quickshell.iconPath(appIcon, true); return Paths.resolveIconPath(appIcon);
} }
hasImage: hasNotificationImage hasImage: hasNotificationImage
@@ -557,7 +557,7 @@ Rectangle {
return appIcon; return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:")) if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return ""; return "";
return Quickshell.iconPath(appIcon, true); return Paths.resolveIconPath(appIcon);
} }
fallbackIcon: { fallbackIcon: {

View File

@@ -524,7 +524,7 @@ PanelWindow {
return appIcon; return appIcon;
if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:")) if (appIcon.startsWith("material:") || appIcon.startsWith("svg:") || appIcon.startsWith("unicode:") || appIcon.startsWith("image:"))
return ""; return "";
return Quickshell.iconPath(appIcon, true); return Paths.resolveIconPath(appIcon);
} }
hasImage: hasNotificationImage hasImage: hasNotificationImage

View File

@@ -897,7 +897,7 @@ Item {
Image { Image {
width: 24 width: 24
height: 24 height: 24
source: modelData.icon ? "image://icon/" + modelData.icon : "image://icon/application-x-executable" source: Paths.resolveIconUrl(modelData.icon || "application-x-executable")
sourceSize.width: 24 sourceSize.width: 24
sourceSize.height: 24 sourceSize.height: 24
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
@@ -1008,7 +1008,7 @@ Item {
Image { Image {
width: 24 width: 24
height: 24 height: 24
source: modelData.icon ? "image://icon/" + modelData.icon : "image://icon/application-x-executable" source: Paths.resolveIconUrl(modelData.icon || "application-x-executable")
sourceSize.width: 24 sourceSize.width: 24
sourceSize.height: 24 sourceSize.height: 24
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit
@@ -1154,7 +1154,7 @@ Item {
Image { Image {
width: 24 width: 24
height: 24 height: 24
source: modelData.icon ? "image://icon/" + modelData.icon : "image://icon/application-x-executable" source: Paths.resolveIconUrl(modelData.icon || "application-x-executable")
sourceSize.width: 24 sourceSize.width: 24
sourceSize.height: 24 sourceSize.height: 24
fillMode: Image.PreserveAspectFit fillMode: Image.PreserveAspectFit

View File

@@ -49,15 +49,7 @@ Item {
readonly property string iconPath: { readonly property string iconPath: {
if (hasSpecialPrefix || !iconValue) if (hasSpecialPrefix || !iconValue)
return ""; return "";
const moddedId = Paths.moddedAppId(iconValue); return Paths.resolveIconPath(iconValue);
if (moddedId !== iconValue) {
if (moddedId.startsWith("~") || moddedId.startsWith("/"))
return Paths.toFileUrl(Paths.expandTilde(moddedId));
if (moddedId.startsWith("file://"))
return moddedId;
return Quickshell.iconPath(moddedId, true);
}
return Quickshell.iconPath(iconValue, true) || DesktopService.resolveIconPath(iconValue);
} }
visible: iconValue !== undefined && iconValue !== "" visible: iconValue !== undefined && iconValue !== ""