Skip to content

mobile: fix the empty torrent list on the direct XML-RPC mount, plus a round of fixes - #3134

Merged
xirvik merged 2 commits into
Novik:masterfrom
xombiemp:mobile-tracker-fetch-fixes
Jul 25, 2026
Merged

mobile: fix the empty torrent list on the direct XML-RPC mount, plus a round of fixes#3134
xirvik merged 2 commits into
Novik:masterfrom
xombiemp:mobile-tracker-fetch-fixes

Conversation

@xombiemp

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #3128. The headline fix is the empty torrent list reported by @Abzie in the #3128 discussion, which affects installs using the direct XML-RPC mount (no httprpc):

  • The mobile tracker fetch sent ?action=getalltrackers with no hashes. httprpc happens to treat an empty hash list as "all torrents", but the direct mount's stub (rTorrentStub.prototype.getalltrackers) builds one t.multicall per given hash — with none given it produces zero commands, and rTorrentStub silently drops command-less requests without invoking the callback. The mobile list render runs inside that callback, so the list stayed empty forever while settings/add pages worked. The fetch now names every hash explicitly, exactly like the desktop's getAllTrackers, and short-circuits the zero-torrent case (the render also removes deleted torrents' rows, so it must still run).

Also in this round:

  • Torrents that appear between full renders (e.g. added from another session) are inserted at their sorted position instead of being appended to the end of the list
  • Torrents added from elsewhere (another session, rss, automation) show a toast, like the existing deletion toasts; a local add keeps its upload receipt and scroll-to-torrent behavior instead
  • The on-screen keyboard is dismissed on scroll for all text fields, not just the quick search (iOS anchors position:fixed elements to the layout viewport while it's open)
  • A new-label edit commits only via its check button or the return key; tapping or scrolling away cancels instead of saving

Test plan

  • On a direct XML-RPC mount (no backend plugin): open the mobile UI — the torrent list renders (regression: also verify on httprpc, where explicit hashes >50 collapse back to the all-torrents form server-side)
  • Two sessions: add a torrent in one — the other inserts it at its sorted position and toasts "Added: name"
  • Add locally: receipt toast, return to list, scroll+highlight to the new torrent, no "Added" toast
  • Edit a label via "New label": check button and return save; tapping/scrolling away reverts
  • Focus any add-form field, scroll — keyboard dismisses, fixed bars stay put

Made with Cursor

- Fix the empty torrent list on the direct XML-RPC mount (reported on
  the bundling PR): the tracker fetch sent ?action=getalltrackers with
  no hashes. httprpc treats that as "all torrents", but the direct
  mount's stub builds one t.multicall per given hash and silently
  sends nothing for an empty list - its callback never fires, and the
  list render lives in that callback. Name every hash explicitly, like
  the desktop's getAllTrackers, and short-circuit the zero-torrent
  case (the render also removes deleted torrents' rows, so it must
  still run)
- Insert torrents that appear between full renders (e.g. added from
  another session) at their sorted position instead of appending them
  to the end of the list
- Toast torrents added from elsewhere (another session, rss,
  automation), like the deletion toasts; a local add keeps its upload
  receipt and scroll-to-torrent instead. Skip the first render cycle,
  when every torrent counts as new
- Dismiss the on-screen keyboard on scroll for all text fields, not
  just the quick search
- Commit a new-label edit only via its check button or the return key;
  tapping or scrolling away now cancels instead of saving
@xombiemp

Copy link
Copy Markdown
Collaborator Author

@Abzie Please try this along with #3133 and let us know if it fixes the issue.

@Abzie

Abzie commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

@xombiemp I have cherry-picked both commits and the torrent list is populating now... It is looking good :)

@xirvik

xirvik commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Tested this on a large torrent list and it regresses into the same blank screen it fixes.

Claude explains it better, sorry for the slop:

getalltrackers is a GET and this names every hash in the query string; on a ~950-torrent view that's a ~46 KB URL, which nginx rejects with 414 Request-URI Too Large before it reaches PHP — the request fails, the callback never runs, list stays empty. The wall is nginx's default large_client_header_buffers (8 KB) ≈ ~150 hashes (measured: 105 hashes/5 KB reaches PHP, 950/46 KB → 414). Small lists test clean, which is why the reporter's did, but a few hundred+ torrents gets the
blank list back — on any backend, since the mobile fetch bypasses the multirpc stub's >50→all collapse. The >50 collapse server-side note doesn't help: the URL is rejected before the server can collapse it.

Options:

  • POST the hashes instead of GET (no URL-length limit), or
  • chunk into ≤50-per-request batches and merge, or
  • keep the empty-hash "all" form where the backend supports it and enumerate only on the direct XML-RPC mount (the case that needs it).

In any case, test it (well, everything) against a rtorrent/ruTorrent with around 5k torrents loaded. It's more common than you'd think.

@xombiemp

Copy link
Copy Markdown
Collaborator Author

@xirvik Not sure I'm following this one completely.
What is multirpc? Is that an out of tree backend?

AI seems to think the in repo backends are not affected:

On stock httprpc, the wire request for a large list is byte-for-byte identical before and after our PR. On the direct mount, the hashes travel as an XML POST body — no URL, no 414. The regression needs a transport that (a) puts the query in a GET URL and (b) does its >50 collapse somewhere our fetch doesn't pass through.

So is there a backend I'm not aware of?

Naming every hash regressed large lists on transports that carry the
query string in the request line: at ~950 torrents the URL outgrows
nginx's default buffers and is 414-rejected before PHP could collapse
it (stock httprpc was unaffected — its stub override collapses >50
hashes to the hashless form and POSTs a body either way).

The PHP transports all treat a hashless getalltrackers as "all
torrents", which is exactly what this fetch wants, so send that form.
Enumerate the hashes only when a probe shows the active transport is
the base XML-RPC stub — the one case that silently drops the hashless
form, and the bug the enumeration was added for. There the hashes
travel as POSTed XML with the stub's existing fragmentation, so no
list size can overflow anything.
@xombiemp

xombiemp commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator Author

@xirvik I implemented your suggestion 3. Can you try it out on your system where it failed previously?

@xirvik

xirvik commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

@xirvik I implemented your suggestion 3. Can you try it out on your system where it failed previously?

I'm not totally sure the fail wasn't due to my own tests - sorry about this, I suspect I made you waste a bit of time on this one.

@xirvik
xirvik merged commit 879011a into Novik:master Jul 25, 2026
5 checks passed
@xirvik xirvik mentioned this pull request Jul 25, 2026
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.

3 participants