thumbnailer: add configs

This commit is contained in:
2 * r + 2 * t 2025-04-05 18:17:42 +11:00
parent 7ace0bf1a2
commit ded52a0f1d
4 changed files with 20 additions and 17 deletions

View file

@ -147,4 +147,13 @@ export default {
upcomingDays: 7, // Number of days which count as upcoming upcomingDays: 7, // Number of days which count as upcoming
notify: true, notify: true,
}, },
thumbnailer: {
maxAttempts: 5,
timeBetweenAttempts: 300,
defaults: {
width: 100,
height: 100,
exact: true,
},
},
}; };

View file

@ -10,7 +10,6 @@ export const {
notifpopups, notifpopups,
osds, osds,
sidebar, sidebar,
sideleft,
math, math,
updates, updates,
weather, weather,
@ -20,5 +19,6 @@ export const {
storage, storage,
wallpapers, wallpapers,
calendar, calendar,
thumbnailer,
} = config; } = config;
export default config; export default config;

View file

@ -82,4 +82,9 @@ export default {
"calendar.webcals": ARR(STR), "calendar.webcals": ARR(STR),
"calendar.upcomingDays": NUM, "calendar.upcomingDays": NUM,
"calendar.notify": BOOL, "calendar.notify": BOOL,
"thumbnailer.maxAttempts": NUM,
"thumbnailer.timeBetweenAttempts": NUM,
"thumbnailer.defaults.width": NUM,
"thumbnailer.defaults.height": NUM,
"thumbnailer.defaults.exact": BOOL,
} as { [k: string]: string | string[] | number[] }; } as { [k: string]: string | string[] | number[] };

View file

@ -1,4 +1,5 @@
import { execAsync, Gio, GLib } from "astal"; import { execAsync, GLib, type Variable } from "astal";
import { thumbnailer as config } from "config";
export interface ThumbOpts { export interface ThumbOpts {
width?: number; width?: number;
@ -9,19 +10,10 @@ export interface ThumbOpts {
export default class Thumbnailer { export default class Thumbnailer {
static readonly thumbnailDir = `${CACHE}/thumbnails`; static readonly thumbnailDir = `${CACHE}/thumbnails`;
static lazy: boolean = true;
static maxAttempts: number = 5;
static timeBetweenAttempts: number = 300;
static defaults: Required<ThumbOpts> = {
width: 100,
height: 100,
exact: true,
};
static readonly #running = new Set<string>(); static readonly #running = new Set<string>();
static getOpt<T extends keyof ThumbOpts>(opt: T, opts: ThumbOpts) { static getOpt<T extends keyof ThumbOpts>(opt: T, opts: ThumbOpts) {
return opts[opt] ?? this.defaults[opt]; return opts[opt] ?? (config.defaults[opt] as Variable<NonNullable<ThumbOpts[T]>>).get();
} }
static async getThumbPath(path: string, opts: ThumbOpts) { static async getThumbPath(path: string, opts: ThumbOpts) {
@ -45,12 +37,12 @@ export default class Thumbnailer {
const cropCmd = this.getOpt("exact", opts) ? `-gravity Center -extent ${width}x${height}` : ""; const cropCmd = this.getOpt("exact", opts) ? `-gravity Center -extent ${width}x${height}` : "";
await execAsync(`magick ${path} -thumbnail ${width}x${height}^ ${cropCmd} -unsharp 0x.5 ${thumbPath}`); await execAsync(`magick ${path} -thumbnail ${width}x${height}^ ${cropCmd} -unsharp 0x.5 ${thumbPath}`);
} catch { } catch {
if (attempts >= this.maxAttempts) { if (attempts >= config.maxAttempts.get()) {
console.error(`Failed to generate thumbnail for ${path}`); console.error(`Failed to generate thumbnail for ${path}`);
return path; return path;
} }
await new Promise(r => setTimeout(r, this.timeBetweenAttempts)); await new Promise(r => setTimeout(r, config.timeBetweenAttempts.get()));
return this.#thumbnail(path, opts, attempts + 1); return this.#thumbnail(path, opts, attempts + 1);
} }
@ -62,9 +54,6 @@ export default class Thumbnailer {
let thumbPath = await this.getThumbPath(path, opts); let thumbPath = await this.getThumbPath(path, opts);
// If not lazy (i.e. force gen), delete existing thumbnail
if (!this.lazy) Gio.File.new_for_path(thumbPath).delete(null);
// Wait for existing thumbnail for path to finish // Wait for existing thumbnail for path to finish
while (this.#running.has(path)) await new Promise(r => setTimeout(r, 100)); while (this.#running.has(path)) await new Promise(r => setTimeout(r, 100));