From 8920cad499210a4ddae20ad0f2b84feaaaddbf7c Mon Sep 17 00:00:00 2001 From: Laurent Date: Sat, 30 May 2026 13:02:50 +0200 Subject: [PATCH] feat: add TrackContextMenuModifier SwiftUI view modifier --- Music/Views/TrackContextMenuModifier.swift | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Music/Views/TrackContextMenuModifier.swift diff --git a/Music/Views/TrackContextMenuModifier.swift b/Music/Views/TrackContextMenuModifier.swift new file mode 100644 index 0000000..0e2ef10 --- /dev/null +++ b/Music/Views/TrackContextMenuModifier.swift @@ -0,0 +1,48 @@ +import SwiftUI + +// Attaches a context menu matching the track table's right-click menu. +// No-ops silently when track or config is nil so callers can pass optionals freely. +struct TrackContextMenuModifier: ViewModifier { + let track: Track? + let config: TrackContextMenuConfig? + + func body(content: Content) -> some View { + if let track, let config { + content.contextMenu { + if let lastPlaylistName = config.lastUsedPlaylistName, + let onAddToLastPlaylist = config.onAddToLastPlaylist { + Button("Add to \(lastPlaylistName)") { + onAddToLastPlaylist(track) + } + Divider() + } + + if !config.playlists.isEmpty { + Menu("Add to Playlist") { + ForEach(config.playlists) { playlist in + Button(playlist.name) { + config.onAddToPlaylist(track, playlist) + } + } + } + } + + if config.selectedPlaylist != nil, + let onRemoveFromPlaylist = config.onRemoveFromPlaylist { + Divider() + Button("Remove from Playlist") { + onRemoveFromPlaylist(track) + } + } + } + } else { + content + } + } +} + +extension View { + func trackContextMenu(track: Track?, config: TrackContextMenuConfig?) -> some View { + modifier(TrackContextMenuModifier(track: track, config: config)) + } +}