Skip to content

feat: drag and drop tracks onto sidebar playlists#363

Open
tsibog wants to merge 8 commits into
sozercan:mainfrom
tsibog:pr/drag-drop-playlist
Open

feat: drag and drop tracks onto sidebar playlists#363
tsibog wants to merge 8 commits into
sozercan:mainfrom
tsibog:pr/drag-drop-playlist

Conversation

@tsibog

@tsibog tsibog commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

Adds drag-and-drop of tracks onto playlists in the sidebar. Any track row (search results, history, home sections, playlist detail, etc.) can be dragged onto an owned playlist in the sidebar to add it. The target playlist highlights while dragging over it, and a brief success badge confirms the drop.

AI Prompt (Optional)

🤖 AI Prompt Used
Developed interactively with Claude Code across multiple sessions; the original
initiating prompt was not preserved. Gist: "Add drag and drop so I can drag any
track row onto a playlist in the sidebar to add it to that playlist. Only owned
playlists should accept drops, show visual feedback while hovering a valid
target, and confirm success."

AI Tool: Claude Code

Type of Change

  • ✨ New feature (non-breaking change that adds functionality)

Related Issues

Changes Made

  • Every rendered Song is a drag source (via the existing Transferable conformance), attached at the shared wrappers rather than per view: playlist track rows, HoverObservingRow (search, history, artist pages, top songs), and HomeSectionItemCard song cards (home, explore, charts, moods, new releases)
  • .dropDestination(for: Song.self, action:isTargeted:) on owned sidebar playlist rows; drops call YTMusicClient.addSongToPlaylist
  • Drag-over highlight on the targeted playlist row; transient success badge after a completed drop
  • Dropping onto Liked Music (Collection row or pinned LM playlist) likes the song instead — LM is the auto-playlist where membership means "liked", so drops route through SongLikeStatusManager (optimistic, broadcasts so like buttons update everywhere, rollback on failure)
  • Error handling with user-facing feedback when the add fails

Testing

  • Unit tests pass (swift test --skip KasetUITests) — 1774 passed, 148 suites
  • Manual testing performed — dragged tracks from search/history/playlist views onto sidebar playlists
  • UI tested on macOS 26+

Checklist

  • My code follows the project's style guidelines
  • I have run swiftlint --strict && swiftformat .
  • I have added tests that prove my fix/feature works (view-layer only; no service changes)
  • New and existing unit tests pass locally
  • I have updated documentation if needed
  • I have checked for any performance implications
  • My changes generate no new warnings

Screenshots

kaset-drag-drop-pr363.mp4

Additional Notes

View-layer only: no API or model changes. The drop path reuses the existing add-to-playlist client call (and the existing like flow for Liked Music).

Daniel Andersson added 2 commits July 11, 2026 00:56
- Song rows and cards are drag sources everywhere a Song is rendered:
  playlist track rows, HoverObservingRow (search, history, artist pages,
  top songs), and HomeSectionItemCard song cards (home, explore, charts,
  moods, new releases)
- .dropDestination(for:action:isTargeted:) on owned sidebar playlists,
  ignores albums
- error handling with do/catch + success/error haptic feedback
Visual feedback for drag-and-drop to playlist sidebar:
- playlist rows get a brand-accent tinted highlight + bounce icon
  while a track is dragged over them (albums excluded)
- green checkmark badge flashes on the row for ~900ms after a
  successful drop

KasetSidebarRow gains isDropTargeted (default false, backwards
compatible).
@tsibog
tsibog force-pushed the pr/drag-drop-playlist branch from 23e4c70 to 182eed5 Compare July 10, 2026 22:57
Liked Music is the LM auto-playlist: membership means liked, so
edit_playlist does not apply. Drops route through SongLikeStatusManager
so like buttons update everywhere. Both the Collection row and a pinned
LM playlist row accept drops; shared drop handling extracted.
@tsibog

tsibog commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 40e52941ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/Kaset/Views/Sidebar.swift Outdated
Daniel Andersson and others added 3 commits July 11, 2026 16:17
Deepen LibraryMutationActions with a single addSong(_:to:) entry owning
LM-vs-editable routing, cache invalidation, and logging; return AddSongOutcome
for callers to map to feedback. Sidebar drop + add-to-playlist menu now converge
on it, so the "adding to Liked Music means liking" rule lives in one place.

Add PlaylistDropTarget value type classifying the target once (folding the VL
browse-id prefix). Eligibility and routing read the same classifier, fixing a
latent bug where a VLLM-pinned Liked Music row passed eligibility then misrouted
to addSongToPlaylist and failed.
Replace copy-pasted .draggable at HoverObservingRow, HomeSectionItemCard, and
playlist track rows with one .songDraggable modifier — the single place a shared
drag preview would live. Fixes HomeSectionItemCard branch ordering that silently
left play-action song cards non-draggable.
@tsibog

tsibog commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 6d506594a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# Conflicts:
#	Tests/KasetTests/LibraryMutationActionsTests.swift
@tsibog
tsibog force-pushed the pr/drag-drop-playlist branch from e341b45 to f334553 Compare July 13, 2026 09:41
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