mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 16:14:40 +00:00
Browsing a relay's groups (Relay Groups → Find groups → pick a relay)
crashed the app to the launcher:
java.lang.IllegalArgumentException: Comparison method violates its
general contract!
at java.util.TimSort.mergeLo
...
at RelayGroupChannelListScreen$allChannels$3$1$1.emit
`sortedBy { it.toBestDisplayName().lowercase() }` re-evaluates its key on
every comparison, and the key comes from mutable shared state — the
channel's display name, which a kind-39000 directory event can change
while the sort is running. TimSort detects the inconsistency and throws.
The failure scales with directory size and needs no user action: a relay
hosting 1237 groups tripped it on the first browse, while a relay with 18
never did — which is why an earlier sweep of this same screen missed it.
v1.12.6 already fixed this class elsewhere ("snapshot live-stream status
order before sorting"); these sites were not covered.
Adds `sortedBySnapshot`, which computes each key ONCE before any
comparison runs, and applies it to all four sites that sorted live
objects by their display name: the relay group directory (both the
initial value and the observer), the parent-group picker, and the
name-ordered search results. The picker's site also had to materialise
its Sequence first, since sorting lazily would have re-introduced the
same window.
Verified on device: the exact tap that crashed now loads the screen with
zero FATAL EXCEPTIONs and the app stays in the foreground.
Found while setting up a NIP-29 group to test the admin surface, which is
also how the directory got large enough to expose it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>