Add a sort toolbar to the Playlists page: Title A-Z/Z-A, shortest/longest first, and a 'group by channel' toggle that groups items by channel (A-Z) and applies the chosen sort within each group. Applying a sort reorders the items and persists via the existing reorder API. The item order is now an undoable value: drag, sort and grouping all go through it, so every change is reversible via undo/redo buttons and Ctrl/Cmd+Z / Ctrl+Y (Ctrl+Shift+Z). Built on two reusable pieces, not playlist-specific: - useUndoable<T> — a generic past/present/future snapshot hook (set/undo/redo/reset + canUndo/canRedo), ref-backed so callbacks are stable and never see a stale snapshot; onApply runs the side effect (here: persist order). - UndoToolbar — undo/redo buttons + keyboard shortcuts, plain props so any undo source can use it. Undo history is reset only when the item set actually changes (different playlist or add/remove), so a refetch confirming our own reorder doesn't wipe it; membership changes (remove) clear history since they aren't reorder-undoable. Trilingual.
45 lines
2.5 KiB
JSON
45 lines
2.5 KiB
JSON
{
|
||
"title": "Wiedergabelisten",
|
||
"watchLater": "Später ansehen",
|
||
"syncYoutube": "Von YouTube synchronisieren",
|
||
"syncedToast": "{{count}} Wiedergabelisten von YouTube synchronisiert",
|
||
"syncFailed": "Synchronisierung von YouTube fehlgeschlagen",
|
||
"ytReadonly": "Von YouTube synchronisiert — Änderungen werden zurücksynchronisiert",
|
||
"noneYet": "Noch keine Wiedergabelisten",
|
||
"newPlaylist": "Neue Liste…",
|
||
"itemCount_one": "{{count}} Video",
|
||
"itemCount_other": "{{count}} Videos",
|
||
"pickOne": "Wähle links eine Liste.",
|
||
"loading": "Wird geladen…",
|
||
"empty": "Diese Liste ist leer — füge Videos aus dem Feed hinzu.",
|
||
"playAll": "Alle abspielen",
|
||
"delete": "Löschen",
|
||
"rename": "Umbenennen",
|
||
"confirmDelete": "Die Wiedergabeliste „{{name}}“ löschen? Kann nicht rückgängig gemacht werden.",
|
||
"addToPlaylist": "Zur Wiedergabeliste hinzufügen",
|
||
"exportToYoutube": "Zu YouTube exportieren",
|
||
"pushToYoutube": "Mit YouTube synchronisieren",
|
||
"unsynced": "Nicht synchronisierte Änderungen",
|
||
"pushTitle": "Mit YouTube synchronisieren",
|
||
"pushConfirm": "Synchronisieren",
|
||
"pushPlanCreate": "Eine neue YouTube-Wiedergabeliste mit {{count}} Videos erstellen? (~{{units}} Kontingenteinheiten; heute noch {{left}} übrig.)",
|
||
"pushPlanUpdate": "Auf YouTube aktualisieren — {{insert}} hinzufügen, {{del}} entfernen, {{reorder}} neu anordnen? (~{{units}} Kontingenteinheiten; heute noch {{left}} übrig.)",
|
||
"pushDiverged": "{{count}} Video(s), die derzeit auf YouTube sind, werden entfernt.",
|
||
"pushNoQuota": "Nicht genug YouTube-Kontingent für heute ({{left}}) für diese Synchronisierung (~{{units}} benötigt). Versuche es morgen erneut.",
|
||
"pushUpToDate": "Bereits mit YouTube synchronisiert.",
|
||
"pushDone": "Mit YouTube synchronisiert ✓",
|
||
"pushPartial": "Synchronisiert, aber {{count}} Element(e) wurden übersprungen.",
|
||
"pushFailed": "Synchronisierung mit YouTube fehlgeschlagen.",
|
||
"deleteOnYoutubeTitle": "Auch auf YouTube löschen?",
|
||
"deleteOnYoutubeMsg": "„{{name}}“ auch aus deinem YouTube-Konto löschen? Wähle „Nur hier“, um sie auf YouTube zu behalten.",
|
||
"deleteOnYoutubeConfirm": "Auf YouTube löschen",
|
||
"deleteHereOnly": "Nur hier",
|
||
"deleteYtFailed": "Löschen auf YouTube fehlgeschlagen; nur hier entfernt.",
|
||
"sortLabel": "Sortierung",
|
||
"sortManual": "Eigene Reihenfolge",
|
||
"sortTitleAsc": "Titel A–Z",
|
||
"sortTitleDesc": "Titel Z–A",
|
||
"sortDurAsc": "Kürzeste zuerst",
|
||
"sortDurDesc": "Längste zuerst",
|
||
"groupByChannel": "Nach Kanal gruppieren"
|
||
}
|