fix(playlists): name the view state in one sentence

Sorting a playlist whose stored order already matches the sort produced a
warning, no Save button and no visible change — which reads as a malfunction,
not as "there is nothing to save". And when the order DID change, three separate
texts piled up in the toolbar (a reset link, a save hint, a "reordering is off"
notice), none of which answered the question actually being asked: did I just
change my playlist?

One line now names which of the three situations you are in — the view matches
the saved order, the view differs and can be saved, or a filter is on and saving
is impossible — and says in each case that the saved order is untouched. The
disabled grip still explains itself on hover and focus, so that notice no longer
needs to stand in the toolbar.
This commit is contained in:
2026-07-21 00:40:49 +02:00
parent cdec80547e
commit f87d58d8d7
3 changed files with 36 additions and 11 deletions
+24 -7
View File
@@ -492,6 +492,23 @@ export default function Playlists() {
// every render re-subscribed those listeners and re-ran focusModal() under the open player.
const closePlayer = useCallback(() => setPlayingId(null), []);
// Name the current view in the user's terms: "Title ↑", "grouped by channel", or both.
const sortLabel = viewSort && !isStoredSort(viewSort)
? `${columns.find((c) => c.key === viewSort.key)?.header ?? viewSort.key} ${
viewSort.dir === "asc" ? "↑" : "↓"
}`
: null;
const viewName = groupBy
? sortLabel
? t("playlists.viewGroupedAnd", { sort: sortLabel })
: t("playlists.viewGrouped")
: (sortLabel ?? "");
const viewStatus = filterActive
? t("playlists.viewFiltered", { shown: shown.length, total: items.length })
: canSaveOrder
? t("playlists.viewDiffers", { view: viewName })
: t("playlists.viewMatches", { view: viewName });
// Order matters: a built-in list is never reorderable, whatever the view says.
const dragHint = !canEdit
? t("playlists.dragBlockedBuiltin")
@@ -670,19 +687,19 @@ export default function Playlists() {
{canSaveOrder && (
<button
onClick={saveOrder}
aria-describedby="pl-save-hint"
className="inline-flex items-center gap-1.5 text-xs font-semibold px-2.5 py-1 rounded-lg border border-accent text-accent hover:bg-accent/10 transition"
>
<Check className="w-3.5 h-3.5" /> {t("playlists.saveOrder")}
</button>
)}
{canSaveOrder && (
<span id="pl-save-hint" className="text-[11px] text-muted/80">
{t("playlists.saveOrderHint")}
</span>
)}
{/* ONE sentence that names the state. Three loose texts used to pile up here (reset
link + save hint + "reordering is off"), and none of them answered the question a
user actually has — "did I just change my playlist?". Worse, sorting a list whose
stored order ALREADY matches the sort produced a warning, no Save button and no
visible change, which reads as a malfunction. Now the line says which of the three
situations you are in; the disabled grip still explains itself on hover/focus. */}
{viewActive && (
<span className="text-[11px] text-muted/80">{dragHint}</span>
<span className="text-[11px] text-muted/80">{viewStatus}</span>
)}
{canEdit && (
<div className="ml-auto">