From 31138ffd9348990fc3221352fc40d48dfcd59141 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 1 Mar 2025 19:08:15 +1100 Subject: launcher: scheme autocomplete --- app.tsx | 6 ++- scss/launcher.scss | 28 +++++++++++++ src/modules/launcher/actions.tsx | 85 ++++++++++++++++++++++++++++++++++------ src/services/schemes.ts | 44 +++++++++++++++++++++ 4 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 src/services/schemes.ts diff --git a/app.tsx b/app.tsx index 0739d01..d97d41d 100644 --- a/app.tsx +++ b/app.tsx @@ -7,8 +7,9 @@ import Session from "@/modules/session"; import Monitors from "@/services/monitors"; import Palette from "@/services/palette"; import Players from "@/services/players"; +import Schemes from "@/services/schemes"; import type PopupWindow from "@/widgets/popupwindow"; -import { execAsync, writeFileAsync } from "astal"; +import { execAsync, idle, writeFileAsync } from "astal"; import { App } from "astal/gtk3"; import { initConfig, updateConfig } from "config"; @@ -38,6 +39,9 @@ App.start({ Monitors.get_default().forEach(m => ); ; + // Init services + idle(() => Schemes.get_default()); + console.log(`Caelestia started in ${Date.now() - now}ms`); }, requestHandler(request, res) { diff --git a/scss/launcher.scss b/scss/launcher.scss index 7c775b7..49f09c8 100644 --- a/scss/launcher.scss +++ b/scss/launcher.scss @@ -125,4 +125,32 @@ background-color: scheme.$surface1; } } + + .swatches { + @include lib.spacing(3); + } + + .swatch { + @include lib.rounded(100); + + min-width: lib.s(16); + min-height: lib.s(16); + + &.big { + min-height: lib.s(32); + + &.left { + @include lib.border(scheme.$overlay0, 0.3); + + border-right: none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &.right { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } } diff --git a/src/modules/launcher/actions.tsx b/src/modules/launcher/actions.tsx index 52910ea..75f1092 100644 --- a/src/modules/launcher/actions.tsx +++ b/src/modules/launcher/actions.tsx @@ -1,4 +1,6 @@ import { Apps } from "@/services/apps"; +import type { IPalette } from "@/services/palette"; +import Schemes from "@/services/schemes"; import { notify } from "@/utils/system"; import { setupCustomTooltip, type FlowBox } from "@/utils/widgets"; import { execAsync, GLib, readFile, register, type Variable } from "astal"; @@ -19,6 +21,11 @@ interface ActionMap { [k: string]: IAction; } +const autocomplete = (entry: Widget.Entry, action: string) => { + entry.set_text(`${config.actionPrefix.get()}${action} `); + entry.set_position(-1); +}; + const actions = (mode: Variable, entry: Widget.Entry): ActionMap => ({ apps: { icon: "apps", @@ -62,27 +69,32 @@ const actions = (mode: Variable, entry: Widget.Entry): ActionMap => ({ description: "Change the current colour scheme", action: (...args) => { // If no args, autocomplete cmd - if (args.length === 0) { - entry.set_text(`${config.actionPrefix.get()}scheme `); - entry.set_position(-1); - return; - } + if (args.length === 0) return autocomplete(entry, "scheme"); execAsync(`caelestia scheme ${args[0]}`).catch(console.error); close(); }, }, + wallpaper: { + icon: "image", + name: "Wallpaper", + description: "Change the current wallpaper", + action: (...args) => { + // If no args, autocomplete cmd + if (args.length === 0) return autocomplete(entry, "wallpaper"); + + if (args[0] === "random") execAsync("caelestia wallpaper").catch(console.error); + else execAsync(`caelestia wallpaper -f ${args[0]}`).catch(console.error); + close(); + }, + }, todo: { icon: "checklist", name: "Todo", description: "Create a todo in Todoist", action: (...args) => { // If no args, autocomplete cmd - if (args.length === 0) { - entry.set_text(`${config.actionPrefix.get()}todo `); - entry.set_position(-1); - return; - } + if (args.length === 0) return autocomplete(entry, "todo"); // If tod not installed, notify if (!GLib.find_program_in_path("tod")) { @@ -165,6 +177,47 @@ const Action = ({ args, icon, name, description, action }: IAction & { args: str ); +const Swatch = ({ colour }: { colour: string }) => ; + +const Scheme = ({ name, colours }: { name: string; colours: IPalette }) => ( + + + +); + @register() export default class Actions extends Widget.Box implements LauncherContent { #map: ActionMap; @@ -190,8 +243,16 @@ export default class Actions extends Widget.Box implements LauncherContent { updateContent(search: string): void { this.#content.foreach(c => c.destroy()); const args = search.split(" "); - for (const { target } of fuzzysort.go(args[0].slice(1), this.#list, { all: true })) - this.#content.add(); + const action = args[0].slice(1); + + if (action === "scheme") { + const scheme = args[1] ?? ""; + for (const { target } of fuzzysort.go(scheme, Object.keys(Schemes.get_default().map), { all: true })) + this.#content.add(); + } else { + for (const { target } of fuzzysort.go(action, this.#list, { all: true })) + this.#content.add(); + } } handleActivate(): void { diff --git a/src/services/schemes.ts b/src/services/schemes.ts new file mode 100644 index 0000000..07d6ded --- /dev/null +++ b/src/services/schemes.ts @@ -0,0 +1,44 @@ +import { execAsync, GLib, GObject, monitorFile, property, readFileAsync, register } from "astal"; +import type { IPalette } from "./palette"; + +const DATA = `${GLib.get_user_data_dir()}/caelestia`; + +@register({ GTypeName: "Schemes" }) +export default class Schemes extends GObject.Object { + static instance: Schemes; + static get_default() { + if (!this.instance) this.instance = new Schemes(); + + return this.instance; + } + + #map: { [k: string]: IPalette } = {}; + + @property(Object) + get map() { + return this.#map; + } + + #schemePathToName(path: string) { + return path.slice(path.lastIndexOf("/") + 1, path.lastIndexOf(".")); + } + + async parseScheme(path: string) { + const schemeColours = (await readFileAsync(path)).split("\n").map(l => l.split(" ")); + return schemeColours.reduce((acc, [name, hex]) => ({ ...acc, [name]: `#${hex}` }), {} as IPalette); + } + + async update() { + const schemes = await execAsync(`find ${DATA}/scripts/data/schemes/ -type f`); + for (const scheme of schemes.split("\n")) + this.#map[this.#schemePathToName(scheme)] = await this.parseScheme(scheme); + this.notify("map"); + } + + constructor() { + super(); + + this.update().catch(console.error); + monitorFile(`${DATA}/scripts/data/schemes`, () => this.update().catch(console.error)); + } +} -- cgit v1.2.3-freya