diff --git a/devices/wim/config/ags/js/applauncher/app-item.js b/devices/wim/config/ags/js/applauncher/app-item.js new file mode 100644 index 0000000..f8ea26d --- /dev/null +++ b/devices/wim/config/ags/js/applauncher/app-item.js @@ -0,0 +1,51 @@ +import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; +import App from 'resource:///com/github/Aylur/ags/app.js'; +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import { lookUpIcon } from 'resource:///com/github/Aylur/ags/utils.js'; + +import Separator from '../misc/separator.js'; + + +export default app => { + const title = Widget.Label({ + class_name: 'title', + label: app.name, + xalign: 0, + vpack: 'center', + truncate: 'end', + }); + + const description = Widget.Label({ + class_name: 'description', + label: app.description || '', + wrap: true, + xalign: 0, + justification: 'left', + vpack: 'center', + }); + + const icon = Widget.Icon({ + icon: lookUpIcon(app.icon_name) ? app.icon_name : + app.app.get_string('Icon') !== 'nix-snowflake' ? app.app.get_string('Icon') : '', + size: 42, + }); + + const textBox = Widget.Box({ + vertical: true, + vpack: 'center', + children: [title, description], + }); + + return Widget.Button({ + class_name: 'app', + setup: self => self.app = app, + on_clicked: () => { + App.closeWindow('applauncher'); + Hyprland.sendMessage(`dispatch exec sh -c ${app.executable}`); + ++app.frequency; + }, + child: Widget.Box({ + children: [icon, Separator(16), textBox], + }), + }); +}; diff --git a/devices/wim/config/ags/js/applauncher/main.js b/devices/wim/config/ags/js/applauncher/main.js index f9634ec..b79df86 100644 --- a/devices/wim/config/ags/js/applauncher/main.js +++ b/devices/wim/config/ags/js/applauncher/main.js @@ -2,102 +2,78 @@ 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'; -import { Label, Box, Icon, Button, Scrollable, Entry } from 'resource:///com/github/Aylur/ags/widget.js'; +import { Box, Entry, Icon, Label, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js'; -import Separator from '../misc/separator.js'; import PopupWindow from '../misc/popup.js'; - -const icons = { - apps: { - apps: 'view-app-grid-symbolic', - search: 'preferences-system-search-symbolic', - }, -}; +import Separator from '../misc/separator.js'; +import AppItem from './app-item.js'; -const AppItem = (app, window) => { - if (app.app.get_string('Icon') == 'Nextcloud') - return; - - return Button({ - className: 'app', - connections: [['clicked', () => { - App.closeWindow(window); - Hyprland.sendMessage(`dispatch exec sh -c ${app.executable}`); - // TODO: focus on new client. Is this only needed after launch? - ++app.frequency; - }]], - child: Box({ - children: [ - Icon({ - icon: app.app.get_string('Icon'), - size: 42, +const Applauncher = ({ window_name = 'applauncher' } = {}) => { + const children = () => [ + ...Applications.query('').flatMap(app => { + const item = AppItem(app); + return [ + Separator(4, { + binds: [['visible', item, 'visible']], }), - Box({ - vertical: true, - children: [ - Label({ - className: 'title', - label: app.name, - xalign: 0, - vpack: 'center', - ellipsize: 3, - }), - Label({ - className: 'description', - label: app.description || '', - wrap: true, - xalign: 0, - justification: 'left', - vpack: 'center', - }), - ], - }), - ], + item, + ]; }), - }); -}; + Separator(4), + ]; -const Applauncher = ({ windowName = 'applauncher' } = {}) => { - const list = Box({ vertical: true }); - const placeholder = Label({ - label: " Couldn't find a match", - className: 'placeholder', + const list = Box({ + vertical: true, + children: children(), }); + const entry = Entry({ hexpand: true, - placeholderText: 'Search', - onAccept: ({ text }) => { - const list = Applications.query(text); + placeholder_text: 'Search', + + // set some text so on-change works the first time + text: '-', + on_accept: ({ text }) => { + const list = Applications.query(text || ''); if (list[0]) { - App.toggleWindow(windowName); - list[0].launch(); + App.toggleWindow(window_name); + Hyprland.sendMessage(`dispatch exec sh -c ${list[0]}`); + ++list[0].frequency; } }, - onChange: ({ text }) => { - list.children = Applications.query(text).map(app => [ - Separator(4), - AppItem(app, windowName), - ]).flat(); - list.add(Separator(4)); - list.show_all(); + on_change: ({ text }) => { + let visibleApps = 0; + list.children.map(item => { + if (item.app) { + item.visible = item.app.match(text); - placeholder.visible = list.children.length === 1; + if (item.app.match(text)) + ++visibleApps; + } + }); + placeholder.visible = visibleApps <= 0; }, }); + const placeholder = Label({ + label: " Couldn't find a match", + className: 'placeholder', + }); + + return Box({ className: 'applauncher', - properties: [['list', list]], vertical: true, children: [ Box({ className: 'header', children: [ - Icon(icons.apps.search), + Icon('preferences-system-search-symbolic'), entry, ], }), + Scrollable({ hscroll: 'never', child: Box({ @@ -106,14 +82,15 @@ const Applauncher = ({ windowName = 'applauncher' } = {}) => { }), }), ], - connections: [[App, (_b, name, visible) => { - if (name !== windowName) + connections: [[App, (_, name, visible) => { + if (name !== window_name) return; - entry.set_text('-'); // force onChange - entry.set_text(''); + entry.text = ''; if (visible) entry.grab_focus(); + else + list.children = children(); }]], }); }; diff --git a/devices/wim/config/ags/js/misc/separator.js b/devices/wim/config/ags/js/misc/separator.js index 306f36c..9ff4b14 100644 --- a/devices/wim/config/ags/js/misc/separator.js +++ b/devices/wim/config/ags/js/misc/separator.js @@ -1,15 +1,17 @@ import { Box } from 'resource:///com/github/Aylur/ags/widget.js'; -export default (size, { vertical = false } = {}) => { +export default (size, { vertical = false, ...props } = {}) => { if (vertical) { return Box({ css: `min-height: ${size}px;`, + ...props, }); } else { return Box({ css: `min-width: ${size}px;`, + ...props, }); } }; diff --git a/devices/wim/config/ags/scss/widgets/applauncher.scss b/devices/wim/config/ags/scss/widgets/applauncher.scss index f951f45..71dc133 100644 --- a/devices/wim/config/ags/scss/widgets/applauncher.scss +++ b/devices/wim/config/ags/scss/widgets/applauncher.scss @@ -107,7 +107,8 @@ image { transition: 200ms; - margin-right: 9px; + margin-left: -10px; + margin-bottom: -8px; } } }