Skip to content

feat: accept a .torrent dragged onto the search field - #147

Open
ugurckr wants to merge 1 commit into
baairon:mainfrom
ugurckr:feat/drop-torrent-file
Open

feat: accept a .torrent dragged onto the search field#147
ugurckr wants to merge 1 commit into
baairon:mainfrom
ugurckr:feat/drop-torrent-file

Conversation

@ugurckr

@ugurckr ugurckr commented Aug 11, 2026

Copy link
Copy Markdown

What and why

Dragging a file onto a terminal window pastes its path into whatever is reading input. That's the
gesture people already reach for when they have a .torrent on disk, and torlink half-supported
it: the search field took a magnet or a bare infohash, but a path was just a search query, so the
obvious move silently searched for C:\Users\...\thing.torrent and found nothing. torlnk <file>.torrent worked from the shell, but there was no way in from inside the running app.

The search field now recognises a .torrent path and downloads it. The work is in getting the
path back out of what the terminal actually pastes, because no two emulators agree:

Emulator What lands in the field
Windows Terminal, PowerShell "C:\Users\u\My Show.torrent" plus a trailing space
macOS Terminal, iTerm2 /Users/u/My\ Show\ \(2024\).torrent
GNOME Terminal file:///home/u/My%20Show.torrent

resolveTorrentPath unwraps all three. The backslash rule is split by platform — an escape on
macOS and Linux, a path separator on Windows — because unescaping a Windows path would destroy it.
It takes the platform as an option rather than reading process.platform only, so the tests drive
both from either host instead of covering only the half that matches the runner.

Two smaller things follow from the same helper: paste (v) takes a path too, since copying a file
in a file manager is how a path gets on the clipboard in the first place; and torlnk <file>.torrent runs its argument through the same normalizer, so a shell-quoted or file://
argument works there as well.

A path that turns out not to be a readable torrent reports that, rather than falling back to a
search — the one thing worse than not supporting the gesture is supporting it silently badly.

No new key and no change to an existing one. on the search field already meant "do something
with this"; this widens what it accepts, next to the magnet and infohash cases that were already
there. The splash placeholder now says so.

Checklist

  • npm run typecheck is clean
  • npm test passes — with one caveat: on my Windows box 5 test files (daemon/runtime,
    daemon/serve, daemon/watch, download/queue, download/queue.safemode) fail to load
    node-datachannel. They fail identically on a clean main here, so it's my environment and
    not this change. Everything else passes, including the 15 new tests.
  • New logic has a test — src/sources/torrentPath.test.ts, covering all three emulator
    shapes on both platforms, ~ expansion, uppercase extensions, and the cases that must stay
    a search (plain query, magnet, blank, a non-torrent file).
  • No new key, so HELP_GROUPS / footerHints are unchanged
  • No new Store field, so makeStore is unchanged
  • OS-touching code works on Windows, macOS, and Linux — that's the substance of the change
  • One concern, Conventional Commits title

Note on ordering

This is independent of my other PR (fix: keep a torrent's own trackers…) and the two touch
different files, so they merge in either order. They do compose, though: dropping a private
torrent's file is exactly the case where the discarded announce list mattered most.

Dropping a file on a terminal pastes its path into whatever is reading
input, which is already how people expect to hand a client a .torrent. The
search field took a magnet or an infohash but treated a path as a search
query, so the obvious gesture silently searched for "C:\Users\..." instead.

Each emulator escapes that path its own way and none of them agree: Windows
Terminal and PowerShell wrap it in double quotes and leave a trailing space,
macOS Terminal and iTerm2 escape spaces and parens with backslashes, GNOME
Terminal pastes a percent-escaped file:// URI. resolveTorrentPath unwraps
all three back to a plain path, with the backslash rule split by platform --
an escape on macOS and Linux, a path separator on Windows, so a Windows path
is never mangled. Its tests drive both platforms from either host rather
than only the half that matches the runner.

Paste (v) takes a path too, since copying a file in a file manager puts one
on the clipboard, and `torlnk <file>.torrent` runs its argument through the
same normalizer so a shell-quoted or file:// argument works there as well.
A path that turns out not to be a readable torrent says so rather than
falling back to a search, so the failure is never silent. No new key, no
change to an existing one -- Enter on the search field already meant "do
something with this", and this widens what it accepts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant