From 4e0cd0ab364f2083d27c13eaabc173293f399898 Mon Sep 17 00:00:00 2001 From: Alan Silva Date: Sun, 6 Sep 2026 00:03:09 +0100 Subject: [PATCH] Fix invisible picker and show dependency setup in UI --- Clipboard.qml | 71 +++++++++++++++++++++++++++++++------------------ PreviewPane.qml | 6 ++--- README.md | 13 +++++---- manifest.json | 2 +- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/Clipboard.qml b/Clipboard.qml index a0deaf7..f1f7349 100644 --- a/Clipboard.qml +++ b/Clipboard.qml @@ -61,7 +61,11 @@ Item { // ------------------------------------------------------------ lifecycle function open() { + // Always show the picker first. Dependency checks are asynchronous and + // only update the in-window banner; they never block or replace the UI. root.opened = true + root.depsChecked = false + root.checkDeps() root.filterText = "" root.typeFilter = "" root.selectedIndex = 0 @@ -334,30 +338,47 @@ Item { // Missing-helper state surfaced IN the picker: banner with the exact // command and a "Run in terminal" button. Nothing launches on its own. property bool depsChecked: false - property var missingDeps: [] // [{ name, command }] - property string depsPendingSlot: "" + property var missingDeps: [] // [{ name, packages }] function checkDeps() { - if (root.depsChecked) return + if (root.depsChecked || depsProc.running) return root.depsChecked = true - if (root.qrDecode) { - depsProc.slot = "qr" - depsProc.command = ["bash", "-c", "command -v zbarimg >/dev/null 2>&1 && echo ok || echo missing"] - depsProc.running = true - } - if (root.ocr) { - depsProc.slot = "ocr" - depsProc.command = ["bash", "-c", "command -v tesseract >/dev/null 2>&1 && echo ok || echo missing"] - depsProc.running = true + var checks = [ + "python3|Clipboard capture|python3", + "jq|Paste and open actions|jq", + "wl-copy|Clipboard access|wl-clipboard", + "wtype|Paste into the active window|wtype" + ] + if (root.qrDecode) checks.push("zbarimg|QR decode|zbar") + if (root.ocr) checks.push("tesseract|OCR search|tesseract tesseract-data-eng") + var script = "" + for (var i = 0; i < checks.length; i++) { + var fields = checks[i].split("|") + script += "command -v " + fields[0] + " >/dev/null 2>&1 || printf '%s\\n' '" + checks[i] + "';" } + depsProc.command = ["bash", "-c", script] + depsProc.running = true } - function depResult(slot, line) { - if (String(line).trim() !== "missing") return - if (slot === "qr") { - root.missingDeps.push({ name: "QR decode", command: "omarchy pkg add zbar" }) - } else if (slot === "ocr") { - root.missingDeps.push({ name: "OCR search", command: "omarchy pkg add tesseract tesseract-data-eng" }) + function depResult(output) { + var missing = [] + var lines = String(output || "").trim().split("\n") + for (var i = 0; i < lines.length; i++) { + if (!lines[i]) continue + var fields = lines[i].split("|") + if (fields.length === 3) + missing.push({ name: fields[1], packages: fields[2] }) } + root.missingDeps = missing + } + + function missingDependencyCommand() { + var packages = [] + for (var i = 0; i < root.missingDeps.length; i++) { + var names = root.missingDeps[i].packages.split(" ") + for (var j = 0; j < names.length; j++) + if (packages.indexOf(names[j]) === -1) packages.push(names[j]) + } + return packages.length ? "omarchy pkg add " + packages.join(" ") : "" } function applySettings(raw) { @@ -407,10 +428,9 @@ Item { Process { id: depsProc - property string slot: "" stdout: StdioCollector { waitForEnd: true - onStreamFinished: root.depResult(depsProc.slot, text) + onStreamFinished: root.depResult(text) } } Process { @@ -473,8 +493,8 @@ Item { PanelWindow { id: panel visible: root.opened - width: root.cardWidth - height: root.cardHeight + implicitWidth: root.cardWidth + implicitHeight: root.cardHeight color: "transparent" WlrLayershell.namespace: "alanfortlink-clipboard" WlrLayershell.layer: WlrLayer.Overlay @@ -724,7 +744,7 @@ Item { Text { anchors.verticalCenter: parent.verticalCenter text: root.missingDeps.length > 0 - ? root.missingDeps[0].name + " unavailable — run: " + root.missingDeps[0].command + ? root.missingDeps[0].name + " unavailable — run: " + root.missingDependencyCommand() : "" color: Color.urgent font.family: root.fontFamily @@ -755,9 +775,8 @@ Item { onClicked: { if (root.missingDeps.length === 0) return root.close() - var cmd = "" - for (var i = 0; i < root.missingDeps.length; i++) - cmd += (i ? " && " : "") + root.missingDeps[i].command + var cmd = root.missingDependencyCommand() + if (!cmd) return cmd += '; echo; echo "Done — press Enter to close"; read' Quickshell.execDetached(["omarchy-launch-terminal", "bash", "-c", cmd]) } diff --git a/PreviewPane.qml b/PreviewPane.qml index ff42703..dfc01f6 100644 --- a/PreviewPane.qml +++ b/PreviewPane.qml @@ -360,7 +360,7 @@ Item { // Decoded QR payload sits above the image so it is immediately readable. Rectangle { - visible: root.entry && root.entry.qr + visible: !!(root.entry && root.entry.qr) width: parent.width height: qrContent.height + Style.space(12) radius: Style.cornerRadius @@ -456,7 +456,7 @@ Item { // OCR text recovered from the image (searchable like any text clip). Rectangle { id: ocrPanel - visible: root.entry && root.entry.ocr + visible: !!(root.entry && root.entry.ocr) width: parent.width height: Math.min(Style.space(150), ocrContent.height + Style.space(12)) radius: Style.cornerRadius @@ -599,7 +599,7 @@ Item { } Text { - visible: root.entry && root.entry.paths && root.entry.paths.length > 10 + visible: !!(root.entry && root.entry.paths && root.entry.paths.length > 10) text: root.entry && root.entry.paths ? "… and " + (root.entry.paths.length - 10) + " more" : "" color: root.mutedFg font.family: root.font_ diff --git a/README.md b/README.md index 91d7af1..34e273c 100644 --- a/README.md +++ b/README.md @@ -47,11 +47,9 @@ full theme integration. omarchy plugin add https://github.com/alanfortlink/clipboard-history.git --enable ``` -Optional extras (usually already installed): - -```bash -omarchy pkg add zbar tesseract tesseract-data-eng # QR decode + OCR search -``` +No separate dependency command is required during installation. The picker +always opens; if a helper is missing, it shows the exact package command inside +the window with a **Run in terminal** button. Already have images in history you'd like OCR'd? One-shot backfill: @@ -63,8 +61,9 @@ That's the whole install — `omarchy plugin add` clones the repo, validates the manifest, and enables it. It replaces the built-in `omarchy.clipboard` (restore it later with `omarchy plugin disable alanfortlink.clipboard`). -Omarchy's default `Super+Ctrl+V` (and `Super+Shift+V`) already routes to it -via the clone mechanism. For a custom binding, edit the **live** config — +Omarchy's default `Super+Ctrl+V` routes to it via the clone mechanism. An +existing `Super+Shift+V` binding targeting `omarchy.clipboard` routes to it too. +For a custom binding, edit the **live** config — `~/.config/hypr/bindings.lua` on Quattro (a plain `bindings.conf` may exist but is not sourced): diff --git a/manifest.json b/manifest.json index e76a0f9..c3b0418 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "schemaVersion": 1, "id": "alanfortlink.clipboard", "name": "Clipboard History", - "version": "1.0.0", + "version": "1.0.1", "author": "alanfortlink", "description": "Raycast-style clipboard history: fuzzy search over content, type, app and date, with rich per-type previews", "kinds": [