1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-28 23:42:51 -05:00

meta: support async launcher plugins, cached GIFs, paste on launcher v2

action
- Preparations for DankGifSearch plugin
This commit is contained in:
bbedward
2026-01-23 12:02:12 -05:00
parent 808ee66e11
commit 972fc534a4
8 changed files with 141 additions and 34 deletions

View File

@@ -1,13 +1,21 @@
import QtQuick
import qs.Common
Image {
Item {
id: root
property string imagePath: ""
property int maxCacheSize: 512
property int status: isAnimated ? animatedImg.status : staticImg.status
property int fillMode: Image.PreserveAspectCrop
readonly property bool isRemoteUrl: imagePath.startsWith("http://") || imagePath.startsWith("https://")
readonly property bool isAnimated: {
if (!imagePath)
return false;
const lower = imagePath.toLowerCase();
return lower.endsWith(".gif") || lower.endsWith(".webp");
}
readonly property string normalizedPath: {
if (!imagePath)
return "";
@@ -30,7 +38,7 @@ Image {
}
readonly property string imageHash: normalizedPath ? djb2Hash(normalizedPath) : ""
readonly property string cachePath: imageHash && !isRemoteUrl ? `${Paths.stringify(Paths.imagecache)}/${imageHash}@${maxCacheSize}x${maxCacheSize}.png` : ""
readonly property string cachePath: imageHash && !isRemoteUrl && !isAnimated ? `${Paths.stringify(Paths.imagecache)}/${imageHash}@${maxCacheSize}x${maxCacheSize}.png` : ""
readonly property string encodedImagePath: {
if (!normalizedPath)
return "";
@@ -39,39 +47,56 @@ Image {
return "file://" + normalizedPath.split('/').map(s => encodeURIComponent(s)).join('/');
}
asynchronous: true
fillMode: Image.PreserveAspectCrop
sourceSize.width: maxCacheSize
sourceSize.height: maxCacheSize
smooth: true
AnimatedImage {
id: animatedImg
anchors.fill: parent
visible: root.isAnimated
asynchronous: true
fillMode: root.fillMode
source: root.isAnimated ? root.imagePath : ""
playing: visible && status === AnimatedImage.Ready
}
Image {
id: staticImg
anchors.fill: parent
visible: !root.isAnimated
asynchronous: true
fillMode: root.fillMode
sourceSize.width: root.maxCacheSize
sourceSize.height: root.maxCacheSize
smooth: true
onStatusChanged: {
if (source == root.cachePath && status === Image.Error) {
source = root.encodedImagePath;
return;
}
if (root.isRemoteUrl || source != root.encodedImagePath || status !== Image.Ready || !root.cachePath)
return;
Paths.mkdir(Paths.imagecache);
const grabPath = root.cachePath;
if (visible && width > 0 && height > 0 && Window.window?.visible) {
grabToImage(res => res.saveToFile(grabPath));
}
}
}
onImagePathChanged: {
if (!imagePath) {
source = "";
staticImg.source = "";
return;
}
if (isAnimated)
return;
if (isRemoteUrl) {
source = imagePath;
staticImg.source = imagePath;
return;
}
Paths.mkdir(Paths.imagecache);
const hash = djb2Hash(normalizedPath);
const cPath = hash ? `${Paths.stringify(Paths.imagecache)}/${hash}@${maxCacheSize}x${maxCacheSize}.png` : "";
const encoded = "file://" + normalizedPath.split('/').map(s => encodeURIComponent(s)).join('/');
source = cPath || encoded;
}
onStatusChanged: {
if (source == cachePath && status === Image.Error) {
source = encodedImagePath;
return;
}
if (isRemoteUrl || source != encodedImagePath || status !== Image.Ready || !cachePath)
return;
Paths.mkdir(Paths.imagecache);
const grabPath = cachePath;
if (visible && width > 0 && height > 0 && Window.window?.visible) {
grabToImage(res => res.saveToFile(grabPath));
}
staticImg.source = cPath || encoded;
}
}