nixos-configs/modules/ags/config/ts/applauncher/main.ts

167 lines
4.4 KiB
TypeScript
Raw Normal View History

import App from 'resource:///com/github/Aylur/ags/app.js';
import Applications from 'resource:///com/github/Aylur/ags/service/applications.js';
2024-01-13 11:15:08 -05:00
// FIXME: find cleaner way to import this
// @ts-expect-error
import { Fzf } from 'file:///home/matt/.nix/modules/ags/config/node_modules/fzf/dist/fzf.es.js';
import { Box, Entry, Icon, Label, ListBox, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
import PopupWindow from '../misc/popup.ts';
import AppItem from './app-item.ts';
2024-01-13 11:15:08 -05:00
// Types
import { Application } from 'types/service/applications.ts';
2024-01-22 10:23:32 -05:00
import { ListBoxRow } from 'types/@girs/gtk-3.0/gtk-3.0.cjs';
import AgsEventBox from 'types/widgets/eventbox';
2023-12-20 03:45:05 -05:00
const Applauncher = (window_name = 'applauncher') => {
2024-01-13 11:15:08 -05:00
let fzfResults: Array<any>;
2024-01-22 10:23:32 -05:00
// @ts-expect-error
const list = ListBox();
2024-01-13 11:15:08 -05:00
const setSort = (text: string) => {
2023-12-07 01:18:47 -05:00
const fzf = new Fzf(Applications.list, {
2024-01-13 11:15:08 -05:00
selector: (app: Application) => {
return app.name + app.executable;
},
2023-12-20 03:45:05 -05:00
tiebreakers: [
2024-01-13 11:15:08 -05:00
(a: Application, b: Application) => b.frequency - a.frequency,
2023-12-20 03:45:05 -05:00
],
2023-12-07 01:18:47 -05:00
});
fzfResults = fzf.find(text);
2023-12-20 17:14:07 -05:00
list.set_sort_func(
2024-01-13 11:15:08 -05:00
(a: ListBoxRow, b: ListBoxRow) => {
2024-01-22 10:23:32 -05:00
const row1 = (a.get_children()[0] as AgsEventBox)
?.attribute.app.name;
const row2 = (b.get_children()[0] as AgsEventBox)
?.attribute.app.name;
2023-12-20 17:14:07 -05:00
if (!row1 || !row2) {
return 0;
}
2023-12-07 01:18:47 -05:00
2023-12-20 17:14:07 -05:00
return fzfResults.indexOf(row1) -
2023-12-07 01:18:47 -05:00
fzfResults.indexOf(row1) || 0;
2023-12-20 17:14:07 -05:00
},
);
2023-12-07 01:18:47 -05:00
};
const makeNewChildren = () => {
2024-01-13 11:15:08 -05:00
const rows = list.get_children() as Array<ListBoxRow>;
2023-12-20 03:45:05 -05:00
rows.forEach((ch) => {
2023-12-07 01:18:47 -05:00
ch.destroy();
});
const children = Applications.query('')
.flatMap((app) => AppItem(app));
children.forEach((ch) => {
list.add(ch);
});
list.show_all();
2023-12-07 01:18:47 -05:00
};
2023-12-07 01:18:47 -05:00
makeNewChildren();
const placeholder = Revealer({
child: Label({
label: " Couldn't find a match",
class_name: '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]) {
2023-12-07 01:18:47 -05:00
App.closeWindow(window_name);
2023-12-21 01:25:59 -05:00
appList[0].launch();
}
},
on_change: ({ text }) => {
if (text === null) {
2023-12-18 18:00:30 -05:00
return;
}
2023-12-07 01:18:47 -05:00
setSort(text);
let visibleApps = 0;
2024-01-13 11:15:08 -05:00
const rows = list.get_children() as Array<ListBoxRow>;
2023-12-20 03:45:05 -05:00
rows.forEach((row) => {
2023-12-07 01:18:47 -05:00
row.changed();
2024-01-22 10:23:32 -05:00
const item = (row.get_children()[0] as AgsEventBox);
2023-12-07 01:18:47 -05:00
2023-12-18 18:00:30 -05:00
if (item?.attribute.app) {
2023-12-20 03:45:05 -05:00
const isMatching = fzfResults.find((r) => {
2023-12-18 18:00:30 -05:00
return r.item.name === item.attribute.app.name;
2023-12-07 01:18:47 -05:00
});
row.visible = isMatching;
2023-12-07 01:18:47 -05:00
if (isMatching) {
++visibleApps;
}
}
});
placeholder.reveal_child = visibleApps <= 0;
},
});
return Box({
2023-12-18 18:00:30 -05:00
class_name: '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({
2023-12-18 18:00:30 -05:00
class_name: '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(),
});