summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-04 14:19:38 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-04 14:19:38 +1000
commit9c4821b4b4c298eeaec6c108f435de4cb5fefc16 (patch)
treeacbba6cff7c1550e60db3c6a15ad3f54e8f36979
parentfeat: launcher wallpaper selector (diff)
downloadcaelestia-shell-9c4821b4b4c298eeaec6c108f435de4cb5fefc16.tar.gz
caelestia-shell-9c4821b4b4c298eeaec6c108f435de4cb5fefc16.tar.bz2
caelestia-shell-9c4821b4b4c298eeaec6c108f435de4cb5fefc16.zip
feat: cache wallpapers
Reduces wallpaper load time massively
-rw-r--r--modules/launcher/WallpaperItem.qml10
-rw-r--r--services/Thumbnailer.qml45
-rw-r--r--services/Wallpapers.qml4
-rw-r--r--widgets/CachingImage.qml45
4 files changed, 95 insertions, 9 deletions
diff --git a/modules/launcher/WallpaperItem.qml b/modules/launcher/WallpaperItem.qml
index bbd611c..c3dd57a 100644
--- a/modules/launcher/WallpaperItem.qml
+++ b/modules/launcher/WallpaperItem.qml
@@ -25,22 +25,18 @@ StyledRect {
}
}
- Image {
+ CachingImage {
id: image
anchors.horizontalCenter: parent.horizontalCenter
y: Appearance.padding.normal
visible: false
- source: `file://${root.modelData.path}`
- asynchronous: true
- fillMode: Image.PreserveAspectCrop
+ path: root.modelData.path
smooth: !root.PathView.view.moving
width: LauncherConfig.sizes.wallpaperWidth
height: width / 16 * 9
- sourceSize.width: width
- sourceSize.height: height
}
Rectangle {
@@ -70,7 +66,7 @@ StyledRect {
renderType: Text.QtRendering
text: root.modelData.name
- font.pointSize: Appearance.font.size.small
+ font.pointSize: Appearance.font.size.normal
}
Behavior on scale {
diff --git a/services/Thumbnailer.qml b/services/Thumbnailer.qml
new file mode 100644
index 0000000..1e22940
--- /dev/null
+++ b/services/Thumbnailer.qml
@@ -0,0 +1,45 @@
+pragma Singleton
+
+import Quickshell
+import Quickshell.Io
+import QtQuick
+import Qt.labs.platform
+
+Singleton {
+ id: root
+
+ readonly property string thumbDir: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/caelestia/thumbnails`.slice(7)
+
+ function go(sha: string, path: string, width: int, height: int): string {
+ if (!sha || !path || !width || !height)
+ return "";
+
+ const thumbPath = `${thumbDir}/${sha}@${width}x${height}-exact.png`;
+
+ thumbProc.path = path;
+ thumbProc.thumbPath = thumbPath;
+ thumbProc.width = width;
+ thumbProc.height = height;
+ thumbProc.startDetached();
+
+ return thumbPath;
+ }
+
+ Process {
+ id: thumbProc
+
+ property string path
+ property string thumbPath
+ property int width
+ property int height
+
+ command: ["fish", "-c", `
+if ! test -f ${thumbPath}
+ set -l size (identify -ping -format '%w\n%h' ${path})
+ if test $size[1] -gt ${width} -o $size[2] -gt ${height}
+ magick ${path} -thumbnail ${width}x${height}^ -background none -gravity center -extent ${width}x${height} -unsharp 0x.5 ${thumbPath}
+ end
+end
+`]
+ }
+}
diff --git a/services/Wallpapers.qml b/services/Wallpapers.qml
index 833e808..bd6528d 100644
--- a/services/Wallpapers.qml
+++ b/services/Wallpapers.qml
@@ -9,7 +9,7 @@ import Qt.labs.platform
Singleton {
id: root
- readonly property string path: `${StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]}/Wallpapers`
+ readonly property string path: `${StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]}/Wallpapers`.slice(7)
property list<Wallpaper> list
@@ -28,7 +28,7 @@ Singleton {
Process {
running: true
- command: ["fd", ".", root.path.slice(7), "-t", "f", "-e", "jpg", "-e", "jpeg", "-e", "png", "-e", "svg"]
+ command: ["fd", ".", root.path, "-t", "f", "-e", "jpg", "-e", "jpeg", "-e", "png", "-e", "svg"]
stdout: SplitParser {
splitMarker: ""
onRead: data => {
diff --git a/widgets/CachingImage.qml b/widgets/CachingImage.qml
new file mode 100644
index 0000000..cff5676
--- /dev/null
+++ b/widgets/CachingImage.qml
@@ -0,0 +1,45 @@
+import "root:/services"
+import Quickshell.Io
+import QtQuick
+
+Image {
+ id: root
+
+ required property string path
+ property string thumbnail: path
+
+ source: `file://${thumbnail}`
+ asynchronous: true
+ fillMode: Image.PreserveAspectCrop
+
+ onPathChanged: shaProc.running = true
+ onWidthChanged: shaProc.running = true
+ onHeightChanged: shaProc.running = true
+ onStatusChanged: {
+ if (status === Image.Error)
+ waitProc.running = true;
+ }
+
+ Process {
+ id: shaProc
+
+ command: ["sha1sum", root.path]
+ stdout: SplitParser {
+ onRead: data => root.thumbnail = Thumbnailer.go(data.split(" ")[0], root.path, root.width, root.height)
+ }
+ }
+
+ Process {
+ id: waitProc
+
+ command: ["inotifywait", "-q", "-e", "close_write", "--format", "%w%f", "-m", root.thumbnail.slice(0, root.thumbnail.lastIndexOf("/"))]
+ stdout: SplitParser {
+ onRead: file => {
+ if (file === root.thumbnail) {
+ root.source = file;
+ waitProc.running = false;
+ }
+ }
+ }
+ }
+}