From d06a25da2c802d4ee4279dedfe52e160969b62cf Mon Sep 17 00:00:00 2001 From: Natalie Date: Tue, 30 Jun 2026 01:49:36 -0400 Subject: [PATCH] =?UTF-8?q?feat(adult):=20=E2=9C=A8=20add=20Select=20all?= =?UTF-8?q?=20/=20None=20buttons=20to=20the=20clip=20checklist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The goon collection clip list is a multi-select checklist but only had "Queue all fresh" — no way to tick or clear the whole set in one tap. Add "All" and "None" buttons that operate on the currently-shown clips, so with a filter active they select/deselect just the matches. Each disables when it would be a no-op (everything already queued / nothing queued). Co-Authored-By: Claude Opus 4.8 (1M context) --- Sources/TVAnarchy/GoonCollectionView.swift | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Sources/TVAnarchy/GoonCollectionView.swift b/Sources/TVAnarchy/GoonCollectionView.swift index bae1efb..f538a71 100644 --- a/Sources/TVAnarchy/GoonCollectionView.swift +++ b/Sources/TVAnarchy/GoonCollectionView.swift @@ -98,6 +98,20 @@ struct GoonCollectionView: View { .background(.quaternary.opacity(0.4), in: RoundedRectangle(cornerRadius: 8)) HStack(spacing: 10) { + Button { selectAllShown() } label: { + Label("All", systemImage: "checkmark.circle") + } + .controlSize(.small) + .disabled(shown.isEmpty || shown.allSatisfy { playlist.isQueued(path: $0.path) }) + .help(filter.isEmpty ? "Select every clip" : "Select every clip matching the filter") + + Button { selectNoneShown() } label: { + Label("None", systemImage: "circle") + } + .controlSize(.small) + .disabled(shown.allSatisfy { !playlist.isQueued(path: $0.path) }) + .help(filter.isEmpty ? "Deselect every clip" : "Deselect every clip matching the filter") + Button { queueAllFresh() } label: { Label("Queue all fresh", systemImage: "plus.rectangle.on.rectangle") } @@ -270,6 +284,21 @@ struct GoonCollectionView: View { } } + /// Queue every currently-shown clip (respects the active filter, so "All" while + /// filtered selects just the matches). + private func selectAllShown() { + for c in shown where !playlist.isQueued(path: c.path) { + playlist.addToQueue(id: c.path, title: c.title, path: c.path) + } + } + + /// Deselect every currently-shown clip (respects the active filter). + private func selectNoneShown() { + for c in shown where playlist.isQueued(path: c.path) { + playlist.removeFromQueue(path: c.path) + } + } + private func clearQueued() { for c in queued { playlist.removeFromQueue(path: c.path) } }