feat(ags launcher): add fzf search
This commit is contained in:
parent
bfbb60d37c
commit
f972815389
5 changed files with 68 additions and 23 deletions
|
@ -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;
|
||||||
|
|
|
@ -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({
|
||||||
|
children: [
|
||||||
Separator(ICON_SEPARATION, {
|
Separator(ICON_SEPARATION, {
|
||||||
binds: [['visible', item, 'visible']],
|
binds: [['visible', item, 'visible']],
|
||||||
}),
|
}),
|
||||||
item,
|
item,
|
||||||
];
|
],
|
||||||
}),
|
|
||||||
Separator(ICON_SEPARATION),
|
|
||||||
];
|
|
||||||
|
|
||||||
const list = Box({
|
|
||||||
vertical: true,
|
|
||||||
children: children(),
|
|
||||||
});
|
});
|
||||||
|
}),
|
||||||
|
Separator(ICON_SEPARATION)]
|
||||||
|
.forEach(((ch) => {
|
||||||
|
list.add(ch);
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
makeNewChildren();
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
}]],
|
}]],
|
||||||
});
|
});
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue