feat(agsV2): add powermenu and icon-browser

This commit is contained in:
matt1432 2024-10-21 15:16:27 -04:00
commit 176ab348e9
7 changed files with 332 additions and 33 deletions
nixosModules/ags/v2/widgets

View file

@ -0,0 +1,142 @@
import { Astal, Gtk, Widget } from 'astal/gtk3';
import { idle } from 'astal';
import { Fzf, FzfResultItem } from 'fzf';
import PopupWindow from '../misc/popup-window';
import { centerCursor } from '../../lib';
export default () => {
let Icons: string[] = [];
let fzfResults = [] as FzfResultItem<string>[];
const list = new Gtk.ListBox({
selectionMode: Gtk.SelectionMode.SINGLE,
});
list.connect('row-activated', (_, row) => {
const icon = ((row.get_children()[0] as Widget.Box).get_children()[0] as Widget.Icon).icon;
console.log(icon);
});
const placeholder = (
<revealer>
<label
label=" Couldn't find a match"
className="placeholder"
/>
</revealer>
) as Widget.Revealer;
const on_text_change = (text: string) => {
const fzf = new Fzf(Icons);
fzfResults = fzf.find(text);
list.invalidate_sort();
const visibleIcons = list.get_children().filter((row) => row.visible).length;
placeholder.reveal_child = visibleIcons <= 0;
};
const entry = (
<entry
onChanged={(self) => on_text_change(self.text)}
hexpand
/>
) as Widget.Entry;
list.set_sort_func((a, b) => {
const row1 = ((a.get_children()[0] as Widget.Box).get_children()[0] as Widget.Icon).icon;
const row2 = ((b.get_children()[0] as Widget.Box).get_children()[0] as Widget.Icon).icon;
if (entry.text === '' || entry.text === '-') {
a.set_visible(true);
b.set_visible(true);
return row1.charCodeAt(0) - row2.charCodeAt(0);
}
else {
const s1 = fzfResults.find((r) => r.item === row1)?.score ?? 0;
const s2 = fzfResults.find((r) => r.item === row2)?.score ?? 0;
a.set_visible(s1 !== 0);
b.set_visible(s2 !== 0);
return s2 - s1;
}
});
const refreshIcons = () => idle(() => {
(list.get_children() as Gtk.ListBoxRow[])
.forEach((child) => {
child.destroy();
});
Icons = Gtk.IconTheme.get_default().list_icons(null)
.filter((icon) => icon.endsWith('symbolic'))
.sort();
Icons
.flatMap((icon) => (
<box>
<icon css="font-size: 60px; margin-right: 25px;" icon={icon} />
<label label={icon} />
</box>
))
.forEach((child) => {
list.add(child);
});
list.show_all();
on_text_change('');
});
refreshIcons();
return (
<PopupWindow
name="icon-browser"
keymode={Astal.Keymode.ON_DEMAND}
on_open={() => {
entry.text = '';
centerCursor();
}}
>
<box
vertical
className="icon-browser"
>
<box className="widget icon-search">
<icon icon="preferences-system-search-symbolic" />
{entry}
<button
css="margin-left: 5px;"
onButtonReleaseEvent={refreshIcons}
>
<icon icon="view-refresh-symbolic" css="font-size: 26px;" />
</button>
</box>
<scrollable
className="widget icon-list"
css="min-height: 600px; min-width: 600px;"
hscroll={Gtk.PolicyType.NEVER}
vscroll={Gtk.PolicyType.AUTOMATIC}
>
<box vertical>
{list}
{placeholder}
</box>
</scrollable>
</box>
</PopupWindow>
);
};

View file

@ -0,0 +1,32 @@
.icon-browser {
.icon-search {
icon {
font-size: 20px;
min-width: 40px;
min-height: 40px
}
entry {}
}
.icon-list {
row {
border-radius: 10px;
&:hover, &:selected {
icon {
-gtk-icon-shadow: 2px 2px $accent_color;
}
}
box {
margin: 20px;
font-size: 16px;
}
}
.placeholder {
font-size: 20px;
}
}
}

View file

@ -0,0 +1,43 @@
import { execAsync } from 'astal';
import { Astal } from 'astal/gtk3';
import { hyprMessage } from '../../lib';
import PopupWindow from '../misc/popup-window';
const PowermenuWidget = () => (
<centerbox className="powermenu widget">
<button
className="shutdown button"
onButtonReleaseEvent={() => execAsync(['systemctl', 'poweroff']).catch(print)}
>
<icon icon="system-shutdown-symbolic" />
</button>
<button
className="reboot button"
onButtonReleaseEvent={() => execAsync(['systemctl', 'reboot']).catch(print)}
>
<icon icon="system-restart-symbolic" />
</button>
<button
className="logout button"
onButtonReleaseEvent={() => hyprMessage('dispatch exit').catch(print)}
>
<icon icon="system-log-out-symbolic" />
</button>
</centerbox>
);
export default () => (
<PopupWindow
name="powermenu"
transition="slide bottom"
// To put it at the center of the screen
exclusivity={Astal.Exclusivity.IGNORE}
>
<PowermenuWidget />
</PopupWindow>
);

View file

@ -0,0 +1,29 @@
.powermenu {
font-size: 70px;
padding: 10px;
icon {
min-width: 130px;
min-height: 130px;
}
button {
margin: 5px 10px;
transition: all ease .2s;
&:hover,
&:active {
background-color: lighten($window_bg_color, 3%);
}
}
.shutdown {
color: $red_1;
}
.reboot {
color: $purple_1;
}
.logout {
color: $yellow_1;
}
}