Fix invisible picker and show dependency setup in UI
This commit is contained in:
+44
-25
@@ -61,7 +61,11 @@ Item {
|
|||||||
// ------------------------------------------------------------ lifecycle
|
// ------------------------------------------------------------ lifecycle
|
||||||
|
|
||||||
function open() {
|
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.opened = true
|
||||||
|
root.depsChecked = false
|
||||||
|
root.checkDeps()
|
||||||
root.filterText = ""
|
root.filterText = ""
|
||||||
root.typeFilter = ""
|
root.typeFilter = ""
|
||||||
root.selectedIndex = 0
|
root.selectedIndex = 0
|
||||||
@@ -334,30 +338,47 @@ Item {
|
|||||||
// Missing-helper state surfaced IN the picker: banner with the exact
|
// Missing-helper state surfaced IN the picker: banner with the exact
|
||||||
// command and a "Run in terminal" button. Nothing launches on its own.
|
// command and a "Run in terminal" button. Nothing launches on its own.
|
||||||
property bool depsChecked: false
|
property bool depsChecked: false
|
||||||
property var missingDeps: [] // [{ name, command }]
|
property var missingDeps: [] // [{ name, packages }]
|
||||||
property string depsPendingSlot: ""
|
|
||||||
function checkDeps() {
|
function checkDeps() {
|
||||||
if (root.depsChecked) return
|
if (root.depsChecked || depsProc.running) return
|
||||||
root.depsChecked = true
|
root.depsChecked = true
|
||||||
if (root.qrDecode) {
|
var checks = [
|
||||||
depsProc.slot = "qr"
|
"python3|Clipboard capture|python3",
|
||||||
depsProc.command = ["bash", "-c", "command -v zbarimg >/dev/null 2>&1 && echo ok || echo missing"]
|
"jq|Paste and open actions|jq",
|
||||||
depsProc.running = true
|
"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] + "';"
|
||||||
}
|
}
|
||||||
if (root.ocr) {
|
depsProc.command = ["bash", "-c", script]
|
||||||
depsProc.slot = "ocr"
|
|
||||||
depsProc.command = ["bash", "-c", "command -v tesseract >/dev/null 2>&1 && echo ok || echo missing"]
|
|
||||||
depsProc.running = true
|
depsProc.running = true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function depResult(slot, line) {
|
function depResult(output) {
|
||||||
if (String(line).trim() !== "missing") return
|
var missing = []
|
||||||
if (slot === "qr") {
|
var lines = String(output || "").trim().split("\n")
|
||||||
root.missingDeps.push({ name: "QR decode", command: "omarchy pkg add zbar" })
|
for (var i = 0; i < lines.length; i++) {
|
||||||
} else if (slot === "ocr") {
|
if (!lines[i]) continue
|
||||||
root.missingDeps.push({ name: "OCR search", command: "omarchy pkg add tesseract tesseract-data-eng" })
|
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) {
|
function applySettings(raw) {
|
||||||
@@ -407,10 +428,9 @@ Item {
|
|||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: depsProc
|
id: depsProc
|
||||||
property string slot: ""
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
waitForEnd: true
|
waitForEnd: true
|
||||||
onStreamFinished: root.depResult(depsProc.slot, text)
|
onStreamFinished: root.depResult(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Process {
|
Process {
|
||||||
@@ -473,8 +493,8 @@ Item {
|
|||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: panel
|
id: panel
|
||||||
visible: root.opened
|
visible: root.opened
|
||||||
width: root.cardWidth
|
implicitWidth: root.cardWidth
|
||||||
height: root.cardHeight
|
implicitHeight: root.cardHeight
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
WlrLayershell.namespace: "alanfortlink-clipboard"
|
WlrLayershell.namespace: "alanfortlink-clipboard"
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
WlrLayershell.layer: WlrLayer.Overlay
|
||||||
@@ -724,7 +744,7 @@ Item {
|
|||||||
Text {
|
Text {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
text: root.missingDeps.length > 0
|
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
|
color: Color.urgent
|
||||||
font.family: root.fontFamily
|
font.family: root.fontFamily
|
||||||
@@ -755,9 +775,8 @@ Item {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.missingDeps.length === 0) return
|
if (root.missingDeps.length === 0) return
|
||||||
root.close()
|
root.close()
|
||||||
var cmd = ""
|
var cmd = root.missingDependencyCommand()
|
||||||
for (var i = 0; i < root.missingDeps.length; i++)
|
if (!cmd) return
|
||||||
cmd += (i ? " && " : "") + root.missingDeps[i].command
|
|
||||||
cmd += '; echo; echo "Done — press Enter to close"; read'
|
cmd += '; echo; echo "Done — press Enter to close"; read'
|
||||||
Quickshell.execDetached(["omarchy-launch-terminal", "bash", "-c", cmd])
|
Quickshell.execDetached(["omarchy-launch-terminal", "bash", "-c", cmd])
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -360,7 +360,7 @@ Item {
|
|||||||
|
|
||||||
// Decoded QR payload sits above the image so it is immediately readable.
|
// Decoded QR payload sits above the image so it is immediately readable.
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.entry && root.entry.qr
|
visible: !!(root.entry && root.entry.qr)
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: qrContent.height + Style.space(12)
|
height: qrContent.height + Style.space(12)
|
||||||
radius: Style.cornerRadius
|
radius: Style.cornerRadius
|
||||||
@@ -456,7 +456,7 @@ Item {
|
|||||||
// OCR text recovered from the image (searchable like any text clip).
|
// OCR text recovered from the image (searchable like any text clip).
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: ocrPanel
|
id: ocrPanel
|
||||||
visible: root.entry && root.entry.ocr
|
visible: !!(root.entry && root.entry.ocr)
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: Math.min(Style.space(150), ocrContent.height + Style.space(12))
|
height: Math.min(Style.space(150), ocrContent.height + Style.space(12))
|
||||||
radius: Style.cornerRadius
|
radius: Style.cornerRadius
|
||||||
@@ -599,7 +599,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
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" : ""
|
text: root.entry && root.entry.paths ? "… and " + (root.entry.paths.length - 10) + " more" : ""
|
||||||
color: root.mutedFg
|
color: root.mutedFg
|
||||||
font.family: root.font_
|
font.family: root.font_
|
||||||
|
|||||||
@@ -47,11 +47,9 @@ full theme integration.
|
|||||||
omarchy plugin add https://github.com/alanfortlink/clipboard-history.git --enable
|
omarchy plugin add https://github.com/alanfortlink/clipboard-history.git --enable
|
||||||
```
|
```
|
||||||
|
|
||||||
Optional extras (usually already installed):
|
No separate dependency command is required during installation. The picker
|
||||||
|
always opens; if a helper is missing, it shows the exact package command inside
|
||||||
```bash
|
the window with a **Run in terminal** button.
|
||||||
omarchy pkg add zbar tesseract tesseract-data-eng # QR decode + OCR search
|
|
||||||
```
|
|
||||||
|
|
||||||
Already have images in history you'd like OCR'd? One-shot backfill:
|
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`
|
manifest, and enables it. It replaces the built-in `omarchy.clipboard`
|
||||||
(restore it later with `omarchy plugin disable alanfortlink.clipboard`).
|
(restore it later with `omarchy plugin disable alanfortlink.clipboard`).
|
||||||
|
|
||||||
Omarchy's default `Super+Ctrl+V` (and `Super+Shift+V`) already routes to it
|
Omarchy's default `Super+Ctrl+V` routes to it via the clone mechanism. An
|
||||||
via the clone mechanism. For a custom binding, edit the **live** config —
|
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
|
`~/.config/hypr/bindings.lua` on Quattro (a plain `bindings.conf` may exist
|
||||||
but is not sourced):
|
but is not sourced):
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"id": "alanfortlink.clipboard",
|
"id": "alanfortlink.clipboard",
|
||||||
"name": "Clipboard History",
|
"name": "Clipboard History",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"author": "alanfortlink",
|
"author": "alanfortlink",
|
||||||
"description": "Raycast-style clipboard history: fuzzy search over content, type, app and date, with rich per-type previews",
|
"description": "Raycast-style clipboard history: fuzzy search over content, type, app and date, with rich per-type previews",
|
||||||
"kinds": [
|
"kinds": [
|
||||||
|
|||||||
Reference in New Issue
Block a user