launcher: wallpaper random by category
This commit is contained in:
parent
877c254740
commit
dddc7382a5
3 changed files with 80 additions and 19 deletions
|
|
@ -188,6 +188,19 @@
|
|||
|
||||
.thumbnail {
|
||||
@include lib.rounded(10);
|
||||
|
||||
& > * {
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
&:first-child {
|
||||
@include lib.rounded(10, $tr: 0, $br: 0);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@include lib.rounded(10, $tl: 0, $bl: 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => (
|
||||
<Gtk.FlowBoxChild visible canFocus={false}>
|
||||
<button
|
||||
className="result"
|
||||
|
|
@ -307,6 +307,32 @@ const Wallpaper = ({ path, thumbnail }: { path: string; thumbnail?: string }) =>
|
|||
</Gtk.FlowBoxChild>
|
||||
);
|
||||
|
||||
const Category = ({ path, wallpapers }: ICategory) => (
|
||||
<Gtk.FlowBoxChild visible canFocus={false}>
|
||||
<button
|
||||
className="result"
|
||||
cursor="pointer"
|
||||
onClicked={() => {
|
||||
execAsync(`caelestia wallpaper -d ${path}`).catch(console.error);
|
||||
close();
|
||||
}}
|
||||
setup={self => setupCustomTooltip(self, path.replace(HOME, "~"))}
|
||||
>
|
||||
<box
|
||||
vertical={config.wallpaper.style.get() !== "compact"}
|
||||
className={`wallpaper ${config.wallpaper.style.get()}`}
|
||||
>
|
||||
<box className="thumbnail">
|
||||
{wallpapers.slice(0, 3).map(w => (
|
||||
<box hexpand css={"background-image: url('" + (w.thumbnail ?? w.path) + "');"} />
|
||||
))}
|
||||
</box>
|
||||
<label truncate label={basename(path)} />
|
||||
</box>
|
||||
</button>
|
||||
</Gtk.FlowBoxChild>
|
||||
);
|
||||
|
||||
@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(<Wallpaper {...obj} />);
|
||||
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 ? <Category {...(obj as ICategory)} /> : <Wallpaper {...obj} />);
|
||||
} 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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue