Skip to content

1.0.37

Choose a tag to compare

@github-actions github-actions released this 11 May 10:38
· 376 commits to main since this release

Overview

This release brings the social layer of TrueTunes to life — playlists you can build and share, a personal Favourites playlist, full user profile pages, a People row on the home screen, and the recently played feature that kicked the branch off.


Playlists

Full playlist system backed by Azure Cosmos DB with optimistic concurrency control on all mutations.

What's new:

  • Create private or public playlists from the home page, profile page, or track context menu
  • Add tracks to any playlist via right-click → "Add to playlist" submenu
  • Drag to reorder tracks within a playlist (owner and members)
  • Remove tracks (owner only)
  • Rename a playlist by clicking the title (owner only, Escape correctly cancels without saving)
  • Delete a playlist with a confirmation step (owner only, Favourites protected server-side)
  • Upload a custom cover image (owner only, stored in Azure Blob with 20-year SAS URL)
  • Join / leave public playlists
  • Playlist detail page (/playlist/:id) with full track table, member list, and metadata
  • Playlist cards on home and profile pages sort Favourites first, then by most recently updated
  • Track count on cards updates immediately after adding or removing tracks

Server functions added: playlist-create, playlist-get, playlist-list, playlist-add-track, playlist-remove-track, playlist-reorder, playlist-update, playlist-delete, playlist-join, playlist-upload-image

Infrastructure: new playlists Cosmos container and playlist-images blob container provisioned via ARM template.


Favourites

  • Each user gets a Favourites playlist auto-created on first login (favourites-ensure Azure Function)
  • Heart button in the player bar toggles the currently playing track in/out of Favourites with optimistic UI update and rollback on failure
  • "Add to Favourites" option in the track context menu
  • Favourites playlist is pinned to the top of all playlist lists and cannot be deleted or made public
  • useFavourite hook with isFavourited state derived from the cached playlist, full add/remove with rollback

User Profiles

  • Profile pages at /profile/:userName showing top tracks, top artists, top albums, playlists, and Queuedle rank
  • Click any user name anywhere in the app (track rows, playlist "added by", leaderboard) to go to their profile
  • Profile picture upload (owner only) stored in Azure Blob
  • Own profile shows a Sign Out link and all playlists (owned + joined); other profiles show only public playlists
  • useUserProfile and useUserStats hooks; profile-get and profile-upload-image Azure Functions

People Row (Home Page)

  • New "People" section on the home page showing all users who have queued tracks
  • Circular profile picture avatars (gradient initial fallback), sorted by most recently queued
  • Current user excluded server-side
  • Click through to any user's profile page
  • users-list Azure Function queries the events container with GROUP BY to get last-queued timestamp per user, joins with profiles for images
  • Skeleton loaders while fetching; hover scale animation with correct overflow handling

Recently Played

  • "Recently Played — Last 7 Days" section on the home page with artist and album grids
  • User picker dropdown (gated behind completing today's Queuedle to prevent spoilers)
  • recently-played Azure Function aggregates Cosmos events per user
  • Drag artists/albums from recently played into the queue

Context Menu

  • Right-click any track anywhere in the app to get: Play next, Add to queue, Add to Favourites, Add to playlist (submenu), View [user]'s profile
  • ContextMenuProvider wraps the app shell; useTrackContextMenu hook exposes showTrackMenu to any component
  • CreatePlaylistDialog inline in the context menu flow for creating a new playlist and immediately adding the track to it

Toast Notifications

  • ToastProvider / useToast for non-blocking error feedback on all mutation failures (add track, remove track, rename, delete, join, reorder, upload image)

Code quality & bug fixes

  • IPC error propagation fix: all 7 mutation IPC handlers now use a playlistFetch helper that throws on non-2xx responses, so renderer catch blocks and optimistic rollbacks actually fire on server errors (previously handlers returned { error: '...' } silently)
  • Escape cancels rename correctly: fixed blur-after-Escape race condition in PlaylistPanel rename input using a cancelRename ref
  • Track count invalidation: all add/remove callsites now invalidate the playlist list query so card track counts update immediately
  • Shared utilities: getPlaylistColor, createDragGhost, PlaylistCard component, and @keyframes skelPulse extracted to canonical locations, eliminating duplication across HomePanel, ProfilePanel, and PlaylistPanel
  • useEnsureFavourites retry logic now works correctly (handler throws instead of returning error object)
  • handleJoin in PlaylistPanel had no error handling — fixed with contextual toast
  • useFavourite toggle invalidates the playlist list query after success so Favourites track count stays accurate

Test coverage

New test files:

  • usePlaylists.test.ts — useFavourite add/remove happy paths, rollback paths, useEnsureFavourites stale time and retry config
  • PlaylistPanel.test.tsx — handleRemoveTrack optimistic update and rollback
  • CreatePlaylistDialog.test.tsx — create without track, create with pending track, server error inline display
  • TopNav.test.tsx — updated to match new profile chip navigation behaviour

722 tests passing, full typecheck clean.