1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-13 01:02:18 -04:00

widgets: make AnimatedImage conditional in DankCircularImage - Cut potential overhead of always using AnimatedImage

This commit is contained in:
bbedward
2026-02-23 09:51:56 -05:00
parent 5c5ff6195a
commit e282831c2e

View File

@@ -10,14 +10,17 @@ Rectangle {
property string fallbackIcon: "notifications" property string fallbackIcon: "notifications"
property string fallbackText: "" property string fallbackText: ""
property bool hasImage: imageSource !== "" property bool hasImage: imageSource !== ""
property alias imageStatus: internalImage.status // Probe with AnimatedImage first; once loaded, check frameCount to decide.
readonly property bool isAnimated: probe.status === Image.Ready && probe.frameCount > 1
readonly property var activeImage: isAnimated ? probe : staticImage
property int imageStatus: activeImage.status
signal imageSaved(string filePath) signal imageSaved(string filePath)
function saveImageToFile(filePath) { function saveImageToFile(filePath) {
if (internalImage.status !== Image.Ready) if (activeImage.status !== Image.Ready)
return false; return false;
internalImage.grabToImage(function (result) { activeImage.grabToImage(function (result) {
if (result && result.saveToFile(filePath)) { if (result && result.saveToFile(filePath)) {
root.imageSaved(filePath); root.imageSaved(filePath);
} }
@@ -30,8 +33,9 @@ Rectangle {
border.color: "transparent" border.color: "transparent"
border.width: 0 border.width: 0
// Probe: loads as AnimatedImage to detect frame count.
AnimatedImage { AnimatedImage {
id: internalImage id: probe
anchors.fill: parent anchors.fill: parent
anchors.margins: 2 anchors.margins: 2
asynchronous: true asynchronous: true
@@ -43,13 +47,46 @@ Rectangle {
source: root.imageSource source: root.imageSource
} }
// Static fallback: used once probe confirms the image is not animated.
Image {
id: staticImage
anchors.fill: parent
anchors.margins: 2
asynchronous: true
fillMode: Image.PreserveAspectCrop
smooth: true
mipmap: true
cache: true
visible: false
source: ""
}
// Once the probe loads, if not animated, hand off to Image and unload probe.
Connections {
target: probe
function onStatusChanged() {
if (probe.status !== Image.Ready)
return;
if (probe.frameCount <= 1) {
staticImage.source = root.imageSource;
probe.source = "";
}
}
}
// If imageSource changes, reset: re-probe with AnimatedImage.
onImageSourceChanged: {
staticImage.source = "";
probe.source = root.imageSource;
}
MultiEffect { MultiEffect {
anchors.fill: parent anchors.fill: parent
anchors.margins: 2 anchors.margins: 2
source: internalImage source: root.activeImage
maskEnabled: true maskEnabled: true
maskSource: circularMask maskSource: circularMask
visible: internalImage.status === Image.Ready && root.imageSource !== "" visible: root.activeImage.status === Image.Ready && root.imageSource !== ""
maskThresholdMin: 0.5 maskThresholdMin: 0.5
maskSpreadAtMin: 1 maskSpreadAtMin: 1
} }
@@ -75,7 +112,7 @@ Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
width: Math.round(parent.width * 0.75) width: Math.round(parent.width * 0.75)
height: width height: width
visible: (internalImage.status !== Image.Ready || root.imageSource === "") && root.fallbackIcon !== "" visible: (root.activeImage.status !== Image.Ready || root.imageSource === "") && root.fallbackIcon !== ""
iconValue: root.fallbackIcon iconValue: root.fallbackIcon
iconSize: width iconSize: width
iconColor: Theme.surfaceVariantText iconColor: Theme.surfaceVariantText