Skip to content

feat(browse): add a Home tab of container tiles - #46

Open
chamika wants to merge 3 commits into
mainfrom
feat/home-tab
Open

feat(browse): add a Home tab of container tiles#46
chamika wants to merge 3 commits into
mainfrom
feat/home-tab

Conversation

@chamika

@chamika chamika commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Replaces the flat list of root categories with a Home tab: one browse node whose children carry group titles, which the AAOS Media Center renders as a stack of titled rows.

Design canvas: https://claude.ai/code/artifact/93013a39-fa5b-4f94-a4b4-f0432426026d

Sections

# Section Tiles
1 Continue listening Saved queue, then the in-progress book. Each row hidden when there is nothing to resume.
2 Made for you Artist radios plus a favourites shuffle
3 New for you Recently added albums plus a shuffle of the newest 50 tracks
4 Jump back in Recently played albums
5 Mixes Genre mixes ranked by play count, plus a library shuffle

The rule that shapes it

Every tile must keep playing. A tile that ends after three minutes is a worse deal than the browse tree it replaced, so each one resolves to a long queue rather than a single track. Tapping a recently added album plays that album and then continues into the rest of the newest tracks.

Constraints worth knowing

  • Tile shape is not ours to choose. The content style API offers list, grid, category list, category grid, a per-item override and group titles, and nothing for artwork shape. The OEM owns it. The round tiles in the original design are not achievable, so the shuffle tiles use the category grid style, which gets their tintable icon drawn with margins.
  • AAOS never reports its grid column count, so row width comes from the display width alone: four tiles at 1200dp and above, three below. Sections are trimmed to that, and again after fetching, so a server that ignores a limit cannot wrap a section onto a second row.
  • Home is five live queries against an 8s browse timeout. They run in parallel and any one that fails or is slow is dropped. A partial Home beats an error screen in a moving car.
  • Existing users keep a stored category set that predates Home, so a one-time migration adds it at the front, dropping the last tab if that would exceed the four-tab cap.

Testing

Suite Result
:automotive:testDebugUnitTest 405 pass, 0 fail (was 362)
:automotive:connectedDebugAndroidTest 52 pass, 0 fail, 0 skipped

The 14 new end-to-end tests drive a real MediaBrowser, the same interface a head unit uses. They cover the section order, the one-row budget, that every tile expands into a multi-track queue, and that a new album keeps playing past its own last track.

Three real bugs surfaced during testing and are fixed here:

  • Home ran its queries on the main thread and died with a network-on-main-thread error. Ordinary browsing avoids this only because it goes through the repository's IO scope, which this path bypassed. Four of the five sections silently came back empty.
  • New for you trusted the server to honour its result limit.
  • The fake Jellyfin server never recorded routes it failed to model. Those answer 501, which the app turns into an empty section rather than an error, so a whole feature could vanish while every assertion still passed.

Not verified

Home has not been run against a real Jellyfin server. The instant mix, resume and play-history endpoints are exercised only against the simulated server, so the shape of real responses is unconfirmed.

https://claude.ai/code/session_01KzDujdziwxMegWj53xkqnr

Replaces the flat list of root categories with a Home tab: one browse node
whose children carry group titles, which the AAOS Media Center renders as a
stack of titled rows. Five sections, in order: Continue listening, Made for
you, New for you, Jump back in, Mixes.

The rule that shapes everything is that a tile must keep playing. A tile that
ends after three minutes is a worse deal than the browse tree it replaced, so
each one resolves to a long queue: the saved music queue, the in-progress
audiobook, an artist instant mix, a recently added album followed by the rest
of the newest 50 tracks, a genre shuffle, or a whole-library shuffle.

Tiles come back from the browser as a bare media id, so synthetic ones carry a
prefix the resolver dispatches on, the way SHUFFLE_GENRE: already did.

Notes on the constraints this had to fit:

- Tile shape is not ours to choose. The content style API offers list, grid,
  category list, category grid, a per-item override and group titles, and
  nothing for artwork shape — the OEM owns it. The shuffle tiles use the
  category grid style so their tintable icon is drawn with margins.
- AAOS never reports its grid column count, so row width comes from the display
  width alone: four tiles at 1200dp and above, three below. Sections are
  trimmed to that, and again after fetching, so a server that ignores a limit
  cannot wrap a section onto a second row.
- Home is five live queries against an 8s browse timeout, so they run in
  parallel and each is dropped if it fails or is slow. A partial Home beats an
  error screen in a moving car.
- Home is built on Dispatchers.IO explicitly. Browse futures resolve on the
  main dispatcher, and unlike ordinary browsing this path does not go through
  the repository's IO scope.
- Track-level queries are scoped to the music libraries so audiobook chapters,
  which are also AUDIO items, cannot leak into the music sections.
- Existing users keep a stored category set that predates Home, so a one-time
  migration adds it at the front and drops the last tab if that would exceed
  the four-tab cap.

The fake Jellyfin server gained resume and instant mix routes, and now records
routes it does not model. Those answer 501, which the app turns into an empty
section rather than an error, so without that a whole section could vanish
while every assertion still passed.

Claude-Session: https://claude.ai/code/session_01KzDujdziwxMegWj53xkqnr
On a head unit the shuffle tiles rendered as bare glyphs floating on the
system background while every neighbour in the row was a solid album square.
The category grid content style causes that by design: it draws a tinted icon
with margins and no tile behind it, which suits a small category icon and not a
tile sitting in a grid of artwork.

They are ordinary grid items now, with a full-bleed vector that carries its own
dark tile, so the host renders them exactly like album art.

The fill is a gradient and is lighter than it first looks it should be. The
AAOS media host paints its own background at about #181C1F, so the first
attempt at #1A1E20 — a colour from the app's own palette — measured two units
away from the background and was invisible on the device. Both values were
sampled from a screenshot rather than guessed.

Claude-Session: https://claude.ai/code/session_01KzDujdziwxMegWj53xkqnr
New Home tab that opens on what you were listening to and gets you playing in one tap

Full release notes:

- New Home tab, shown first when you open DashTune. It gathers everything into one screen instead of making you pick a category and drill down
- Continue listening picks up where you left off, with your last music queue and your current audiobook, each showing how far through you are
- Made for you offers instant mixes built around artists you like, plus a shuffle of all your favourites
- New for you shows recently added albums. Choosing one plays that album and then keeps going through the rest of your newest music, so it doesn't fall silent at the end
- Jump back in brings back the albums you played most recently
- Mixes shuffles the genres you listen to most, plus a shuffle of your whole library
- Every tile plays for a long stretch rather than a single track, so one tap is enough for a whole drive
- Home refreshes as you listen, so it looks different on your next trip
- Home is added to your tabs automatically when you update, and can be turned off in Settings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant