Skip to content

feat(web): copy source tracks when duplicating a playlist#14321

Open
dylanjeffers wants to merge 4 commits into
claude/add-tracks-by-urlfrom
claude/duplicate-copy-tracks
Open

feat(web): copy source tracks when duplicating a playlist#14321
dylanjeffers wants to merge 4 commits into
claude/add-tracks-by-urlfrom
claude/duplicate-copy-tracks

Conversation

@dylanjeffers
Copy link
Copy Markdown
Contributor

Summary

Promotes the duplicate-playlist flow (#14319) from metadata-only to a true duplicate that also copies every track from the source playlist.

Stacked on #14320#14319#14318.

Implementation

  • New DUPLICATE_PLAYLIST action (in cacheCollectionsActions) carries { sourcePlaylistId, formFields, trackIds, source, isAlbum }.
  • New duplicatePlaylistSaga orchestrates the full sequence:
    1. Dispatches the existing createPlaylist / createAlbum action with initTrackId = trackIds[0] so the first track lands as part of the create flow.
    2. take()s the resulting CREATE_PLAYLIST_REQUESTED to learn the new playlist id.
    3. For tracks 2..N, sequentially dispatches addTrackToPlaylist(trackId, newPlaylistId, { silent: true }) with a 30 ms inter-dispatch delay so each saga's optimistic update is visible to the next iteration.
    4. Emits a single summary toast ("Duplicated playlist with N tracks").
  • Modal update: DuplicatePlaylistModal now dispatches DUPLICATE_PLAYLIST and surfaces the actual track count to the user ("All N tracks will be copied to the new playlist") instead of the previous "tracks not copied" note.

Test plan

  • Duplicate a playlist with 0 tracks → new playlist created, summary toast reads "Duplicated playlist"
  • Duplicate a playlist with 1 track → that track lands via the initTrackId path; toast "Duplicated playlist with 1 track"
  • Duplicate a playlist with N tracks (try 5 and 30) → all N tracks present in the new playlist in the same order; toast "Duplicated playlist with N tracks"
  • Customize title / description / artwork switches still work and the duplicate respects each choice
  • New playlist is private by default and the user is routed to it
  • No per-track "Added track to playlist" toasts during the copy (silent option is honored)

🤖 Generated with Claude Code

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 15, 2026

⚠️ No Changeset found

Latest commit: 24e8a3b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

dylanjeffers and others added 3 commits May 15, 2026 11:09
The "New" button in the playlist library sidebar (and the empty-state nav
link) used to immediately create a playlist named "New Playlist" and route
the user into the edit page. Replace that one-shot dispatch with a Create
Playlist modal that lets the user set a title, optional description, and
optional artwork before the playlist is created.

- New `CreatePlaylistModal` slice via `createModal` helper, wired into
  the modals reducer/state.
- New `CreatePlaylistModal` component (Harmony Modal + TextInput +
  TextArea + UploadArtwork) reusing the existing `resizeImage` pipeline.
- The sidebar "New" popup item and the empty-library nav link both open
  the modal instead of dispatching `createPlaylist` directly.
- Playlists still default to private (enforced by the existing
  `optimisticallySavePlaylist` saga) and the saga still routes the user
  to the new playlist page after creation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a "Duplicate Playlist" secondary action to the sidebar's New (+)
popup menu. Opens a modal where the user pastes any public Audius
playlist URL, sees a preview of the source playlist (title, description,
cover art), and toggles per-field switches to customize what should
differ in the copy. The duplicated playlist is created as private by
default (enforced by the existing optimisticallySavePlaylist saga).

Scope:
- Metadata-only duplication for now. Tracks are not copied — a follow-up
  PR will support full duplicate including track contents. The modal
  surfaces this with a helper line so users know they need to add tracks
  separately.
- Reuses the existing createPlaylist saga: when artwork is not
  customized, we pass the source playlist's cover_art_sizes CID through
  so the saga reuses the cover instead of treating it as a new upload.

Implementation:
- New `DuplicatePlaylistModal` Redux modal slice (createModal helper).
- New `DuplicatePlaylistModal` component (Harmony Modal + TextInput +
  Switch + TextArea + Artwork + UploadArtwork).
- Resolves pasted URL → permalink via `getPathFromPlaylistUrl`, then
  loads the source via `useCollectionByPermalink`.
- Wires "Duplicate Playlist" into `CreatePlaylistLibraryItemButton`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a new "Add Tracks by URL" affordance to the owner action row on
playlist detail pages. Clicking it opens a modal where the user pastes
Audius track links — line, comma, or tab separated — and submits to
batch-add them to the current playlist. Albums and DDEX-imported
collections are intentionally excluded.

Implementation details:
- New `AddTracksByUrlModal` Redux modal slice (createModal helper) wired
  through types/parentSlice/reducers/index.
- New `AddTracksByUrlModal` component:
  - Parses pasted text into a deduped list of permalinks via
    `getPathFromTrackUrl`.
  - Resolves them in one round-trip via `sdk.tracks.getBulkTracks`.
  - Filters out tracks already in the playlist, enforces a 100-track
    cap, and reports invalid/unresolved/duplicate/over-limit counts in a
    single summary toast.
  - Dispatches `addTrackToPlaylist` per track with a 30 ms gap so each
    saga's optimistic update reads the previous one's state.
- `addTrackToPlaylist` now accepts `{ silent: true }` so the per-track
  "Added track to playlist" toast can be suppressed during batch adds;
  default behavior (single-track adds elsewhere) is unchanged.
- New `IconLink` button in `OwnerActionButtons` opens the modal,
  prefilled with the current collection id. Hidden for albums and
  DDEX-imported collections.

Scope notes:
- Resolution uses the existing `addTrackToPlaylist` saga path
  (sequential dispatches with small delay). A future PR could replace
  this with a dedicated `addTracksToPlaylistBatch` saga that issues a
  single SDK update for cleaner semantics on large pastes.
- Larger track-curation features from the spec (multi-select, range
  select, undo/redo, copy selected URLs, multi-row drag) are deferred
  to follow-up PRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers force-pushed the claude/add-tracks-by-url branch from 6116b0b to 2a42659 Compare May 15, 2026 18:11
Promotes the duplicate-playlist flow from metadata-only to a true
duplicate that also copies every track from the source.

- New DUPLICATE_PLAYLIST action carries the source playlist id, the
  composed form fields, the full source track id list, and an isAlbum
  flag.
- New duplicatePlaylistSaga drives the full sequence: it dispatches the
  existing createPlaylist / createAlbum saga with the first source
  track as initTrackId, takes() the resulting CREATE_PLAYLIST_REQUESTED
  to learn the new playlist id, then sequentially dispatches
  addTrackToPlaylist({ silent: true }) for every remaining track with
  a small inter-dispatch delay so each saga sees the previous
  optimistic update. Closes with a single summary toast.
- DuplicatePlaylistModal now dispatches DUPLICATE_PLAYLIST and exposes
  the actual track count to the user ("All N tracks will be copied")
  instead of the previous "tracks not copied" note.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dylanjeffers dylanjeffers force-pushed the claude/duplicate-copy-tracks branch from 12936a4 to 24e8a3b Compare May 15, 2026 18:11
@github-actions
Copy link
Copy Markdown
Contributor

🌐 Web preview ready

Preview URL: https://audius-web-preview-pr-14321.audius.workers.dev

Unique preview for this PR (deployed from this branch).
Workflow run

@dylanjeffers dylanjeffers force-pushed the claude/add-tracks-by-url branch from 2a42659 to b85318e Compare May 21, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant