Introduces DropHandler to own the drop pipeline and addresses every item
from the review:
- Folders / .app bundles / packages: DropProgressCopier.copyTree walks
directories instead of failing with a generic 'Failed to copy'.
- File promises (Photos, Mail, browser image drags) are now accepted and
materialized instead of silently no-opping.
- Multi-file toast race: per-file DropSession id; stale relocation
results for a superseded file are ignored by update/finish/
setFinalDestination.
- Partial files: copyTree removes its partial output on any error, and
the handler drops the now-empty subdir, so the guest never sees a
truncated file.
- Teardown race: in-flight guest relocations register with
RelocationGate; 'tart run' drains it (<=6s) before deleting the drop
zone / exiting.
- Path collisions: each file copies into its own dropRoot/<uuid>/ subdir.
- Reserved name: a user --dir named 'Dropped Files' is now rejected.
- Linux / no agent: relocation is skipped and the toast says 'Copied to
the shared folder' instead of a misleading Finder destination.
- Agent-down timing: success toast holds on a fallback timer that
outlives the 5s RPC deadline so the final destination is always shown.
- Concurrency: relocations run one-at-a-time; copy failures are
coalesced into a single alert instead of a modal storm.
- Zero-byte/unknown size shows just the copied amount, not '0 bytes of ?'.
- Removed dead DropFolderBox + stale doc comment; fixed the
http://-vs-https:// typo in toRemoteOrLocalURL.
Tests: DropProgressCopierTests (replace/cancel/error-cleanup/empty/
directory/size), GuestDropParseTests (stdout parser), and a reserved-name
case in DirectoryShareTests. Product and test target both compile.
DropProgressToast.swift (436 lines) bundled four responsibilities. Split
verbatim into:
- DropCancellationToken.swift - cancel token + DropCopyCancelled sentinel
- DropProgressCopier.swift - chunked file copier
- DropProgressToast.swift - toast state/coordination (lifecycle API)
- DropProgressToast+Panel.swift - AppKit panel construction/positioning
Each file is well under 250 lines and single-responsibility. The only
non-move change is widening the members the +Panel extension references
from private to internal; no behavior, signatures, or logic changed.