import { Apps as AppsService } from "@/services/apps"; import MathService, { type HistoryItem } from "@/services/math"; import { getAppCategoryIcon } from "@/utils/icons"; import { launch } from "@/utils/system"; import { type FlowBox, setupCustomTooltip } from "@/utils/widgets"; import { bind, execAsync, Gio, register, Variable } from "astal"; import { Astal, Gtk, Widget } from "astal/gtk3"; import { launcher as config } from "config"; import type AstalApps from "gi://AstalApps"; import { close, ContentBox, type LauncherContent, limitLength } from "./util"; const AppResult = ({ app }: { app: AstalApps.Application }) => ( ); const FileResult = ({ path }: { path: string }) => ( ); const MathResult = ({ icon, equation, result }: HistoryItem) => ( ); @register() class Apps extends Widget.Box implements LauncherContent { #content: FlowBox; constructor() { super({ name: "apps", className: "apps" }); this.#content = () as FlowBox; this.add( {this.#content} ); } updateContent(search: string): void { this.#content.foreach(c => c.destroy()); for (const app of limitLength(AppsService.fuzzy_query(search), config.apps)) this.#content.add(); } handleActivate(): void { this.#content.get_child_at_index(0)?.get_child()?.grab_focus(); this.#content.get_child_at_index(0)?.get_child()?.activate(); } } @register() class Files extends Widget.Box implements LauncherContent { #content: FlowBox; constructor() { super({ name: "files", className: "files" }); this.#content = () as FlowBox; this.add( {this.#content} ); } updateContent(search: string): void { execAsync(["fd", ...config.files.fdOpts.get(), search, HOME]) .then(out => { this.#content.foreach(c => c.destroy()); const paths = out.split("\n").filter(path => path); for (const path of limitLength(paths, config.files)) this.#content.add(); }) .catch(() => {}); // Ignore errors } handleActivate(): void { this.#content.get_child_at_index(0)?.get_child()?.grab_focus(); this.#content.get_child_at_index(0)?.get_child()?.activate(); } } @register() class Math extends Widget.Box implements LauncherContent { #showResult: Variable; #result: Variable; #content: FlowBox; constructor() { super({ name: "math", className: "math", vertical: true }); this.#showResult = Variable(false); this.#result = Variable({ equation: "", result: "", icon: "" }); this.#content = () as FlowBox; this.add( ); this.add( {this.#content} ); } updateContent(search: string): void { this.#showResult.set(search.length > 0); this.#result.set(MathService.get_default().evaluate(search)); this.#content.foreach(c => c.destroy()); for (const item of limitLength(MathService.get_default().history, config.math)) this.#content.add(); } handleActivate(search: string): void { if (!search) return; MathService.get_default().commit(); const res = this.#result.get(); // Copy and close if not assignment, help or error if (!["equal", "help", "error"].includes(res.icon)) { execAsync(["wl-copy", "--", res.result]).catch(console.error); close(); } } } export default () => ({ apps: new Apps(), files: new Files(), math: new Math(), });