Commit Graph
25 Commits
Author SHA1 Message Date
Admin 1320b12699 web-player: TypeScript helpers (partial)
Add src/lib/actions/pressable.ts and clickOutside.ts (Svelte actions;
role/tabindex stay static in markup for SSR accessibility, the action
only adds click + Enter/Space) and src/lib/toggle.svelte.ts
(createToggle), used by playlists.svelte.ts and queuePanel.svelte.ts.

format.ts: adds plural(n, one, many); migrates the repo's 15 manual
pluralizations, unifying them to lowercase (visible diff in
Playlists, Home, liked, Explore).

player.svelte.ts: adds toQueueItem, isQueueCurrent, playAllOrToggle,
playShuffled; renames addToQueue -> playNextItem (the old name was
misleading: it inserts next, not at the end). Migrates the 5 places
that repeated the isCurrentQueue/playAll pattern (album, playlist,
liked, mix, Home). Simplifies liked.svelte.ts and recentlyPlayed.ts
with object spread instead of rebuilding every field by hand.

navigation.svelte.ts: adds searchHref (migrates the duplicated
buildHref from TopBar and Explore) and appNavLinks (added; its
adoption in Sidebar/TabsBar is left for a later pass, as noted
there).

menus.svelte.ts: createTrackMenu() replaces the manual context-menu
state (contextMenu + contextMenuStateFor + addToQueue) in Home,
Explore and Mix.

Deliberately left pending: removing tracks.ts's TrackTarget wrapper
and its 8 accessors is deferred — it's the riskiest change in the
plan, touches types across Home/Explore/Mix/menus, and couldn't be
visually verified without Docker this session.

Verified with npm run check/build.
2026-09-20 23:01:13 +02:00
Admin aa20e70671 web-player: buttons (Button, IconButton, PlayButton)
Button: subtle variants (primary/secondary, left unchanged per the
user's call), glass (formerly secondaryOnGlow, with its own
font-normal), accent, strong (cta-strong/ink, replacing the `!`
overrides on the Home hero), danger. Uses the --color-btn* tokens
instead of bg-[var(--mf-btn-...)]. Radius unified to rounded-control.

IconButton: adds shape (square/round), size (xs/sm/md/lg), tone
(muted/subtle/plain), pressed (aria-pressed + text-accent),
href/reload (links), surface (permanent background + hover to
surface-hover instead of the generic `hover` alias, which matched
surface-2 and gave no contrast).

New PlayButton: a single place for the play/pause SVGs, strong/glass
variants, as="span" for non-interactive overlays. Replaces
TransportControls' main button, the MixTile overlay, and the "Top
result" circle in Explore.

Migrated to IconButton: close queue, "Create playlist" (Sidebar),
Like (TrackInfo, with pressed), queue (PlayerExtras), back (TopBar),
login (MobileHeader), and the row actions in tables (remove/add, size
xs). BackLink uses size-icon-sm and drops a duplicate hover.

Decision (not blocking): remove TopBar's decorative "forward" button
and PlayerExtras' decorative AlignJustify icon (visually dead code).
TransportControls' buttons (shuffle/prev/next/repeat) are
deliberately left unmigrated: they currently have no background or
hit-box of their own, and IconButton always applies a fixed-size
box — migrating them would have added a visible hover pill that
couldn't be verified without Docker this session.

Verified with npm run check/build.
2026-09-20 22:48:08 +02:00
Admin 58eb670fed web-player: unify Artwork and Avatar
Add src/lib/components/ui/Artwork.svelte and Avatar.svelte (B.3) and
migrate every use of Cover, PlaylistArt, MixArt and ArtistAvatar
(Sidebar, Queue, TrackInfo, TrackContextMenu, AlbumContextMenu,
TrackTitleCell, AlbumCard, PlaylistCard, MixTile, AlbumHeader,
PlaylistHeader, Home, Explore, mix, user profile, TopBar,
MobileHeader). Remove the 4 old components.

Artwork: size decides both dimension and radius automatically
(cover-*/radius tokens from the earlier token pass); fallback chain
is src -> mosaic (>=4 trackIds) -> first cover -> placeholder,
cascading if each step fails (previously split across 3 components
with slightly different logic each). Adds a 'fill' size (aspect-square
w-full), not in the spec, needed for fluid grid cards until MediaCard
lands later.

TrackTitleCell's `coverSize` prop (free-form Tailwind classes)
becomes `size: 'sm'|'lg'`, delegating to Artwork. SearchResultRow
loses its `kind` prop and the per-type radius (now decided by
Artwork/Avatar).

Product decision (not blocking): remove the name under the profile
avatar on /u/[id] since it duplicated the CollectionHeader title.

Small radius/size deltas are documented in the plan's README
(auto-radius by size replaces ad-hoc classes; see table B.1.1/B.1.2).

Verified with npm run check/build; no authenticated visual QA (Docker
unavailable this session).
2026-09-20 22:39:05 +02:00
Admin 3f5e01f910 Update packages 2026-09-20 16:00:57 +02:00
Admin c14db5a711 Checkpoint web-player design-system refactor and backend track genre tagging
Advances the ongoing token/componentization cleanup (anchored player dock,
border-based panels instead of floating shadows, corrected light-mode
accent/gradient tokens) alongside in-progress backend support for track
genre tags.
2026-09-17 17:43:37 +02:00
Admin 5ae9955bd0 Remove YouTube integration from web-player; unify Home track rows
Drops every YouTube-backed route, proxy and type (external
albums/tracks, thumbnail proxy, youtube.ts) and simplifies
player/track/mix types to the local-only catalog now that the
backend contract dropped Source/ExternalId. Genre tiles on Explore
and "Populares esta semana" on Home stay as deliberate client-only
placeholders per product decision, just without the YouTube backing.

Also finishes the design-system unification pass: Home's three
hand-rolled track rows (Continuar escuchando, Playlist destacada,
Populares esta semana) now reuse the shared TrackTitleCell component
instead of duplicating cover+title+artist markup, and the orphaned
Rail.svelte (no importers) is removed.
2026-09-15 21:17:14 +02:00
Admin 5696683859 Fix light-mode regression and finish design-system cleanup
A code-review pass on the previous commit found a real bug: the explore
genre tiles used var(--mf-ink) as a decorative gradient endpoint, but that
token is meant for text-on-accent and flips to white in light mode,
turning the tiles solid white. Replaces it with a new, deliberately
theme-invariant --mf-tile-shade token (same category as --mf-cover-grad).

Also: raises CollectionHeader's meta-line contrast in light mode
(text-muted, ~3:1, to text-fg-2), makes its actions prop optional so
pages without conditional actions don't render an empty wrapper, moves
AccountMenu.svelte into $lib/components/ui/ per the repo's own
componentization rule, adds the aria-expanded TopBar's trigger was
missing relative to MobileHeader's, and migrates the profile page
(u/[id]/+page.svelte) onto CollectionHeader — a sixth duplicate of the
same header pattern that the previous commit touched but missed.
2026-09-15 18:06:37 +02:00
Admin f1756468bc Unify web-player design tokens and componentize collection headers
Migrates remaining one-off colors (bg-white/[N%], border-white/N, hardcoded
shadows/gradients) to the existing --mf-* tokens so light mode reacts
consistently everywhere, including a fix to --color-hover which was
hardcoded instead of pointing at --mf-surface-2. Extracts CollectionHeader
(album/playlist/mix/liked headers) and AccountMenu (TopBar/MobileHeader)
to remove five and two duplicated implementations respectively, and
normalizes inconsistent empty-state copy.
2026-09-15 17:53:47 +02:00
Admin 7861600081 Redesign explore search and inline top-bar search box
- Explore: replace per-kind colored badges/tints in search results
  with the app's neutral accent, add an always-visible Usuarios chip,
  and keep the top-result type label as plain text
- Move SearchBox into TopBar/MobileHeader as an inline debounced
  search form, dropping the standalone SearchBox component
- Sync design handoff artboards with the current search UI
2026-09-15 03:35:05 +02:00
Admin dc1ba89a6d Add likes, follows and playlist visibility; redesign web-player UI
Backend:
- New Likes feature (toggle/get liked tracks) and endpoints
- User follow/unfollow, listening stats, public user profile
- Playlist visibility (public/private) support
- Various auth and DTO/response adjustments to support the above

Frontend (web-player):
- New design system pass: theme tokens/mode (light/dark), glass menu,
  tabs bar, player dock/extras/queue components, mix tiles, artist link
- New routes: Liked, public user profile (/u/[id]), likes API proxy
- Search refactor: shared SearchBox component used by TopBar and
  MobileHeader (search now reachable on mobile), live results as you
  type instead of requiring Enter, dropped the "Buscando…" quick-result
  preview
- Removed now-unused components (MobileNav, CoverBadge, MixBentoTile,
  PlayPauseOverlay, SuggestionsTable, userDirectory)
- Design handoff reference docs added under web-player/design_handoff_musify_player
  and web-player/docs/design-system-refactor-plan.md
2026-09-14 23:42:45 +02:00
Admin 29a7fed6a5 Generalize YouTube-backed endpoints behind a source parameter
Removes the last YouTube-specific routes (/youtube/*) and merges them
into the general track/album/playlist endpoints, keyed by a `source`
string validated against TrackSource. This mirrors the earlier track
search merge for albums and playlist-track additions:

- GetAlbums now merges local albums with live YouTube Music search
  results, paginated via a youtubeContinuationToken, deduped against
  already-materialized ExternalAlbum rows.
- New GET /albums/external/{source}/{externalId} and
  GET /tracks/external/{source}/{externalId}/stream replace the
  YouTube-only equivalents.
- POST /playlists/{id}/tracks replaces the separate
  .../youtube-tracks endpoint, accepting an optional Source/ExternalId
  pair alongside TrackId.
- AlbumSearchItemResponse/AlbumsSearchResponse follow the same
  discriminated-union + trailing-HasNextPage-field pattern already
  used for track search, so HasNextPage stays a required field in the
  generated OpenAPI schema.
- Frontend routes renamed accordingly (/albums/youtube/[albumId] ->
  /albums/external/[source]/[externalId], etc.) with a single
  /api/thumbnail proxy replacing /api/youtube/thumbnail.

Musify.Api.Endpoints.YouTubeEndpoints and the standalone
SearchYouTubeAlbums query are removed as a result.
2026-09-10 15:03:36 +02:00
Admin 92a06a3c15 Combine track search with live YouTube Music results
GET /tracks now merges the local catalog page with a live YouTube Music
search (deduplicated against tracks already provisioned locally) whenever a
name filter is given, appending the YouTube hits after the local matches and
carrying a continuation token for further pages. Each item is tagged with its
source via the new TrackSearchItemResponse/TracksSearchResponse shapes,
wrapping the existing TrackApplicationResponse or a raw YouTubeSongResult so
neither type had to change.

GET /youtube/search is removed along with its now-unused handler; the
web-player's explore page, its /api/tracks proxy, and the YouTube filler
helper are updated to call the combined endpoint instead of hitting the two
separately.
2026-09-10 09:55:58 +02:00
Admin d867a60126 Changes 2026-08-18 14:38:00 +02:00
Admin f54ebec0eb Changes 2026-07-25 01:46:59 +02:00
Admin 6412a657e7 Changes 2026-07-24 18:54:31 +02:00
Admin 9132e67371 feat(web-player): rebuild Inicio and Buscar to the design handoff
Applies the handoff's layout and image shapes while keeping the current
Musify design system (Inter, colors, tokens) — no font or palette swap.

Inicio now stacks distinct shelves instead of repeated square grids:
recently played rows, a rail of recently listened albums with an "Álbum"
badge, a "Hecho para ti" bento of mixes, a rail of playlists with a
trailing dashed "Ver todas" tile, tall "Canciones nuevas" posters with a
"Nuevo" badge, a rail of circular top-artist avatars, and a recommended
rail. Buscar splits into Álbumes (square cards + badge), Usuarios (a
circular-avatar directory) and a flat Canciones list.

Top artists and the search user directory are filler data until the
backend exposes them. New shared pieces: Rail, CoverBadge, ArtistAvatar,
MixBentoTile. The orphaned TrackTile and MixCard are removed.
2026-07-22 04:40:14 +02:00
Admin 2f98982d83 feat: bring over the albums, explore and player work from the worktree
Moves the remaining uncommitted work: the home gets quick mixes and a
"Tus álbumes" shelf, saving a YouTube album now goes through
addYoutubeAlbumToPlaylistAction instead of the SaveYouTubeAlbum command,
and UserAlbum drops its unused ExternalId.

The mixes section keeps its current shape (no refresh action, no badge,
hidden when empty) rather than the older version the worktree carried.
2026-07-21 18:18:23 +02:00
Admin b75c97a696 feat(web-player): label each explore result with its kind 2026-07-21 18:13:46 +02:00
Admin 787664f97b feat(web-player): show the cover mosaic on the explore albums 2026-07-21 18:13:46 +02:00
Admin 62b0ab37a9 feat(web-player): page the album results and save YouTube albums
The albums section keeps a Ver más button while YouTube Music has another
page, fed by a new /api/youtube/albums route that forwards the continuation
token. The YouTube album page gains a save button that drops the whole album,
tracks included, into your library and takes you to it.
2026-07-20 20:49:56 +02:00
Admin 29c220a1cf feat(web-player): show YouTube Music albums in the explore search
The Albums chip now returns both your own albums and what YouTube Music has
for the term. A YouTube card opens a read-only album page with its cover,
tracklist and play button, and right-clicking a track still offers to add it
to a playlist through the existing menu.
2026-07-20 20:39:21 +02:00
Admin ed7fca5366 feat(web-player): filter the explore results with a chip group
Under the search box there are now three checkbox chips choosing what the page
shows. Songs keep the existing grid and Albums searches the albums by title;
Users is rendered disabled until there is something behind it.
2026-07-20 20:30:33 +02:00
Admin 9e4388332f perf(web-player): cut down the searches the explore page fires
Typing in the search box navigated on every pause, so single letters and
round-trips back to the same term each triggered a full YouTube search and a
new grid of covers. The debounce is longer, a term identical to the current
one no longer navigates, YouTube is only queried past a minimum length, and
the infinite scroll waits until the sentinel is closer before pulling a page.
2026-07-20 17:38:37 +02:00
Admin d4a66e4320 refactor(web-player): centralise styles and drop dead code
Styles: adds the scrim and on-art tokens so the black overlays and the
white marks drawn over artwork stop being raw tailwind colours, and
routes every component through the semantic layer instead of reaching
into the --mf-* palette. Renames --mf-accent-60, which was actually an
80% mix, to --mf-accent-soft, and removes the unused --mf-radius and
the --color-neutral-950 override.

Dead code: the root +layout.server.ts already redirects everything
except /login, so the anonymous branches in the home and explore loads
and the needsAuth empty state could never run. Deletes the unused
accentSoft helper, and stops exporting helpers nobody imports.

fmtTime and fmtDate move out of theme/color.ts into $lib/format.ts;
they are not colour concerns.

The accent animation now cancels its pending frame on teardown.
2026-07-20 14:35:45 +02:00
Admin 97daa13ebd refactor: rename frontend/ to web-player/ and format with prettier
Updates the compose build context, the Dockerfile header, the package
name and the docs. The compose service and container keep the name
frontend/musify-frontend, since nginx routes to http://frontend:3000.

The source files also carry the first prettier pass, so the rename and
the reformat land together for them.
2026-07-20 07:35:01 +02:00