diff options
| -rw-r--r-- | scss/launcher.scss | 23 | ||||
| -rw-r--r-- | src/modules/launcher.tsx | 61 |
2 files changed, 59 insertions, 25 deletions
diff --git a/scss/launcher.scss b/scss/launcher.scss index 7535699..3c4ff0b 100644 --- a/scss/launcher.scss +++ b/scss/launcher.scss @@ -80,14 +80,12 @@ .result { @include lib.element-decel; + border-bottom: lib.s(2) solid transparent; + padding-left: lib.s(10); + .icon { font-size: lib.s(32); } - } - - .apps .result { - border-bottom: lib.s(2) solid transparent; - padding-left: lib.s(10); & > box { @include lib.spacing(10); @@ -107,21 +105,6 @@ } } - // .result { - // @include lib.element-decel; - - // padding: lib.s(5) lib.s(10); - - // &:hover, - // &:focus { - // background-color: scheme.$surface0; - // } - - // &:active { - // background-color: scheme.$surface1; - // } - // } - .pinned-app { @include lib.rounded(5); diff --git a/src/modules/launcher.tsx b/src/modules/launcher.tsx index b6af58e..8e83fe2 100644 --- a/src/modules/launcher.tsx +++ b/src/modules/launcher.tsx @@ -3,8 +3,9 @@ import { getAppCategoryIcon } from "@/utils/icons"; import { launch } from "@/utils/system"; import { FlowBox } from "@/utils/widgets"; import PopupWindow from "@/widgets/popupwindow"; -import { bind, register, Variable } from "astal"; +import { bind, execAsync, Gio, register, Variable } from "astal"; import { App, Astal, Gtk, Widget } from "astal/gtk3"; +import { launcher as config } from "config"; import type AstalApps from "gi://AstalApps"; type Mode = "apps" | "files" | "math" | "windows"; @@ -32,6 +33,9 @@ const getPrettyMode = (mode: Mode) => { return mode; }; +const limitLength = <T,>(arr: T[], cfg: { maxResults: Variable<number> }) => + cfg.maxResults.get() > 0 && arr.length > cfg.maxResults.get() ? arr.slice(0, cfg.maxResults.get()) : arr; + const AppResult = ({ app }: { app: AstalApps.Application }) => ( <Gtk.FlowBoxChild visible canFocus={false}> <button @@ -54,6 +58,35 @@ const AppResult = ({ app }: { app: AstalApps.Application }) => ( </Gtk.FlowBoxChild> ); +const FileResult = ({ path }: { path: string }) => ( + <Gtk.FlowBoxChild visible canFocus={false}> + <button + className="result" + cursor="pointer" + onClicked={() => { + execAsync([ + "bash", + "-c", + `dbus-send --session --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:"file://${path}" string:"" || xdg-open "${path}"`, + ]).catch(console.error); + close(); + }} + > + <box> + <icon + className="icon" + gicon={ + Gio.File.new_for_path(path) + .query_info(Gio.FILE_ATTRIBUTE_STANDARD_ICON, Gio.FileQueryInfoFlags.NONE, null) + .get_icon()! + } + /> + <label truncate label={path.replace(HOME, "~")} /> + </box> + </button> + </Gtk.FlowBoxChild> +); + @register() class Apps extends Widget.Box implements ModeContent { #content: FlowBox; @@ -72,7 +105,8 @@ class Apps extends Widget.Box implements ModeContent { updateContent(search: string): void { this.#content.foreach(c => c.destroy()); - AppsService.fuzzy_query(search).forEach(app => this.#content.add(<AppResult app={app} />)); + for (const app of limitLength(AppsService.fuzzy_query(search), config.apps)) + this.#content.add(<AppResult app={app} />); } handleActivate(): void { @@ -83,16 +117,33 @@ class Apps extends Widget.Box implements ModeContent { @register() class Files extends Widget.Box implements ModeContent { + #content: FlowBox; + constructor() { super({ name: "files", className: "files" }); + + this.#content = (<FlowBox homogeneous valign={Gtk.Align.START} maxChildrenPerLine={2} />) as FlowBox; + + this.add( + <scrollable expand hscroll={Gtk.PolicyType.NEVER}> + {this.#content} + </scrollable> + ); } updateContent(search: string): void { - throw new Error("Method not implemented."); + 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(<FileResult path={path} />); + }) + .catch(() => {}); // Ignore errors } - handleActivate(search: string): void { - throw new Error("Method not implemented."); + handleActivate(): void { + this.#content.get_child_at_index(0)?.get_child()?.grab_focus(); + this.#content.get_child_at_index(0)?.get_child()?.activate(); } } |