launcher: files mode
This commit is contained in:
parent
5cf36b0058
commit
c314fe43cd
2 changed files with 59 additions and 25 deletions
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue