feat(ags launcher): add fzf search

This commit is contained in:
matt1432 2023-12-07 01:18:47 -05:00
parent bfbb60d37c
commit f972815389
5 changed files with 68 additions and 23 deletions

View file

@ -44,13 +44,14 @@ export default (app) => {
return Button({ return Button({
hexpand: true,
class_name: 'app', class_name: 'app',
setup: (self) => { setup: (self) => {
self.app = app; self.app = app;
}, },
on_clicked: () => { onPrimaryClickRelease: () => {
App.closeWindow('applauncher'); App.closeWindow('applauncher');
Hyprland.sendMessage(`dispatch exec sh -c ${app.executable}`); Hyprland.sendMessage(`dispatch exec sh -c ${app.executable}`);
++app.frequency; ++app.frequency;

View file

@ -1,8 +1,10 @@
import App from 'resource:///com/github/Aylur/ags/app.js'; import App from 'resource:///com/github/Aylur/ags/app.js';
import Applications from 'resource:///com/github/Aylur/ags/service/applications.js'; import Applications from 'resource:///com/github/Aylur/ags/service/applications.js';
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.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, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js'; import { Box, Entry, Icon, Label, ListBox, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
import PopupWindow from '../misc/popup.js'; import PopupWindow from '../misc/popup.js';
import Separator from '../misc/separator.js'; import Separator from '../misc/separator.js';
@ -12,24 +14,53 @@ import AppItem from './app-item.js';
const Applauncher = ({ window_name = 'applauncher' } = {}) => { const Applauncher = ({ window_name = 'applauncher' } = {}) => {
const ICON_SEPARATION = 4; const ICON_SEPARATION = 4;
const children = () => [ let fzfResults;
...Applications.query('').flatMap((app) => { 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].children[1]?.app.name;
const row2 = b.get_children()[0].children[1]?.app.name;
if (!row1 || !row2) {
return 0;
}
return fzfResults.indexOf(row1) -
fzfResults.indexOf(row1) || 0;
});
};
const makeNewChildren = () => {
list.get_children().forEach((ch) => {
ch.destroy();
});
[...Applications.query('').flatMap((app) => {
const item = AppItem(app); const item = AppItem(app);
return [ return Box({
Separator(ICON_SEPARATION, { children: [
binds: [['visible', item, 'visible']], Separator(ICON_SEPARATION, {
}), binds: [['visible', item, 'visible']],
item, }),
]; item,
],
});
}), }),
Separator(ICON_SEPARATION), Separator(ICON_SEPARATION)]
]; .forEach(((ch) => {
list.add(ch);
}));
};
const list = Box({ makeNewChildren();
vertical: true,
children: children(),
});
const placeholder = Label({ const placeholder = Label({
label: " Couldn't find a match", label: " Couldn't find a match",
@ -45,7 +76,7 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
const appList = Applications.query(text || ''); const appList = Applications.query(text || '');
if (appList[0]) { if (appList[0]) {
App.toggleWindow(window_name); App.closeWindow(window_name);
Hyprland.sendMessage(`dispatch exec sh -c Hyprland.sendMessage(`dispatch exec sh -c
${appList[0].executable}`); ${appList[0].executable}`);
++appList[0].frequency; ++appList[0].frequency;
@ -53,13 +84,22 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
}, },
on_change: ({ text }) => { on_change: ({ text }) => {
setSort(text);
let visibleApps = 0; let visibleApps = 0;
list.children.forEach((item) => { list.get_children().forEach((row) => {
if (item.app) { row.changed();
item.visible = item.app.match(text);
if (item.app.match(text)) { const item = row.get_children()[0].children[1];
if (item?.app) {
const isMatching = fzfResults.find((r) => {
return r.item.name === item.app.name;
});
row.visible = isMatching;
if (isMatching) {
++visibleApps; ++visibleApps;
} }
} }
@ -101,7 +141,7 @@ const Applauncher = ({ window_name = 'applauncher' } = {}) => {
entry.grab_focus(); entry.grab_focus();
} }
else { else {
list.children = children(); makeNewChildren();
} }
}]], }]],
}); });

View file

@ -8,6 +8,7 @@
"@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/eslint-plugin": "^6.9.1",
"@typescript-eslint/parser": "^6.9.1", "@typescript-eslint/parser": "^6.9.1",
"eslint": "^8.52.0", "eslint": "^8.52.0",
"fzf": "^0.5.2",
"stylelint-config-standard-scss": "^11.0.0" "stylelint-config-standard-scss": "^11.0.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -10,6 +10,10 @@
font-size: 16px; font-size: 16px;
} }
list, row {
all: unset;
}
.header { .header {
margin: 16.2px; margin: 16.2px;
margin-bottom: 0; margin-bottom: 0;

View file

@ -38,7 +38,6 @@ in {
pavucontrol # TODO: replace with ags widget pavucontrol # TODO: replace with ags widget
]) ])
++ (optionals isTouchscreen (with pkgs; [ ++ (optionals isTouchscreen (with pkgs; [
# touchscreen
lisgd lisgd
squeekboard squeekboard
ydotool ydotool