fix(protocol): sort channels by TS3 linked-list order, not by numeric value
The TeamSpeak 3 protocol's per-channel `order` field is NOT a
numeric rank — it stores the ChannelId of the channel that should
appear immediately before this one within the same parent. The
previous chanora_protocol::adapter::build_snapshot sorted by
`order.0` as if it were a sequence number, producing
stable-but-arbitrary output that did not match TS3 client display
order. Surfaced on the Windows verification round as 'channel
sort in not correct'.
Replace the numeric sort with a linked-list walk per parent
followed by a root-first depth-first emission so the bridge
consumer receives a pre-ordered tree:
fn sort_channels_tree(&[&Channel]) -> Vec<&Channel>
fn sort_channels_tree_by<T>(&[&T], extract) -> Vec<&T>
fn emit_subtree<T>(by_parent, root_id, out, extract)
Defensive behaviour:
* Per-parent cycle guard so a malformed snapshot can't infinite-loop.
* Channels whose predecessor pointer is unreachable from
order=0 are appended at the end of their parent bucket sorted
by id (channel never silently disappears from the UI).
* Channels whose `parent` is not present anywhere in the tree
are appended at the very end sorted by id (orphan defence).
Unit tests cover the four shapes that broke real users:
* Single-parent linked list out of HashMap iteration order
* Disconnected predecessor (leftover-bucket fallback)
* Two-level tree (depth-first subtree emission)
* Two-channel cycle (no infinite loop, both channels emitted)
Also removes the now-redundant Dart-side numeric sort in
_SnapshotView.build(); Flutter trusts the pre-ordered server
list and would otherwise re-introduce the bug.
Verified on Linux: cargo test --workspace 59/0/3 (was 55 + 4 new
adapter tests), flutter analyze clean.
This commit is contained in:
@@ -1269,8 +1269,14 @@ class _SnapshotView extends StatelessWidget {
|
||||
final l10n = AppL10n.of(context);
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final channels = [...snapshot.channels]
|
||||
..sort((a, b) => a.order.compareTo(b.order));
|
||||
// Channels arrive pre-sorted from the bridge: the Rust
|
||||
// adapter (chanora_protocol::adapter::sort_channels_tree)
|
||||
// emits them in root-first depth-first order following the
|
||||
// TeamSpeak linked-list `order` predecessor pointers. We
|
||||
// therefore trust the server order verbatim — re-sorting by
|
||||
// `order` numerically here would re-introduce the bug fixed
|
||||
// in that adapter (TS3 `order` is NOT a numeric rank).
|
||||
final channels = snapshot.channels;
|
||||
|
||||
final byChannel = <BigInt, List<rust.BridgeClient>>{};
|
||||
for (final c in snapshot.clients) {
|
||||
|
||||
Reference in New Issue
Block a user