diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-02-28 12:48:42 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-02-28 12:48:42 +1100 |
| commit | 5cf36b005814ee254271648691513d5361096649 (patch) | |
| tree | e8dea19f804586b07f6804b9bf2366d7303fb624 | |
| parent | launcher: made search bar + mode switcher (diff) | |
| download | caelestia-shell-5cf36b005814ee254271648691513d5361096649.tar.gz caelestia-shell-5cf36b005814ee254271648691513d5361096649.tar.bz2 caelestia-shell-5cf36b005814ee254271648691513d5361096649.zip | |
launcher: apps mode
| -rw-r--r-- | scss/launcher.scss | 64 | ||||
| -rw-r--r-- | src/modules/launcher.tsx | 82 | ||||
| -rw-r--r-- | src/utils/widgets.ts | 7 |
3 files changed, 136 insertions, 17 deletions
diff --git a/scss/launcher.scss b/scss/launcher.scss index c2175e7..7535699 100644 --- a/scss/launcher.scss +++ b/scss/launcher.scss @@ -1,3 +1,4 @@ +@use "sass:color"; @use "scheme"; @use "lib"; @use "font"; @@ -14,8 +15,19 @@ } } - .mode-switcher .mode.selected { - border-top: lib.s(2) solid $colour; + .mode-switcher .mode { + &.selected { + border-top: lib.s(2) solid $colour; + } + + &:hover, + &:focus { + color: $colour; + } + + &:active { + color: color.mix($colour, scheme.$base, 80%); + } } } } @@ -32,14 +44,14 @@ min-width: lib.s(700); min-height: lib.s(420); - @include lib.spacing(20, true); - @include launcher(apps, scheme.$sapphire); @include launcher(files, scheme.$peach); @include launcher(math, scheme.$green); @include launcher(windows, scheme.$teal); .search-bar { + margin-bottom: lib.s(15); + @include lib.spacing(10); .mode { @@ -55,23 +67,61 @@ border-top: lib.s(2) solid transparent; padding-top: lib.s(10); + + .icon { + font-size: lib.s(24); + } + + & > box { + @include lib.spacing(10); + } } .result { @include lib.element-decel; - padding: lib.s(5) lib.s(10); + .icon { + font-size: lib.s(32); + } + } - &:hover, - &:focus { + .apps .result { + border-bottom: lib.s(2) solid transparent; + padding-left: lib.s(10); + + & > box { + @include lib.spacing(10); + } + + &:hover { background-color: scheme.$surface0; } + &:focus { + border-bottom: lib.s(2) solid scheme.$red; + color: scheme.$red; + } + &:active { background-color: scheme.$surface1; } } + // .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 356b6d4..b6af58e 100644 --- a/src/modules/launcher.tsx +++ b/src/modules/launcher.tsx @@ -1,6 +1,11 @@ +import { Apps as AppsService } from "@/services/apps"; +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 { Astal, Gtk, Widget } from "astal/gtk3"; +import { App, Astal, Gtk, Widget } from "astal/gtk3"; +import type AstalApps from "gi://AstalApps"; type Mode = "apps" | "files" | "math" | "windows"; @@ -9,25 +14,77 @@ interface ModeContent { handleActivate(search: string): void; } +const close = () => App.get_window("launcher")?.hide(); + +const getModeIcon = (mode: Mode) => { + if (mode === "apps") return "apps"; + if (mode === "files") return "folder"; + if (mode === "math") return "calculate"; + if (mode === "windows") return "select_window"; + return "search"; +}; + +const getPrettyMode = (mode: Mode) => { + if (mode === "apps") return "Apps"; + if (mode === "files") return "Files"; + if (mode === "math") return "Math"; + if (mode === "windows") return "Windows"; + return mode; +}; + +const AppResult = ({ app }: { app: AstalApps.Application }) => ( + <Gtk.FlowBoxChild visible canFocus={false}> + <button + className="result" + cursor="pointer" + onClicked={() => { + launch(app); + close(); + }} + > + <box> + {app.iconName && Astal.Icon.lookup_icon(app.iconName) ? ( + <icon className="icon" icon={app.iconName} /> + ) : ( + <label className="icon" label={getAppCategoryIcon(app)} /> + )} + <label truncate label={app.name} /> + </box> + </button> + </Gtk.FlowBoxChild> +); + @register() class Apps extends Widget.Box implements ModeContent { + #content: FlowBox; + constructor() { - super({ name: "apps" }); + super({ name: "apps", className: "apps" }); + + 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."); + this.#content.foreach(c => c.destroy()); + AppsService.fuzzy_query(search).forEach(app => this.#content.add(<AppResult app={app} />)); } - 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(); } } @register() class Files extends Widget.Box implements ModeContent { constructor() { - super({ name: "files" }); + super({ name: "files", className: "files" }); } updateContent(search: string): void { @@ -42,7 +99,7 @@ class Files extends Widget.Box implements ModeContent { @register() class Math extends Widget.Box implements ModeContent { constructor() { - super({ name: "math" }); + super({ name: "math", className: "math" }); } updateContent(search: string): void { @@ -57,7 +114,7 @@ class Math extends Widget.Box implements ModeContent { @register() class Windows extends Widget.Box implements ModeContent { constructor() { - super({ name: "windows" }); + super({ name: "windows", className: "windows" }); } updateContent(search: string): void { @@ -83,8 +140,12 @@ const ModeSwitcher = ({ mode, modes }: { mode: Variable<Mode>; modes: Mode[] }) className={bind(mode).as(c => `mode ${c === m ? "selected" : ""}`)} cursor="pointer" onClicked={() => mode.set(m)} - label={m} - /> + > + <box halign={Gtk.Align.CENTER}> + <label className="icon" label={getModeIcon(m)} /> + <label label={getPrettyMode(m)} /> + </box> + </button> ))} </box> ); @@ -144,6 +205,7 @@ export default class Launcher extends PopupWindow { this.mode = mode; + content[mode.get()].updateContent(entry.get_text()); this.hook(mode, (_, v: Mode) => { entry.set_text(""); content[v].updateContent(entry.get_text()); diff --git a/src/utils/widgets.ts b/src/utils/widgets.ts index 9802263..7b1eb5c 100644 --- a/src/utils/widgets.ts +++ b/src/utils/widgets.ts @@ -73,3 +73,10 @@ export class Calendar extends astalify(Gtk.Calendar) { super(props as any); } } + +@register() +export class FlowBox extends astalify(Gtk.FlowBox) { + constructor(props: ConstructProps<FlowBox, Gtk.FlowBox.ConstructorProps>) { + super(props as any); + } +} |