feat(ags): add app launcher from aylur's dots

This commit is contained in:
matt1432 2023-09-29 03:36:48 -04:00
parent d42221de0b
commit e9cc337a9c
6 changed files with 319 additions and 3 deletions

View file

@ -6,6 +6,7 @@ import { NotificationsPopupList } from './js/notifications/popup.js'
import { Calendar } from './js/date.js';
import { QuickSettings } from './js/quick-settings/main.js';
import Overview from './js/overview/main.js';
import AppLauncher from './js/applauncher/main.js';
import { Closer, closeAll } from './js/misc/closer.js';
ags.App.closeAll = () => closeAll();
@ -27,6 +28,7 @@ export default {
'calendar': 500,
'powermenu': 500,
'overview': 500,
'applauncher': 500,
},
windows: [
Powermenu,
@ -37,5 +39,6 @@ export default {
Calendar,
QuickSettings,
Overview,
AppLauncher,
],
};

View file

@ -0,0 +1,126 @@
const { App } = ags;
const { Applications } = ags.Service;
const { Label, Box, Icon, Button, Scrollable, Entry, Window } = ags.Widget;
import { Separator } from '../misc/separator.js';
import { PopUp } from '../misc/popup.js';
const icons = {
apps: {
apps: 'view-app-grid-symbolic',
search: 'preferences-system-search-symbolic',
}
};
const AppItem = (app, window) => {
if (app.app.get_string('Icon') == 'Nextcloud')
return;
return Button({
className: 'app',
connections: [['clicked', () => {
App.closeWindow(window);
app.launch();
}]],
child: Box({
children: [
Icon({
icon: app.app.get_string('Icon'),
size: 42,
}),
Box({
vertical: true,
children: [
Label({
className: 'title',
label: app.name,
xalign: 0,
valign: 'center',
ellipsize: 3,
}),
Label({
className: 'description',
label: app.description || '',
wrap: true,
xalign: 0,
justification: 'left',
valign: 'center',
}),
],
}),
],
}),
});
};
const Applauncher = ({ windowName = 'applauncher' } = {}) => {
const list = Box({ vertical: true });
const placeholder = Label({
label: " Couldn't find a match",
className: 'placeholder',
});
const entry = Entry({
hexpand: true,
placeholderText: 'Search',
onAccept: ({ text }) => {
const list = Applications.query(text);
if (list[0]) {
App.toggleWindow(windowName);
list[0].launch();
}
},
onChange: ({ text }) => {
list.children = Applications.query(text).map(app => [
Separator(4),
AppItem(app, windowName),
]).flat();
list.add(Separator(4));
list.show_all();
placeholder.visible = list.children.length === 1;
},
});
return Box({
className: 'applauncher',
properties: [['list', list]],
vertical: true,
children: [
Box({
className: 'header',
children: [
Icon(icons.apps.search),
entry,
],
}),
Scrollable({
hscroll: 'never',
child: Box({
vertical: true,
children: [list, placeholder],
}),
}),
],
connections: [[App, (_b, name, visible) => {
if (name !== windowName)
return;
entry.set_text('-'); // force onChange
entry.set_text('');
if (visible)
entry.grab_focus();
}]],
});
};
// TODO: make focusable a bit less focusable
export default Window({
name: 'applauncher',
popup: true,
focusable: true,
layer: 'overlay',
child: PopUp({
name: 'applauncher',
child: Applauncher(),
}),
});

View file

@ -13,3 +13,4 @@
@import "./widgets/quick-settings.scss";
@import "./widgets/player.scss";
@import "./widgets/overview.scss";
@import "./widgets/applauncher.scss";

View file

@ -0,0 +1,113 @@
.applauncher {
all: unset;
box-shadow: 0 0 4.5px 0 rgba(0, 0, 0, 0.6);
margin: 9px;
border: 2px solid $contrastbg;
border-radius: 25px;
background-color: $bg;
color: #f8f8f2;
padding: 16.2px;
* {
font-size: 16px;
}
.header {
margin: 16.2px;
margin-bottom: 0;
image, entry {
all: unset;
border-radius: 9px;
color: #f8f8f2;
background-color: rgba(#44475a, 0.6);
border: 1px solid #44475a;
padding: 4.5px;
}
image {
margin-right: 9px;
-gtk-icon-transform: scale(0.8);
font-size: 25.6px;
}
}
scrolledwindow {
padding: 16.2px;
min-width: 700px;
min-height: 450px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.placeholder {
margin-top: 9px;
color: #f8f8f2;
font-size: 1.2em;
}
.app {
all: unset;
transition: 200ms;
padding: 9px;
&:active {
background-color: rgba($contrastbg, 0.5);
border-radius: 9px;
box-shadow: inset 0 0 0 3px rgba(238, 238, 238, 0.03);
.title {
color: #f8f8f2;
}
}
&:hover, &:focus {
.title {
color: $contrastbg;
}
image {
-gtk-icon-shadow: 2px 2px $contrastbg;
}
}
label {
transition: 200ms;
&.title {
color: #f8f8f2;
}
&.description {
color: rgba(238, 238, 238, 0.7);
}
}
image {
transition: 200ms;
margin-right: 9px;
}
}
}

View file

@ -695,3 +695,76 @@ calendar:indeterminate {
border: 2px solid #333333; }
.overview .special .workspace .window.active {
border: 2px solid purple; }
.applauncher {
all: unset;
box-shadow: 0 0 4.5px 0 rgba(0, 0, 0, 0.6);
margin: 9px;
border: 2px solid rgba(189, 147, 249, 0.8);
border-radius: 25px;
background-color: rgba(40, 42, 54, 0.8);
color: #f8f8f2;
padding: 16.2px; }
.applauncher * {
font-size: 16px; }
.applauncher .header {
margin: 16.2px;
margin-bottom: 0; }
.applauncher .header image, .applauncher .header entry {
all: unset;
border-radius: 9px;
color: #f8f8f2;
background-color: rgba(68, 71, 90, 0.6);
border: 1px solid #44475a;
padding: 4.5px; }
.applauncher .header image {
margin-right: 9px;
-gtk-icon-transform: scale(0.8);
font-size: 25.6px; }
.applauncher scrolledwindow {
padding: 16.2px;
min-width: 700px;
min-height: 450px; }
.applauncher scrolledwindow scrollbar, .applauncher scrolledwindow scrollbar * {
all: unset; }
.applauncher scrolledwindow scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3); }
.applauncher scrolledwindow scrollbar.vertical:hover {
background-color: rgba(23, 23, 23, 0.7); }
.applauncher scrolledwindow scrollbar.vertical:hover slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em; }
.applauncher scrolledwindow scrollbar.vertical slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms; }
.applauncher .placeholder {
margin-top: 9px;
color: #f8f8f2;
font-size: 1.2em; }
.applauncher .app {
all: unset;
transition: 200ms;
padding: 9px; }
.applauncher .app:active {
background-color: rgba(189, 147, 249, 0.5);
border-radius: 9px;
box-shadow: inset 0 0 0 3px rgba(238, 238, 238, 0.03); }
.applauncher .app:active .title {
color: #f8f8f2; }
.applauncher .app:hover .title, .applauncher .app:focus .title {
color: rgba(189, 147, 249, 0.8); }
.applauncher .app:hover image, .applauncher .app:focus image {
-gtk-icon-shadow: 2px 2px rgba(189, 147, 249, 0.8); }
.applauncher .app label {
transition: 200ms; }
.applauncher .app label.title {
color: #f8f8f2; }
.applauncher .app label.description {
color: rgba(238, 238, 238, 0.7); }
.applauncher .app image {
transition: 200ms;
margin-right: 9px; }

View file

@ -24,7 +24,7 @@ exec-once = XDG_DATA_DIRS=$kora ags
exec-once = gnome-keyring-daemon --start --components=secrets
exec-once = squeekboard
exec-once = wofi --show drun
exec-once = bash -c "sleep 1; ags -t applauncher"
exec-once = hyprpaper
exec-once = wl-paste --watch cliphist store
@ -172,8 +172,8 @@ bind = $mainMod, C, killactive,
bind = $mainMod, L, exec, $LOCK_PATH/lock.sh
bind = $mainMod SHIFT, E, exec, ags run-js 'ags.App.openWindow("powermenu")'
bindn =, Escape, exec, ags run-js 'ags.App.closeAll()'
bind = $mainMod SHIFT, SPACE, togglefloating,
bind = $mainMod, D, exec, wofi --show drun
bind = $mainMod SHIFT, SPACE, togglefloating,
bind = $mainMod, D, exec, ags -t applauncher
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle