From 40da0200c606bbd5bc0c10d47d3a6b22a487e722 Mon Sep 17 00:00:00 2001 From: Akshay Kolli Date: Tue, 30 Jun 2026 10:39:33 -0700 Subject: [PATCH] WIP: hide empty collection count pills --- docs/SMOKE_TEST.md | 19 +++++++++--------- .../clipbored/views/ClipboardPanelView.swift | 20 +++++++++++++++++++ .../ClipboardPanelViewTests.swift | 4 ++++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/docs/SMOKE_TEST.md b/docs/SMOKE_TEST.md index 3586335..e1515b3 100644 --- a/docs/SMOKE_TEST.md +++ b/docs/SMOKE_TEST.md @@ -49,15 +49,16 @@ Use this checklist before a release or after changes to panel, pasteboard, setti 16. Return to Clipboard, select a card, use its Collect button to choose Client Work, and confirm the Client Work chip count increases. 17. Select the Client Work chip and confirm the rail filters to assigned items, cards use the Client Work name/color in their headers, and the collection/color/assignment persists after quitting and reopening ClipBored. 18. Right-click the Client Work chip, choose Edit Collection..., rename it, change its color, and confirm the chip and assigned card headers update. -19. Right-click a media, file, link, PDF, audio, or text card, choose Rename..., give it a title, and confirm the card title and search results use the custom title while paste/copy still uses the original payload. -20. Double-click an item and confirm it attempts to paste or falls back to copy without creating a duplicate history entry. -21. Right-click a card, use Capture Rules to ignore its source app, copy from that app again, and confirm the new item is skipped. -22. Drag an unassigned card onto the renamed collection chip and confirm the chip count increases and the card appears when that collection is selected. -23. Resize or test on a narrow display and confirm the bottom shelf switches to compact cards that still show two recent clips cleanly. -24. Select a file, rich text, or URL card and confirm the selected-card rail exposes `Paste Plain Text`, the corner source/kind badge remains visible, and on a narrow shelf secondary actions collapse behind `More` instead of overflowing the card. -25. Confirm card footers do not show `Unknown` for clips without a source app, and confirm used clips show their usage count beside the source app. -26. Confirm card headers use readable relative ages such as `3 minutes ago` or `2 hours ago`, including when viewing a named collection. -27. Confirm the selected card shows a green corner Stack control, the action rail does not duplicate Stack, and clips added to Stack keep a visible corner indicator when selection moves away. +19. Confirm collection chips with 0 clips do not show a visible count pill, while chips with clips still show their counts. +20. Right-click a media, file, link, PDF, audio, or text card, choose Rename..., give it a title, and confirm the card title and search results use the custom title while paste/copy still uses the original payload. +21. Double-click an item and confirm it attempts to paste or falls back to copy without creating a duplicate history entry. +22. Right-click a card, use Capture Rules to ignore its source app, copy from that app again, and confirm the new item is skipped. +23. Drag an unassigned card onto the renamed collection chip and confirm the chip count increases and the card appears when that collection is selected. +24. Resize or test on a narrow display and confirm the bottom shelf switches to compact cards that still show two recent clips cleanly. +25. Select a file, rich text, or URL card and confirm the selected-card rail exposes `Paste Plain Text`, the corner source/kind badge remains visible, and on a narrow shelf secondary actions collapse behind `More` instead of overflowing the card. +26. Confirm card footers do not show `Unknown` for clips without a source app, and confirm used clips show their usage count beside the source app. +27. Confirm card headers use readable relative ages such as `3 minutes ago` or `2 hours ago`, including when viewing a named collection. +28. Confirm the selected card shows a green corner Stack control, the action rail does not duplicate Stack, and clips added to Stack keep a visible corner indicator when selection moves away. ## Copy And Paste diff --git a/sources/clipbored/views/ClipboardPanelView.swift b/sources/clipbored/views/ClipboardPanelView.swift index 6a4b726..0048c01 100644 --- a/sources/clipbored/views/ClipboardPanelView.swift +++ b/sources/clipbored/views/ClipboardPanelView.swift @@ -1493,6 +1493,11 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate { return ClipboardSortMode.allCases.compactMap { collectionButtons[$0]?.count } } + var debugCollectionCountLabelHiddenStates: [Bool] { + updateCollectionButtons() + return ClipboardSortMode.allCases.compactMap { collectionButtons[$0]?.debugCountLabelIsHidden } + } + var debugCollectionChipAccessibilityLabels: [String] { updateCollectionButtons() return ClipboardSortMode.allCases.compactMap { collectionButtons[$0]?.accessibilityLabel() } @@ -1565,6 +1570,11 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate { return viewModel.collectionNames.compactMap { customCollectionButtons[$0]?.count } } + var debugCustomCollectionCountLabelHiddenStates: [Bool] { + updateCollectionButtons() + return viewModel.collectionNames.compactMap { customCollectionButtons[$0]?.debugCountLabelIsHidden } + } + var debugCustomCollectionColorHexes: [String: String] { Dictionary(uniqueKeysWithValues: viewModel.collectionNames.map { name in (name, ClipboardCollectionVisuals.hexString(for: collectionColor(forCollectionNamed: name))) @@ -2109,6 +2119,7 @@ private final class CollectionChipView: NSView { ? NSColor.controlAccentColor.withAlphaComponent(0.16) : NSColor.labelColor.withAlphaComponent(0.07) ).cgColor + updateCountLabelVisibility() updateAccessibility() updateChrome() } @@ -2138,9 +2149,14 @@ private final class CollectionChipView: NSView { func setCount(_ count: Int) { self.count = count countLabel.stringValue = count > 999 ? "999+" : "\(count)" + updateCountLabelVisibility() updateAccessibility() } + private func updateCountLabelVisibility() { + countLabel.isHidden = count == 0 + } + private func updateAccessibility() { let noun = count == 1 ? "clip" : "clips" let selectedText = isSelected ? "selected, " : "" @@ -2291,6 +2307,10 @@ private final class CollectionChipView: NSView { isKeyboardFocused } + var debugCountLabelIsHidden: Bool { + countLabel.isHidden + } + func debugDropItem(_ itemID: UUID) { onDropItem?(itemID) } diff --git a/tests/clipboredtests/ClipboardPanelViewTests.swift b/tests/clipboredtests/ClipboardPanelViewTests.swift index 656f8c8..a19a720 100644 --- a/tests/clipboredtests/ClipboardPanelViewTests.swift +++ b/tests/clipboredtests/ClipboardPanelViewTests.swift @@ -223,6 +223,7 @@ final class ClipboardPanelViewTests: XCTestCase { fixture.window.contentView?.layoutSubtreeIfNeeded() XCTAssertEqual(fixture.view.debugCollectionChipAcceptsFirstResponder, Array(repeating: true, count: ClipboardSortMode.allCases.count)) + XCTAssertEqual(fixture.view.debugCollectionCountLabelHiddenStates, Array(repeating: true, count: ClipboardSortMode.allCases.count)) XCTAssertEqual(fixture.view.debugCollectionChipAccessibilityLabels.first, "Clipboard, selected, 0 clips") XCTAssertTrue(fixture.view.debugFocusCollectionChip(.links)) @@ -326,6 +327,7 @@ final class ClipboardPanelViewTests: XCTestCase { XCTAssertEqual(fixture.viewModel.statusMessage, "Created Research Stack") XCTAssertEqual(fixture.view.debugCustomCollectionTitles, ["Research Stack"]) XCTAssertEqual(fixture.view.debugCustomCollectionCounts, [0]) + XCTAssertEqual(fixture.view.debugCustomCollectionCountLabelHiddenStates, [true]) XCTAssertEqual(fixture.view.debugSelectedCollectionTitle, "Research Stack") XCTAssertEqual(fixture.view.debugVisibleCardCount, 0) XCTAssertEqual(fixture.view.debugEmptyStateText?.title, "No clips in Research Stack") @@ -624,6 +626,7 @@ final class ClipboardPanelViewTests: XCTestCase { XCTAssertEqual(fixture.viewModel.visibleItems.count, 6) XCTAssertEqual(ClipboardSortMode.allCases.map { fixture.viewModel.collectionCount(for: $0) }, [6, 6, 2, 1, 1, 1, 1, 1]) XCTAssertEqual(fixture.view.debugCollectionCounts, [6, 6, 2, 1, 1, 1, 1, 1]) + XCTAssertEqual(fixture.view.debugCollectionCountLabelHiddenStates, Array(repeating: false, count: ClipboardSortMode.allCases.count)) } func testCollectionRailShowsAssignedCollections() { @@ -642,6 +645,7 @@ final class ClipboardPanelViewTests: XCTestCase { XCTAssertEqual(fixture.view.debugCustomCollectionTitles, ["Useful Links", "Important Notes", "Client Work"]) XCTAssertEqual(fixture.view.debugCustomCollectionCounts, [1, 1, 1]) + XCTAssertEqual(fixture.view.debugCustomCollectionCountLabelHiddenStates, [false, false, false]) fixture.viewModel.selectCollection(named: "Useful Links") drainMainQueue()