import { type Binding } from 'lib/utils'; import PopupWindow, { Padding } from 'widget/PopupWindow'; import icons from 'lib/icons'; import options from 'options'; import nix from 'service/nix'; import * as AppLauncher from './AppLauncher'; import * as NixRun from './NixRun'; import * as ShRun from './ShRun'; const { width, margin } = options.launcher; const isnix = nix.available; function Launcher() { const favs = AppLauncher.Favorites(); const applauncher = AppLauncher.Launcher(); const sh = ShRun.ShRun(); const shicon = ShRun.Icon(); const nix = NixRun.NixRun(); const nixload = NixRun.Spinner(); function HelpButton(cmd: string, desc: string | Binding) { return Widget.Box( { vertical: true }, Widget.Separator(), Widget.Button( { class_name: 'help', on_clicked: () => { entry.grab_focus(); entry.text = `:${cmd} `; entry.set_position(-1); }, }, Widget.Box([ Widget.Label({ class_name: 'name', label: `:${cmd}`, }), Widget.Label({ hexpand: true, hpack: 'end', class_name: 'description', label: desc, }), ]), ), ); } const help = Widget.Revealer({ child: Widget.Box( { vertical: true }, HelpButton('sh', 'run a binary'), isnix ? HelpButton( 'nx', options.launcher.nix.pkgs.bind().as(pkg => `run a nix package from ${pkg}`), ) : Widget.Box(), ), }); const entry = Widget.Entry({ hexpand: true, primary_icon_name: icons.ui.search, on_accept: ({ text }) => { if (text?.startsWith(':nx')) nix.run(text.substring(3)); else if (text?.startsWith(':sh')) sh.run(text.substring(3)); else applauncher.launchFirst(); App.toggleWindow('launcher'); entry.text = ''; }, on_change: ({ text }) => { text ||= ''; favs.reveal_child = text === ''; help.reveal_child = text.split(' ').length === 1 && text?.startsWith(':'); if (text?.startsWith(':nx')) nix.filter(text.substring(3)); else nix.filter(''); if (text?.startsWith(':sh')) sh.filter(text.substring(3)); else sh.filter(''); if (!text?.startsWith(':')) applauncher.filter(text); }, }); function focus() { entry.text = ''; entry.set_position(-1); entry.select_region(0, -1); entry.grab_focus(); favs.reveal_child = true; } const layout = Widget.Box({ css: width.bind().as(v => `min-width: ${v}pt;`), class_name: 'launcher', vertical: true, vpack: 'start', setup: self => self.hook(App, (_, win, visible) => { if (win !== 'launcher') return; entry.text = ''; if (visible) focus(); }), children: [ Widget.Box([entry, nixload, shicon]), favs, help, applauncher, //nix, sh, ], }); return Widget.Box( { vertical: true, css: 'padding: 1px' }, Padding('applauncher', { css: margin.bind().as(v => `min-height: ${v}pt;`), vexpand: false, }), layout, ); } export default () => PopupWindow({ name: 'launcher', layout: 'top', child: Launcher(), });