ui: VOD sort dropdown with persisted key + locale labels

Adds a sort selector next to the existing filter input. Five modes:
newest first (default), oldest first, most viewed, longest first,
shortest first. Concrete user pain — long archives previously had no
way to find the longest stream, the most-watched, or to scroll back
to the start chronologically.

- vodSortKey state persisted to localStorage as
  twitch-vod-manager:vod-sort and validated against an enum on load,
  so an unknown stored value falls back to date_desc
- renderVodGridFromCurrentState now applies sortVods before
  filterVodsByQuery so the filter sees the sort and the match counter
  is consistent
- sortVods uses created_at timestamps for date sorts, view_count for
  views, and a tiny vodDurationToSeconds parser (XhYmZs) for duration
- DE + EN labels for both the "Sort:" prefix and the five option
  texts; refreshVodSortSelectLabels re-runs on language switch
- syncVodSortSelect on init preselects the persisted value before
  any VOD load so the dropdown reflects state immediately

Browser-default keyboard nav (arrows, type-ahead) covers keyboard
access for the select.

docs/IMPROVEMENT_LOG.md: Cycle 4 dated section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xRangerDE
2026-05-03 15:54:53 +02:00
co-authored by Claude Opus 4.7
parent 020f3dacf1
commit 832b606701
7 changed files with 157 additions and 5 deletions
+10 -2
View File
@@ -239,9 +239,17 @@
<div class="content">
<!-- VODs Tab -->
<div class="tab-content active" id="vodsTab">
<div class="vod-filter-row" style="display:flex; align-items:center; gap:8px; margin-bottom:12px;">
<input type="text" id="vodFilterInput" placeholder="Filter VODs..." oninput="onVodFilterInput()" style="flex:1; background: var(--bg-secondary,#222); border:1px solid var(--border-color,#444); border-radius:6px; padding:8px 12px; color: var(--text-primary,#fff); font-size:13px;">
<div class="vod-filter-row" style="display:flex; align-items:center; gap:8px; margin-bottom:12px; flex-wrap:wrap;">
<input type="text" id="vodFilterInput" placeholder="Filter VODs..." oninput="onVodFilterInput()" style="flex:1; min-width:180px; background: var(--bg-secondary,#222); border:1px solid var(--border-color,#444); border-radius:6px; padding:8px 12px; color: var(--text-primary,#fff); font-size:13px;">
<button id="vodFilterClearBtn" onclick="clearVodFilter()" title="Clear filter" style="display:none; background:transparent; border:1px solid var(--border-color,#444); border-radius:6px; padding:8px 12px; color: var(--text-secondary,#888); cursor:pointer;">x</button>
<label id="vodSortLabel" for="vodSortSelect" style="color: var(--text-secondary,#888); font-size:12px; margin-left:8px;">Sort:</label>
<select id="vodSortSelect" onchange="onVodSortChange()" style="background: var(--bg-secondary,#222); border:1px solid var(--border-color,#444); border-radius:6px; padding:7px 10px; color: var(--text-primary,#fff); font-size:13px;">
<option value="date_desc">Newest first</option>
<option value="date_asc">Oldest first</option>
<option value="views_desc">Most viewed</option>
<option value="duration_desc">Longest first</option>
<option value="duration_asc">Shortest first</option>
</select>
<span id="vodFilterCount" style="color: var(--text-secondary,#888); font-size:12px; min-width:80px;"></span>
</div>
<div class="vod-grid" id="vodGrid">