Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

quickshell/nuguland/Launcher.qml

Raw
import QtQuick
import Quickshell
import "launch.js" as Launch

Item {
    id: root

    property var launchRecords: []
    property var lastInteraction: ({})

    readonly property var apps: Launch.buildApps(DesktopEntries.applications ? DesktopEntries.applications.values : [])
    readonly property bool appScanDone: true
    readonly property string appScanError: ""

    function stateJson() {
        return JSON.stringify({
            "launchRecords": launchRecords,
            "lastInteraction": lastInteraction,
            "appCount": apps.length,
            "appScanDone": appScanDone,
            "appScanError": appScanError
        });
    }

    function rememberActivation(record, executed) {
        const entry = {
            "kind": "activate",
            "record": record,
            "executed": !!executed
        };
        const rows = launchRecords.slice(Math.max(0, launchRecords.length - 19));
        rows.push(record);
        launchRecords = rows;
        lastInteraction = entry;
        return stateJson();
    }

    function rowFromJson(rowJson) {
        if (typeof rowJson === "string") {
            try {
                return JSON.parse(rowJson);
            } catch (error) {
                return {
                    "id": "invalid",
                    "title": "Invalid launcher row",
                    "provider": "error",
                    "error": String(error)
                };
            }
        }
        return rowJson || ({});
    }

    function sliceForRow(row) {
        return row.terminal ? "work.slice" : "app-graphical.slice";
    }

    function launchRecord(rowJson) {
        const row = rowFromJson(rowJson);
        const title = String(row.title || row.id || "app");
        const id = String(row.id || row.desktopId || title);
        return JSON.stringify({
            "id": id,
            "label": title,
            "kind": "app",
            "provider": "app",
            "desktopId": row.desktopId || "",
            "desktopPath": row.desktopPath || "",
            "argv": row.execArgv || [],
            "workingDirectory": row.workingDirectory || "",
            "environment": {},
            "slice": sliceForRow(row),
            "startupNotify": true,
            "windowMatching": {
                "desktopId": row.desktopId || "",
                "title": title,
                "appId": row.desktopId ? String(row.desktopId).replace(/\.desktop$/, "") : ""
            },
            "osdFeedback": `app:${title}`,
            "route": "desktop-entry",
            "terminal": !!row.terminal
        });
    }

    function execRecord(record) {
        if (!record.argv || record.argv.length === 0)
            return false;

        const selector = record.slice === "work.slice" ? "w" : "a";
        Quickshell.execDetached(["uwsm", "app", "-s", selector, "--"].concat(record.argv));
        return true;
    }

    function activate(rowJson) {
        const record = JSON.parse(launchRecord(rowJson));
        return rememberActivation(record, execRecord(record));
    }

    function activateAction(rowJson, index) {
        const row = rowFromJson(rowJson);
        const action = (row.actions || [])[Number(index) || 0];
        if (!action) {
            lastInteraction = {
                "kind": "activate-missing-action",
                "row": row.id || row.title || "app",
                "index": Number(index) || 0
            };
            return stateJson();
        }

        const record = JSON.parse(launchRecord(row));
        record.id = `${record.id}:${action.id || action.title}`;
        record.label = `${record.label}: ${action.title || action.id}`;
        record.argv = action.execArgv || [];
        record.desktopPath = "";
        record.osdFeedback = `app-action:${record.label}`;
        return rememberActivation(record, execRecord(record));
    }

    function activateFirst(query) {
        const result = JSON.parse(search(query));
        if (!result.results || result.results.length === 0) {
            lastInteraction = {
                "kind": "activate-empty",
                "query": String(query)
            };
            return stateJson();
        }
        return activate(JSON.stringify(result.results[0]));
    }

    function rowById(id) {
        const wanted = String(id);
        for (let i = 0; i < apps.length; i++) {
            if (apps[i].id === wanted || apps[i].desktopId === wanted)
                return Launch.shapeRow(Object.assign({
                    "route": "desktop-entry"
                }, apps[i]), "app", 1500);
        }
        return null;
    }

    function activateId(id) {
        const row = rowById(id);
        if (!row) {
            lastInteraction = {
                "kind": "activate-missing-id",
                "id": String(id)
            };
            return stateJson();
        }
        return activate(JSON.stringify(row));
    }

    function hotkey(id) {
        const name = String(id);
        let record = {
            "id": name,
            "label": name,
            "kind": "hotkey",
            "provider": "hotkey",
            "argv": ["nuguctl", "hotkey", name],
            "slice": "session-graphical.slice",
            "osdFeedback": name
        };
        if (name === "open-launcher")
            record.argv = ["qs", "ipc", "-c", "nuguland", "call", "nuguland", "openLauncher"];

        lastInteraction = {
            "kind": "hotkey",
            "record": record
        };
        return JSON.stringify(lastInteraction);
    }

    function search(raw) {
        const ranked = Launch.rankResults(raw, {
            "apps": apps
        });
        return JSON.stringify({
            "query": raw,
            "providerIntent": ranked.providerIntent,
            "selectedIndex": ranked.selectedIndex,
            "results": ranked.results
        });
    }

    function selfTest() {
        const cases = [];
        function ok(name, cond) {
            cases.push({
                "name": name,
                "pass": !!cond
            });
        }
        try {
            ok("intent-app", Launch.prefixIntent("firefox").intent === "app");
            const exact = Launch.fuzzyScore("firefox", "firefox", 0);
            const prefix = Launch.fuzzyScore("fire", "firefox", 0);
            const subseq = Launch.fuzzyScore("frfx", "firefox", 0);
            ok("fuzzy-order", exact > prefix && prefix > subseq && subseq >= 0);
            ok("fuzzy-miss", Launch.fuzzyScore("zzz", "firefox", 0) === -1);
            const built = Launch.buildApps([
                {
                    "id": "firefox",
                    "name": "Firefox",
                    "genericName": "Web Browser",
                    "icon": "firefox",
                    "categories": ["Network"],
                    "keywords": ["web", "browser"],
                    "actions": [
                        {
                            "id": "new-window",
                            "name": "New Window",
                            "command": ["firefox", "--new-window"]
                        }
                    ]
                }
            ]);
            ok("app-details", built[0].details[0].value === "Network" && built[0].keywords[0] === "web");
            ok("app-actions", built[0].actions[0].title === "New Window");
            const rApp = Launch.rankResults("browser", {
                "apps": built
            });
            ok("rank-keyword", rApp.selectedIndex === 0 && rApp.results[0].title === "Firefox");
            ok("rank-app-only", rApp.results[0].provider === "app");
        } catch (error) {
            ok("threw:" + error, false);
        }
        const fail = cases.filter(c => {
            return !c.pass;
        }).length;
        return JSON.stringify({
            "pass": cases.length - fail,
            "fail": fail,
            "cases": cases
        });
    }
}