Conversation
…umber Closes #51. The rail's order came from a single computed (useUplData.orderedChannels) that always sorted by channel number, with the name only as a tiebreak. That explains every symptom in the issue thread: - "all the playlists EXCEPT localnow have been alphabetized" — most built-in sources never populate channelNo, so every row tied on the number key and fell through to the name tiebreak. The rail looked alphabetical by accident. - "it's not sorting the custom playlist I added" — a clone inherits each channel's number from its original source (00s Replay = 600000 sitting next to 6065), so the numeric key dominated and the list looked shuffled. Adds an A-Z / # toggle to the channel rail header, defaulting to NAME order. The choice is a per-device viewer preference persisted under 'upl:sort', following UplVideoJsPlayer's existing 'upl:audio' pattern — same namespace, same defensive read, same silent fallback when storage is blocked. Deliberately not a Settings field: this bundle never fetches /api/settings, and importing useSettings would drag data.ts into the popup. The channelNo comparator is the one the Playlist detail table already uses (numeric when both sides parse, else lexical, unnumbered last), which fixes two latent bugs in the old expression — both of which put unnumbered channels FIRST, directly against the comment that sat above it: - Number(null) is 0, not NaN, so a null channelNo sorted ahead of channel 1. - '' is not null, so a blank channelNo lexically outranked every real number. Blank now counts as unnumbered in both the sort and the display ('—', matching a null one, instead of leaving a gap in the column). parseFloat rather than Number is load-bearing: it reads the leading number, so a '12A' subchannel sorts next to 12 instead of being exiled with the unparseable values. A reorder moves every list index, so the rail re-pins its keyboard cursor to the playing channel on a sort change — as a watcher separate from the existing re-measure, which also fires on every filter keystroke, where yanking the cursor back would fight the person typing. No server change. GET /api/playlists/:id/channels keeps its index-backed .sort({ group: 1, tvg_name: 1 }), which m3u/compose.ts deliberately mirrors for the .m3u export; the player re-sorts client-side instead. Verified: `npm run build` (vue-tsc + vite) passes. Both orders, the persistence, the cursor re-pin, the filter-does-not-move-the-cursor guard, the 340px header layout and both themes were exercised in-browser against the real components, using the issue's own channel numbers.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…umber
Closes #51.
The rail's order came from a single computed (useUplData.orderedChannels) that always sorted by channel number, with the name only as a tiebreak. That explains every symptom in the issue thread:
Adds an A-Z / # toggle to the channel rail header, defaulting to NAME order. The choice is a per-device viewer preference persisted under 'upl:sort', following UplVideoJsPlayer's existing 'upl:audio' pattern — same namespace, same defensive read, same silent fallback when storage is blocked. Deliberately not a Settings field: this bundle never fetches /api/settings, and importing useSettings would drag data.ts into the popup.
The channelNo comparator is the one the Playlist detail table already uses (numeric when both sides parse, else lexical, unnumbered last), which fixes two latent bugs in the old expression — both of which put unnumbered channels FIRST, directly against the comment that sat above it:
Blank now counts as unnumbered in both the sort and the display ('—', matching a null one, instead of leaving a gap in the column). parseFloat rather than Number is load-bearing: it reads the leading number, so a '12A' subchannel sorts next to 12 instead of being exiled with the unparseable values.
A reorder moves every list index, so the rail re-pins its keyboard cursor to the playing channel on a sort change — as a watcher separate from the existing re-measure, which also fires on every filter keystroke, where yanking the cursor back would fight the person typing.
No server change. GET /api/playlists/:id/channels keeps its index-backed .sort({ group: 1, tvg_name: 1 }), which m3u/compose.ts deliberately mirrors for the .m3u export; the player re-sorts client-side instead.
Verified:
npm run build(vue-tsc + vite) passes. Both orders, the persistence, the cursor re-pin, the filter-does-not-move-the-cursor guard, the 340px header layout and both themes were exercised in-browser against the real components, using the issue's own channel numbers.