Files
omarchy/bin/omarchy-tailscale-receive
T
OmarchybotandClaude Opus 5 07adef8a53 Let a received Taildrop file wait to be answered (backport of #7953)
Backport of the Taildrop toast fix (PR #7953, merged to quattro as 7e469f96)
onto the v4-0-1 release branch.

A delivery can land hours after it was sent, and the toast announcing it was
expiring after five seconds -- so a file that arrived while nobody was at the
machine was gone from the screen before anyone could click it open. Critical
urgency is what the shell reads as a popup that lives until it is clicked or
dismissed, the same thing omarchy-crash-watch uses to keep its click-to-diagnose
toast around.

The mechanism is already on this branch: omarchy-notification-send parses
options that follow the two positionals, and NotificationLogic.js gives a
critical popup duration 0, which never expires.

One conflict, in test/shell.d/notification-send-test.sh. #7953 added coverage
for the trailing-option path in the notify-send form it had then; #7926, which
merged after it on quattro and is already backported here, rewrote that file for
the Notify D-Bus form and carried the same coverage across. This branch
therefore already asserts what #7953 added -- an urgency and a glyph after the
description reach the call, and the urgency is set once -- so the branch's
version stands and the resolved file is unchanged.

Verified by mutation: with -u critical removed, test/shell.d/tailscale-receive-
test.sh fails at once; restored, it passes, including the new assertion that
every announcement waits to be answered.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018DEMYa9UWtroz93DhMTtcV
2026-08-25 09:39:50 +02:00

100 lines
2.6 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Save incoming Taildrop files and announce them
# omarchy:args=[--once] [directory]
# omarchy:examples=omarchy tailscale receive | omarchy tailscale receive --once ~/Desktop
set -euo pipefail
once=false
if [[ ${1:-} == "--once" ]]; then
once=true
shift
fi
dir="${1:-${XDG_DOWNLOAD_DIR:-$HOME/Downloads}}"
# Taildrop lands in a staging directory next door rather than straight in the
# downloads directory: waiting for a delivery can take hours, and everything
# else that shows up meanwhile is somebody else's file. Same filesystem, so
# handing the finished file over is a rename.
staging="$dir/.omarchy-taildrop"
mkdir -p "$staging"
# Take the name by linking to it rather than by looking and then renaming.
# link(2) refuses an existing name, so nothing can land on the chosen one in
# the gap between the two. Staging shares the filesystem with the downloads
# directory, so the link always resolves and unlinking the staged name
# finishes the move. Prints the name it took.
claim_path() {
local staged="$1" name="${staged##*/}" base ext candidate index=0
base="${name%.*}"
ext="${name#"$base"}"
[[ -z $base ]] && { base="$name"; ext=""; }
while (( index < 1000 )); do
if (( index == 0 )); then
candidate="$dir/$name"
else
candidate="$dir/$base-$index$ext"
fi
if ln -- "$staged" "$candidate" 2>/dev/null; then
rm -f -- "$staged"
printf '%s\n' "$candidate"
return 0
fi
# Only a taken name is worth another spin. Anything else failed the link
# itself, and the file keeps its place in staging for the next run.
[[ -e $candidate ]] || return 1
((index++))
done
return 1
}
announce() {
local path="$1"
local name="${path##*/}"
local args=("Received $name" "Saved to ${dir/#$HOME/~}" -u critical)
case "${name,,}" in
*.png | *.jpg | *.jpeg | *.gif | *.webp | *.avif | *.bmp | *.tif | *.tiff)
args+=(--image "$path")
;;
*)
args+=(-g 󰒊)
;;
esac
# Announcing is best-effort: the file is already delivered, and under `set -e`
# a notification outage would otherwise kill the long-running receiver.
omarchy-notification-send "${args[@]}" --exec xdg-open "$path" || true
}
deliver() {
local staged target
while IFS= read -r staged; do
target=$(claim_path "$staged") || continue
announce "$target"
done < <(find "$staging" -mindepth 1 -maxdepth 1)
}
# Anything left staged by an interrupted run still deserves delivering.
deliver
while true; do
if ! tailscale file get --wait --conflict=rename "$staging"; then
$once && exit 1
sleep 10
continue
fi
deliver
$once && exit 0
done