v1.9.2
A focused fix release. The Charts page region selector was effectively non-functional — three structural bugs in how we read YouTube's chart response made a global event playlist appear regardless of region. Also includes a TrackTable migration that retires three hand-rolled DataTable pages and two related bug fixes.
Charts — bug report thanks 
@dmnmsc (#73)
- Events visually separated from country charts. YouTube injects a global event playlist (currently
"Coachella 2026: Daily Top 100 Songs"— same playlist ID worldwide) at position 0 of every country's response. Previously the Charts page default-loaded that slot, so picking a country still showed the global Coachella playlist. The Charts page now renders two stacked pill rows: aFeatured globally:strip for any shelves whose title carries a brand prefix (": "separator) and a country-charts row for the actual regional shelves. Country charts sort by priority —Top 100 Songs→Weekly Top Songs on Shorts→Trending 20→ rest — and the default-loaded pill is the first country chart, never an event. The event row hides automatically on narrow terminals (< 80 cols) to reclaim a row of vertical space. - Now reads
daily + weekly + videosfrom the API. Previously onlydailywas consulted, which silently dropped Spain (returns its data undervideos) and missed the Top 100 Songs / Top 100 Music Videos shelves underweeklyfor premium-supported regions. All three keys are now concatenated, then split into events vs charts. - Region picker expanded 17 → 68 entries. Global (
ZZ) is the new default. The list now mirrors YouTube's full advertised set (62 codes fromcountries.options) plus six historically-supported codes outside that list (Hong Kong, Malaysia, Singapore, Taiwan, Thailand, Vietnam). Settings default flipsregion = "GB"→region = "ZZ". - Locale-style configs auto-normalise. New
services/regions.normalise_region()helper strips locale tails —"ES-ES","en-GB","es_ES"now resolve to bare two-letter codes (ES,EN,ES) before hitting the API. YouTube's chart endpoint silently falls back to Global for any locale-shaped input; this prevents existing configs from being broken by that quirk. _clean_shelf_titleno longer strips brand prefixes. Coachella keeps its"Coachella 2026:"prefix on the pill so users can tell an event from a country chart at a glance.
New
- TrackTable migration on Queue, Liked Songs, Recently Played. Three pages migrated from raw
DataTabletoTrackTable. Gains right-click context menus, play indicators, column resize, filtering, and sorting — for free, on three pages that previously rolled those manually. Also retires theon_mouse_downright-click workaround we added to QueuePage in v1.9.0 (TrackTable already wires this up). Thanks
@wgordon17 (#74). [▶ Start Radio]button added to Liked Songs and Recently Played page headers — seeds a radio from 5 random tracks in the collection. Thanks
@wgordon17 (#74).- Shuffle-lock integration on Liked Songs and Recently Played — selecting a track applies the per-collection shuffle preference. Thanks

@wgordon17 (#74).
Fixes
- Radio track durations no longer show
--:--— ytmusicapi'sget_watch_playlistreturns duration under alengthkey (e.g."3:07"), notduration.extract_duration()now checksduration_seconds→duration→lengthin priority order. Thanks
@wgordon17 (#74). - Play history no longer stores duration as 0 —
log_playwas reading rawtrack.get("duration_seconds", 0), but normalized tracks store the value underduration. Switched toextract_duration()so the value is always correct regardless of source. Thanks
@wgordon17 (#74). - TrackTable Duration column no longer cut off on first paint. The row-label column (which carries the
▶playing indicator) reserves ~3 cells of width that the original column-fit pass didn't account for, so the rightmost column ("Duratio…") got pushed past the visible viewport on initial render._fill_title_columnnow runs afterload_tracksandappend_tracksso the Title column shrinks to compensate as soon as rows exist. - Sidebar gains a bottom separator under the Playlists panel — the existing top separator (a
Rulewidget between the pinned-nav block and the LibraryPanel) is now mirrored below the LibraryPanel, so thePlaylistspanel sits between two matching$border-coloured horizontal rules instead of just one.