feat: Shortcuts widget
This commit is contained in:
@ -69,7 +69,7 @@ export default async function Clipboard(_monitor_id: number) {
|
||||
};
|
||||
|
||||
const setup = (self: Gtk.Window) => self.connect('notify::visible', async () => {
|
||||
await getClipboardHistory(history)
|
||||
if (self.is_visible()) await getClipboardHistory(history)
|
||||
})
|
||||
|
||||
return <window
|
||||
|
82
ags/widget/launcher/shortcuts.tsx
Normal file
82
ags/widget/launcher/shortcuts.tsx
Normal file
@ -0,0 +1,82 @@
|
||||
import { generateModmaskMap, hideWindow, limit, skip } from "@lib/utils";
|
||||
|
||||
import { App, Astal, Gtk } from "astal/gtk4";
|
||||
import { Variable, bind } from "astal";
|
||||
|
||||
import Hyprland from "gi://AstalHyprland";
|
||||
|
||||
const modmasks = generateModmaskMap();
|
||||
|
||||
// Incomplete Astal types?
|
||||
type Bind = Hyprland.Bind & { description: string };
|
||||
|
||||
function ShortcutEntry({ entry }: { entry: Bind }) {
|
||||
return <box cssClasses={["entry"]} spacing={4}>
|
||||
{entry.modmask !== 0 && <label
|
||||
cssClasses={["kbd"]}
|
||||
label={modmasks[entry.modmask]?.toString()} />
|
||||
}
|
||||
<label cssClasses={["kbd"]} label={entry.key.toString()} />
|
||||
<label label={entry.description} />
|
||||
</box>
|
||||
}
|
||||
|
||||
export default async function Shortcuts(_monitor_id: number) {
|
||||
const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor;
|
||||
const hypr = Hyprland.get_default();
|
||||
|
||||
const shortcuts: Variable<Bind[]> = Variable([]);
|
||||
const toSkip = Variable(0);
|
||||
|
||||
const list = Variable.derive([
|
||||
bind(shortcuts),
|
||||
bind(toSkip)
|
||||
], (page, count) => limit(
|
||||
skip(page, count),
|
||||
10
|
||||
));
|
||||
|
||||
const isEmpty = bind(list).as(list => list.length === 0);
|
||||
const onScroll = (dy: number) => {
|
||||
const value = toSkip.get();
|
||||
|
||||
if (dy < 0) {
|
||||
if ((value - 10) < 0) return;
|
||||
toSkip.set(value - 10)
|
||||
} else {
|
||||
if ((value + 10) > shortcuts.get().length) return;
|
||||
toSkip.set(value + 10)
|
||||
}
|
||||
};
|
||||
|
||||
const setup = (self: Gtk.Window) => self.connect('notify::visible', async () => {
|
||||
if (self.is_visible()) shortcuts.set(hypr.get_binds() as Bind[])
|
||||
})
|
||||
|
||||
return <window
|
||||
visible={false}
|
||||
monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
|
||||
name={"shortcuts"}
|
||||
cssClasses={["shortcuts"]}
|
||||
keymode={Astal.Keymode.EXCLUSIVE}
|
||||
anchor={TOP | BOTTOM | LEFT | RIGHT}
|
||||
onKeyPressed={hideWindow}
|
||||
application={App}
|
||||
setup={setup}>
|
||||
<box hexpand={false} cssClasses={["shortcuts"]} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
|
||||
<box spacing={6} vertical onScroll={(_, __, dy) => onScroll(dy)}>
|
||||
{bind(list).as(list => list.map(entry => (
|
||||
<ShortcutEntry entry={entry} />
|
||||
)))}
|
||||
</box>
|
||||
<box
|
||||
halign={Gtk.Align.CENTER}
|
||||
cssClasses={["not-found"]}
|
||||
vertical
|
||||
visible={isEmpty}>
|
||||
<image iconName="system-search-symbolic" />
|
||||
<label label="No match found" />
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
}
|
Reference in New Issue
Block a user