From ba4a879cc7c44187c429cea629e05b106ca75802 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Fri, 24 Jan 2025 21:21:26 +1100 Subject: launcher: use scrollable --- config.ts | 44 +++++++++++------ src/modules/launcher.tsx | 123 ++++++++++++++++++++++++++++++++--------------- src/services/math.ts | 3 +- 3 files changed, 116 insertions(+), 54 deletions(-) diff --git a/config.ts b/config.ts index 3ea635a..05f9ff7 100644 --- a/config.ts +++ b/config.ts @@ -7,21 +7,33 @@ export const bar = { }; export const launcher = { - maxResults: 15, - fdOpts: ["-a", "-t", "f"], - pins: [ - ["firefox", "waterfox", "google-chrome", "chromium", "brave-browser", "vivaldi-stable", "vivaldi-snapshot"], - ["foot", "alacritty", "kitty", "wezterm"], - ["thunar", "nemo", "nautilus"], - ["codium", "code", "clion", "intellij-idea-ultimate-edition"], - ["spotify-adblock", "spotify", "audacious", "elisa"], - ], + maxResults: 15, // Max shown results at one time (i.e. max height of the launcher) + apps: { + maxResults: 30, // Actual max results, -1 for infinite + pins: [ + ["firefox", "waterfox", "google-chrome", "chromium", "brave-browser", "vivaldi-stable", "vivaldi-snapshot"], + ["foot", "alacritty", "kitty", "wezterm"], + ["thunar", "nemo", "nautilus"], + ["codium", "code", "clion", "intellij-idea-ultimate-edition"], + ["spotify-adblock", "spotify", "audacious", "elisa"], + ], + }, + files: { + maxResults: 40, // Actual max results, -1 for infinite + fdOpts: ["-a", "-t", "f"], // Options to pass to `fd` + }, + math: { + maxResults: 40, // Actual max results, -1 for infinite + }, windows: { - // Weights for fuzzysort - title: 1, - class: 1, - initialTitle: 0.5, - initialClass: 0.5, + maxResults: -1, // Actual max results, -1 for infinite + weights: { + // Weights for fuzzy sort + title: 1, + class: 1, + initialTitle: 0.5, + initialClass: 0.5, + }, }, }; @@ -55,6 +67,10 @@ export const osds = { }; // Services +export const math = { + maxHistory: 100, +}; + export const updates = { interval: 900000, }; diff --git a/src/modules/launcher.tsx b/src/modules/launcher.tsx index b588e3a..115137d 100644 --- a/src/modules/launcher.tsx +++ b/src/modules/launcher.tsx @@ -47,6 +47,9 @@ const getEmptyTextFromMode = (mode: Mode) => { } }; +const limitLength = (arr: T[], cfg: { maxResults: number }) => + cfg.maxResults > 0 && arr.length > cfg.maxResults ? arr.slice(0, cfg.maxResults) : arr; + const close = (self: JSX.Element) => { const toplevel = self.get_toplevel(); if (toplevel instanceof Widget.Window) toplevel.hide(); @@ -114,7 +117,7 @@ const PinnedApp = (names: string[]) => { return widget; }; -const PinnedApps = () => {config.pins.map(PinnedApp)}; +const PinnedApps = () => {config.apps.pins.map(PinnedApp)}; const SearchEntry = ({ entry }: { entry: Widget.Entry }) => ( void; onSecondaryClick?: (self: Widget.Button) => void; + onMiddleClick?: (self: Widget.Button) => void; onDestroy?: () => void; }) => ( @@ -388,18 +398,43 @@ const WindowResult = ({ client, reload }: { client: Client; reload: () => void } }) ); + const classOrTitle = (prop: "Class" | "Title", header = true) => { + const lower = prop.toLowerCase() as "class" | "title"; + return ( + (header ? `${prop}: ` : "") + + (client[lower] || (client[`initial${prop}`] ? `${client[`initial${prop}`]} (initial)` : `No ${lower}`)) + ); + }; + const workspace = (header = false) => + (header ? "Workspace: " : "") + `${client.workspace.name} (${client.workspace.id})`; + const prop = (prop: keyof typeof client, header?: string) => + `${header ?? prop.slice(0, 1).toUpperCase() + prop.slice(1)}: ${client[prop]}`; + const result = ( { close(self); astalClient?.focus(); }} onSecondaryClick={() => menu.popup_at_pointer(null)} + onMiddleClick={() => { + astalClient?.kill(); + const id = hyprland.connect("client-removed", () => { + hyprland.disconnect(id); + reload(); + }); + }} onDestroy={() => menu.destroy()} /> ); @@ -409,24 +444,10 @@ const WindowResult = ({ client, reload }: { client: Client; reload: () => void } const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) => { const empty = Variable(true); - return ( - (t ? "empty" : "list"))} - > - - + const scrollable = ( + { const subcommands: Record = { apps: { @@ -470,11 +491,16 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) }; const subcommandList = Object.keys(subcommands); - const updateEmpty = () => empty.set(self.get_children().length === 0); + const afterUpdate = () => { + empty.set(self.get_children().length === 0); + + const children = limitLength(self.get_children(), config); + const height = children.reduce((a, b) => a + b.get_preferred_height()[1], 0); + scrollable.css = `min-height: ${height}px;`; + }; const appSearch = () => { - const apps = Apps.fuzzy_query(entry.text); - if (apps.length > config.maxResults) apps.length = config.maxResults; + const apps = limitLength(Apps.fuzzy_query(entry.text), config.apps); for (const app of apps) self.add(); }; @@ -485,23 +511,23 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) ); self.add(); } - for (const item of MathService.get_default().history) + for (const item of limitLength(MathService.get_default().history, config.math)) self.add(); }; const fileSearch = () => - execAsync(["fd", ...config.fdOpts, entry.text, HOME]) + execAsync(["fd", ...config.files.fdOpts, entry.text, HOME]) .then(out => { const paths = out.split("\n").filter(path => path); - if (paths.length > config.maxResults) paths.length = config.maxResults; self.foreach(ch => ch.destroy()); - for (const path of paths) self.add(); + for (const path of limitLength(paths, config.files)) + self.add(); }) .catch(e => { // Ignore execAsync error if (!(e instanceof Gio.IOErrorEnum || e instanceof GLib.SpawnError)) console.error(e); }) - .finally(updateEmpty); + .finally(afterUpdate); const listWindows = () => { const hyprland = AstalHyprland.get_default(); @@ -512,13 +538,13 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) if (entry.text) { const clients = fuzzysort.go(entry.text, unsortedClients, { all: true, - limit: config.maxResults, + limit: config.windows.maxResults, keys: ["title", "class", "initialTitle", "initialClass"], scoreFn: r => - r[0].score * config.windows.title + - r[1].score * config.windows.class + - r[2].score * config.windows.initialTitle + - r[3].score * config.windows.initialClass, + r[0].score * config.windows.weights.title + + r[1].score * config.windows.weights.class + + r[2].score * config.windows.weights.initialTitle + + r[3].score * config.windows.weights.initialClass, }); self.foreach(ch => ch.destroy()); for (const { obj } of clients) @@ -526,13 +552,13 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) } else { const clients = unsortedClients.sort((a, b) => a.focusHistoryID - b.focusHistoryID); self.foreach(ch => ch.destroy()); - for (const client of clients) + for (const client of limitLength(clients, config.windows)) self.add(); } } catch (e) { console.error(e); } finally { - updateEmpty(); + afterUpdate(); } }); }; @@ -572,10 +598,29 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable }) else if (mode.get() === "files") fileSearch(); else if (mode.get() === "windows") listWindows(); - if (ignoreFileAsync) updateEmpty(); + if (ignoreFileAsync) afterUpdate(); }); }} /> + + ) as Widget.Scrollable; + + return ( + (t ? "empty" : "list"))} + > + + + {scrollable} ); }; diff --git a/src/services/math.ts b/src/services/math.ts index c66798c..14e90e0 100644 --- a/src/services/math.ts +++ b/src/services/math.ts @@ -1,5 +1,6 @@ import { GLib, GObject, property, readFile, register, writeFileAsync } from "astal"; import { derivative, evaluate, rationalize, simplify } from "mathjs/number"; +import { math as config } from "../../config"; export interface HistoryItem { equation: string; @@ -16,7 +17,7 @@ export default class Math extends GObject.Object { return this.instance; } - readonly #maxHistory = 20; + readonly #maxHistory = config.maxHistory; readonly #path = `${CACHE}/math-history.json`; readonly #history: HistoryItem[] = []; -- cgit v1.2.3-freya