nixos-configs/devices/wim/config/ags/js/applauncher/main.js

146 lines
3.8 KiB
JavaScript

import App from 'resource:///com/github/Aylur/ags/app.js';
import Applications from 'resource:///com/github/Aylur/ags/service/applications.js';
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
// TODO: find cleaner way to import this
import { Fzf } from '../../node_modules/fzf/dist/fzf.es.js';
import { Box, Entry, Icon, Label, ListBox, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
import PopupWindow from '../misc/popup.js';
import AppItem from './app-item.js';
const Applauncher = ({ window_name = 'applauncher' } = {}) => {
let fzfResults;
const list = ListBox();
const setSort = (text) => {
const fzf = new Fzf(Applications.list, {
selector: (app) => app.name,
tiebreakers: [(a, b) => b._frequency -
a._frequency],
});
fzfResults = fzf.find(text);
list.set_sort_func((a, b) => {
const row1 = a.get_children()[0]?.app.name;
const row2 = b.get_children()[0]?.app.name;
if (!row1 || !row2) {
return 0;
}
return fzfResults.indexOf(row1) -
fzfResults.indexOf(row1) || 0;
});
};
const makeNewChildren = () => {
list.get_children().forEach((ch) => {
ch.destroy();
});
const children = Applications.query('')
.flatMap((app) => AppItem(app));
children.forEach((ch) => {
list.add(ch);
});
list.show_all();
};
makeNewChildren();
const placeholder = Label({
label: " Couldn't find a match",
className: 'placeholder',
});
const entry = Entry({
// Set some text so on-change works the first time
text: '-',
hexpand: true,
on_accept: ({ text }) => {
const appList = Applications.query(text || '');
if (appList[0]) {
App.closeWindow(window_name);
Hyprland.sendMessage(`dispatch exec sh -c
${appList[0].executable}`);
++appList[0].frequency;
}
},
on_change: ({ text }) => {
setSort(text);
let visibleApps = 0;
list.get_children().forEach((row) => {
row.changed();
const item = row.get_children()[0];
if (item?.app) {
const isMatching = fzfResults.find((r) => {
return r.item.name === item.app.name;
});
row.visible = isMatching;
if (isMatching) {
++visibleApps;
}
}
});
placeholder.visible = visibleApps <= 0;
},
});
return Box({
className: 'applauncher',
vertical: true,
setup: (self) => {
self.hook(App, (_, name, visible) => {
if (name !== window_name) {
return;
}
entry.text = '';
if (visible) {
entry.grab_focus();
}
else {
makeNewChildren();
}
});
},
children: [
Box({
className: 'header',
children: [
Icon('preferences-system-search-symbolic'),
entry,
],
}),
Scrollable({
hscroll: 'never',
vscroll: 'automatic',
child: Box({
vertical: true,
children: [list, placeholder],
}),
}),
],
});
};
export default () => PopupWindow({
name: 'applauncher',
focusable: true,
child: Applauncher(),
});