From dddc7382a59009b6a0e7e2322559efd9087c5acf Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 15 Mar 2025 13:53:53 +1100 Subject: launcher: wallpaper random by category --- src/modules/launcher/actions.tsx | 47 +++++++++++++++++++++++++++++++--------- src/services/wallpapers.ts | 39 +++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/modules/launcher/actions.tsx b/src/modules/launcher/actions.tsx index 05005a4..4ebabfb 100644 --- a/src/modules/launcher/actions.tsx +++ b/src/modules/launcher/actions.tsx @@ -1,7 +1,7 @@ import { Apps } from "@/services/apps"; import Palette from "@/services/palette"; import Schemes, { type Colours } from "@/services/schemes"; -import Wallpapers from "@/services/wallpapers"; +import Wallpapers, { type ICategory, type IWallpaper } from "@/services/wallpapers"; import { basename } from "@/utils/strings"; import { notify } from "@/utils/system"; import { setupCustomTooltip, type FlowBox } from "@/utils/widgets"; @@ -285,7 +285,7 @@ const Scheme = ({ scheme, name, colours }: { scheme?: string; name: string; colo ); }; -const Wallpaper = ({ path, thumbnail }: { path: string; thumbnail?: string }) => ( +const Wallpaper = ({ path, thumbnail }: IWallpaper) => ( + +); + @register() export default class Actions extends Widget.Box implements LauncherContent { #map: ActionMap; @@ -348,9 +374,12 @@ export default class Actions extends Widget.Box implements LauncherContent { } } } else if (action === "wallpaper") { - const wallpaper = args[1] ?? ""; - for (const { obj } of fuzzysort.go(wallpaper, Wallpapers.get_default().list, { all: true, key: "path" })) - this.#content.add(); + const random = args[1].toLowerCase() === "random"; + const term = (random ? args[2] : args[1]) ?? ""; + const list = random ? Wallpapers.get_default().categories : Wallpapers.get_default().list; + + for (const { obj } of fuzzysort.go(term, list, { all: true, key: "path" })) + this.#content.add(random ? : ); } else { const list = this.#list.filter( a => this.#map[a].available?.() ?? !config.disabledActions.get().includes(a) @@ -364,11 +393,9 @@ export default class Actions extends Widget.Box implements LauncherContent { const args = search.split(" "); const action = args[0].slice(1).toLowerCase(); - if ((action === "scheme" || action === "wallpaper") && args[1].toLowerCase() === "random") { - execAsync(`caelestia ${action}`).catch(console.error); + if (action === "scheme" && args[1].toLowerCase() === "random") { + execAsync(`caelestia scheme`).catch(console.error); close(); - } - - this.#content.get_child_at_index(0)?.get_child()?.activate(); + } else this.#content.get_child_at_index(0)?.get_child()?.activate(); } } diff --git a/src/services/wallpapers.ts b/src/services/wallpapers.ts index 9a4e5bb..87a9c62 100644 --- a/src/services/wallpapers.ts +++ b/src/services/wallpapers.ts @@ -3,11 +3,16 @@ import { monitorDirectory } from "@/utils/system"; import { execAsync, GLib, GObject, property, register } from "astal"; import { wallpapers as config } from "config"; -export interface Wallpaper { +export interface IWallpaper { path: string; thumbnail?: string; } +export interface ICategory { + path: string; + wallpapers: IWallpaper[]; +} + @register({ GTypeName: "Wallpapers" }) export default class Wallpapers extends GObject.Object { static instance: Wallpapers; @@ -19,13 +24,19 @@ export default class Wallpapers extends GObject.Object { #thumbnailDir = `${CACHE}/thumbnails`; - #list: Wallpaper[] = []; + #list: IWallpaper[] = []; + #categories: ICategory[] = []; @property(Object) get list() { return this.#list; } + @property(Object) + get categories() { + return this.#categories; + } + async #thumbnail(path: string) { const dir = path.slice(1, path.lastIndexOf("/")).replaceAll("/", "-"); const thumbPath = `${this.#thumbnailDir}/${dir}-${basename(path)}.jpg`; @@ -33,20 +44,30 @@ export default class Wallpapers extends GObject.Object { return thumbPath; } + #listDir(path: { path: string; recursive: boolean }, type: "f" | "d") { + const absPath = path.path.replace("~", HOME); + const maxDepth = path.recursive ? "" : "-maxdepth 1"; + return execAsync(`find ${absPath} ${maxDepth} -path '*/.*' -prune -o -type ${type} -print`); + } + async update() { const results = await Promise.allSettled( - config.paths - .get() - .map(p => execAsync(`find ${p.path.replace("~", HOME)}/ ${p.recursive ? "" : "-maxdepth 1"} -type f`)) + config.paths.get().map(async p => ({ path: p, files: await this.#listDir(p, "f") })) ); - const files = results - .filter(r => r.status === "fulfilled") - .map(r => r.value.replaceAll("\n", " ")) - .join(" "); + const successes = results.filter(r => r.status === "fulfilled").map(r => r.value); + + const files = successes.map(r => r.files.replaceAll("\n", " ")).join(" "); const list = (await execAsync(["fish", "-c", `identify -ping -format '%i\n' ${files} ; true`])).split("\n"); this.#list = await Promise.all(list.map(async p => ({ path: p, thumbnail: await this.#thumbnail(p) }))); this.notify("list"); + + const categories = await Promise.all(successes.map(r => this.#listDir(r.path, "d"))); + this.#categories = categories + .flatMap(c => c.split("\n")) + .map(c => ({ path: c, wallpapers: this.#list.filter(w => w.path.startsWith(c)) })) + .filter(c => c.wallpapers.length > 0); + this.notify("categories"); } constructor() { -- cgit v1.2.3-freya