Fix review findings: dual-entry image capture, image blob GC at limit, stdin drain, fuzzy query edge cases, uri encoding, GC queue, temp-file pruning, theme border widths
This commit is contained in:
+21
-12
@@ -88,18 +88,27 @@ Item {
|
||||
var pruned = Store.prune(root.history, root.historyLimit)
|
||||
root.history = pruned.entries
|
||||
historyFile.setText(JSON.stringify(root.history, null, 1) + "\n")
|
||||
if (pruned.droppedImagePaths.length > 0) {
|
||||
var cmd = ["rm", "-f"].concat(pruned.droppedImagePaths)
|
||||
gcProc.command = cmd
|
||||
gcProc.running = true
|
||||
}
|
||||
if (pruned.droppedImagePaths.length > 0) queueGc(pruned.droppedImagePaths)
|
||||
}
|
||||
|
||||
// Serialize GC batches: a single reusable Process would silently drop
|
||||
// overlapping runs, so pending paths queue until the current rm exits.
|
||||
property var gcQueue: []
|
||||
function queueGc(paths) {
|
||||
root.gcQueue.push(paths)
|
||||
if (!gcProc.running) runNextGc()
|
||||
}
|
||||
function runNextGc() {
|
||||
if (root.gcQueue.length === 0) return
|
||||
gcProc.command = ["rm", "-f"].concat(root.gcQueue.shift())
|
||||
gcProc.running = true
|
||||
}
|
||||
|
||||
function addClipboardJson(line) {
|
||||
var entry = null
|
||||
try { entry = JSON.parse(String(line || "")) } catch (e) { return }
|
||||
if (!entry) return
|
||||
root.history = Store.addEntry(root.history, entry, root.historyLimit, Math.floor(Date.now() / 1000))
|
||||
root.history = Store.addEntry(root.history, entry, Math.floor(Date.now() / 1000))
|
||||
root.saveHistory()
|
||||
if (root.opened) root.rebuild()
|
||||
}
|
||||
@@ -242,10 +251,7 @@ Item {
|
||||
root.history = []
|
||||
root.typeCache = {}
|
||||
root.saveHistory()
|
||||
if (dropped.length > 0) {
|
||||
gcProc.command = ["rm", "-f"].concat(dropped)
|
||||
gcProc.running = true
|
||||
}
|
||||
if (dropped.length > 0) queueGc(dropped)
|
||||
root.selectedIndex = 0
|
||||
root.clearConfirmOpen = false
|
||||
root.rebuild()
|
||||
@@ -271,7 +277,10 @@ Item {
|
||||
onFileChanged: reload()
|
||||
}
|
||||
|
||||
Process { id: gcProc }
|
||||
Process {
|
||||
id: gcProc
|
||||
onExited: runNextGc()
|
||||
}
|
||||
|
||||
// Reap watchers left behind by a previous shell instance, then start our
|
||||
// own. pdeathsig kills them whenever the shell exits.
|
||||
@@ -674,7 +683,7 @@ Item {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: root.listWidth + Style.space(6)
|
||||
width: 1
|
||||
width: Style.normalBorderWidth
|
||||
color: root.lineColor
|
||||
}
|
||||
|
||||
|
||||
+4
-11
@@ -65,10 +65,11 @@ function parseQuery(q) {
|
||||
var canonical = TYPE_ALIASES[wanted]
|
||||
if (canonical) { out.type = canonical; continue }
|
||||
// prefix match: "type:im" → image
|
||||
var matchedType = ""
|
||||
for (var key in TYPE_ALIASES) {
|
||||
if (key.indexOf(wanted) === 0) { out.type = TYPE_ALIASES[key]; break }
|
||||
if (key.indexOf(wanted) === 0) { matchedType = TYPE_ALIASES[key]; break }
|
||||
}
|
||||
if (out.type) continue
|
||||
if (matchedType) { out.type = matchedType; continue }
|
||||
// unknown type — treat the whole token as a term
|
||||
out.terms.push(tok)
|
||||
continue
|
||||
@@ -91,7 +92,7 @@ function parseQuery(q) {
|
||||
|
||||
if (AGE_WORDS[lower] !== undefined) {
|
||||
out.maxAge = AGE_WORDS[lower]
|
||||
if (lower === "yesterday") out.minAge = 0 // refined below relative to now; caller passes now
|
||||
if (lower === "yesterday") out.minAge = 86400
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -219,14 +220,6 @@ function ageFilterOk(parsed, ageSeconds) {
|
||||
return true
|
||||
}
|
||||
|
||||
// "yesterday" means older than 24h but within 48h.
|
||||
function refineYesterday(parsed, now) {
|
||||
// Only applies when the query contained the bare word "yesterday" and no
|
||||
// explicit duration bounds; approximated by caller passing minAge via the
|
||||
// maxAge=172800 already set. We require age > 86400 - slack handled here.
|
||||
return parsed
|
||||
}
|
||||
|
||||
function recencyBonus(ts, now) {
|
||||
if (!ts) return 0
|
||||
var ageDays = Math.max(0, (now - ts) / 86400)
|
||||
|
||||
@@ -163,7 +163,7 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: Style.space(10)
|
||||
height: 1
|
||||
height: Style.normalBorderWidth
|
||||
color: root.lineColor
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ Item {
|
||||
height: Style.space(120)
|
||||
radius: Style.cornerRadius
|
||||
color: root.hexRe.test(root.rawSafe()) ? root.rawSafe() : "transparent"
|
||||
border.width: 1
|
||||
border.width: Style.normalBorderWidth
|
||||
border.color: root.lineColor
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ Item {
|
||||
Rectangle {
|
||||
anchors.fill: img
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.width: Style.normalBorderWidth
|
||||
border.color: root.lineColor
|
||||
radius: Style.space(4)
|
||||
visible: img.status === Image.Ready
|
||||
|
||||
+6
-6
@@ -86,17 +86,17 @@ function parseHistory(raw, now) {
|
||||
}
|
||||
|
||||
// Add (or bump) an entry; newest first. Keeps pin state and usage count of
|
||||
// the existing copy when the same content is copied again.
|
||||
function addEntry(history, entry, limit, now) {
|
||||
// the existing copy when the same content is copied again. Does NOT truncate
|
||||
// to the limit: the caller prunes via prune() so evicted image blobs can be
|
||||
// garbage-collected (truncating here would leak them).
|
||||
function addEntry(history, entry, now) {
|
||||
var normalized = normalize(entry, now)
|
||||
var max = limit === undefined || limit === null ? DEFAULT_LIMIT : Number(limit)
|
||||
if (isNaN(max) || max < 1) max = DEFAULT_LIMIT
|
||||
if (!normalized) return Array.isArray(history) ? history.slice(0, max) : []
|
||||
if (!normalized) return Array.isArray(history) ? history.slice() : []
|
||||
|
||||
var key = entryKey(normalized)
|
||||
var next = [normalized]
|
||||
var values = Array.isArray(history) ? history : []
|
||||
for (var i = 0; i < values.length && next.length < max; i++) {
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var existing = normalize(values[i], now)
|
||||
if (!existing) continue
|
||||
if (entryKey(existing) === key) {
|
||||
|
||||
Binary file not shown.
+8
-1
@@ -99,6 +99,7 @@ def capture_image(types, app):
|
||||
pass
|
||||
return
|
||||
emit(entry)
|
||||
return True
|
||||
|
||||
|
||||
def decode_text(data):
|
||||
@@ -159,7 +160,13 @@ def capture_text(types, app):
|
||||
|
||||
|
||||
def main():
|
||||
sys.stdin.close() # watcher payload unused; we probe ourselves
|
||||
# The watcher pipes the clipboard payload to us; wl-clipboard blocks on
|
||||
# writes if we close the pipe early, so drain it instead (we still probe
|
||||
# types ourselves below).
|
||||
try:
|
||||
sys.stdin.buffer.read()
|
||||
except Exception:
|
||||
pass
|
||||
types = list_types()
|
||||
if not types:
|
||||
return
|
||||
|
||||
@@ -28,6 +28,8 @@ open_text() {
|
||||
local dir file
|
||||
dir="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy/clipboard-open"
|
||||
mkdir -p "$dir"
|
||||
# Prune temp copies older than a week; nothing else reclaims them.
|
||||
find "$dir" -type f -name 'clipboard.*.txt' -mtime +7 -delete 2>/dev/null || true
|
||||
file=$(mktemp --tmpdir="$dir" clipboard.XXXXXX.txt)
|
||||
printf '%s' "$text" >"$file"
|
||||
exec omarchy-launch-editor "$file"
|
||||
@@ -43,7 +45,7 @@ case $(jq -r '.type' <<<"$entry") in
|
||||
exec xdg-open "$path"
|
||||
;;
|
||||
files)
|
||||
first=$(jq -r '.paths[0]' <<<"$entry")
|
||||
first=$(jq -r '.paths[0] // empty' <<<"$entry")
|
||||
[[ -n $first ]] || exit 0
|
||||
exec xdg-open "$first"
|
||||
;;
|
||||
|
||||
@@ -23,7 +23,7 @@ case "$type" in
|
||||
;;
|
||||
files)
|
||||
while IFS= read -r p; do
|
||||
printf 'file://%s\n' "$p"
|
||||
printf 'file://%s\n' "$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1]))' "$p")"
|
||||
done < <(jq -r '.paths[]' <<<"$entry") | wl-copy --type text/uri-list
|
||||
;;
|
||||
*)
|
||||
|
||||
Reference in New Issue
Block a user