feat(web): inline edit mode on playlist detail page with staged Apply#14322
Open
dylanjeffers wants to merge 1 commit into
Open
feat(web): inline edit mode on playlist detail page with staged Apply#14322dylanjeffers wants to merge 1 commit into
dylanjeffers wants to merge 1 commit into
Conversation
|
This was referenced May 15, 2026
12936a4 to
24e8a3b
Compare
Brings playlist detail-page editing inline per the new UX spec. The
existing /edit route still works for advanced fields (audience,
price, genre, etc.), but the common metadata flow is now handled
directly on the detail page.
- New `PlaylistEditModeProvider` context holds the edit-mode flag,
the staged metadata draft, conflict status, and saving status. The
matching `usePlaylistEditMode` hook safely returns a no-op shape
when not inside the provider, so shared components stay
backwards-compatible.
- Wrapped the desktop CollectionPage in the provider and rendered a
sticky `PlaylistEditModeBar` at the page footer. The bar shows a
Discard / Apply pair when there are pending changes, a slim "no
changes yet" footer while in edit mode without changes, and a
conflict banner with a Reload action when the playlist was changed
remotely since edit mode started.
- The `EditButton` pencil in the owner action row now toggles inline
edit mode instead of routing to /edit (the legacy link is kept as
a fallback when no provider is mounted).
- CollectionHeader (desktop) renders an inline `TextInput` for the
title, a `TextArea` for the description, and a `Switch` for
visibility while in edit mode. Otherwise behavior is unchanged.
- Desktop Artwork supports inline upload (file picker) when edit
mode is on; the staged image previews immediately and is sent
through on Apply along with the metadata draft.
- Apply checks the collection's `updated_at` against the timestamp
captured when edit mode started; if it has advanced, the bar
flips to the conflict state and aborts the save.
- Success messages are specific ("Saved details", "Saved artwork",
or "Saved details and artwork") based on which fields the user
changed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10295c5 to
ba2fa57
Compare
Contributor
🌐 Web preview readyPreview URL: https://audius-web-preview-pr-14322.audius.workers.dev Unique preview for this PR (deployed from this branch). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings playlist detail-page editing inline per the new UX spec. The existing
/editroute still works for advanced fields (audience, price, genre, etc.), but the common metadata flow — title, description, visibility, artwork — is now handled directly on the detail page with a staged Apply / Discard model and remote-change conflict detection.Stacked on #14321 → #14320 → #14319 → #14318.
Implementation
PlaylistEditModeProvidercontext holdsisEditMode, the staged metadatadraft,hasChanges, savestatus(idle / saving / conflict), and aneditModeLoadedAttimestamp for conflict detection. The matchingusePlaylistEditModehook returns a no-op shape when not inside a provider so shared components likeCollectionHeaderstay backwards-compatible everywhere else they're used.CollectionPageis wrapped in the provider. A stickyPlaylistEditModeBarrenders at the page footer in three states:/edit. The legacy/editlink still works at the URL level and the button keeps the legacy behavior when no provider is mounted.TextInputfor title (with autoFocus on entering edit mode, 64-char max).TextAreafor description (1000-char max, grows, char counter).Switchfor visibility — checked = Public, unchecked = Hidden.resizeImagepipeline and previewed immediately; on Apply it's sent through as part of the edit payload.collection.updated_atto theeditModeLoadedAttimestamp captured when the user entered edit mode. Ifupdated_athas advanced, the bar flips to the conflict state and aborts — the user clicks Reload to get fresh data.Notes / scope
/editpage is intentionally kept; this PR doesn't remove or redirect it.Test plan
/editURL still loads the existing advanced editor.🤖 Generated with Claude Code