WIP: use readable card age text

This commit is contained in:
Akshay Kolli
2026-06-30 10:22:09 -07:00
parent 241596acb3
commit 74f42c4b02
3 changed files with 35 additions and 4 deletions

View File

@@ -56,6 +56,7 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
23. Resize or test on a narrow display and confirm the bottom shelf switches to compact cards that still show two recent clips cleanly. 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. 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. 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.
## Copy And Paste ## Copy And Paste

View File

@@ -4268,9 +4268,19 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
private static func relativeDateText(for date: Date) -> String { private static func relativeDateText(for date: Date) -> String {
let seconds = max(0, Int(Date().timeIntervalSince(date))) let seconds = max(0, Int(Date().timeIntervalSince(date)))
if seconds < 60 { return "Just now" } if seconds < 60 { return "Just now" }
if seconds < 3600 { return "\(seconds / 60)m ago" } if seconds < 3600 {
if seconds < 86400 { return "\(seconds / 3600)h ago" } let minutes = seconds / 60
if seconds < 604800 { return "\(seconds / 86400)d ago" } return "\(minutes) \(minutes == 1 ? "minute" : "minutes") ago"
return "\(seconds / 604800)w ago" }
if seconds < 86400 {
let hours = seconds / 3600
return "\(hours) \(hours == 1 ? "hour" : "hours") ago"
}
if seconds < 604800 {
let days = seconds / 86400
return "\(days) \(days == 1 ? "day" : "days") ago"
}
let weeks = seconds / 604800
return "\(weeks) \(weeks == 1 ? "week" : "weeks") ago"
} }
} }

View File

@@ -349,6 +349,26 @@ final class ClipboardPanelViewTests: XCTestCase {
XCTAssertEqual(fixture.view.debugFirstCardFooterDetailText, "17 characters") XCTAssertEqual(fixture.view.debugFirstCardFooterDetailText, "17 characters")
} }
func testCardHeaderUsesReadableRelativeAgeText() {
let fixture = makePanelFixture()
var item = makeTextItem("Readable age", store: fixture.store)
item.createdAt = Date().addingTimeInterval(-3 * 60)
fixture.store.upsert(item)
drainMainQueue()
fixture.window.contentView?.layoutSubtreeIfNeeded()
XCTAssertEqual(fixture.view.debugFirstCardHeaderSubtitle, "3 minutes ago")
fixture.viewModel.createCollection(named: "Age Stack", colorHex: "#FF3B30", selectAfterCreate: false)
fixture.viewModel.assignSelected(to: "Age Stack")
fixture.viewModel.selectCollection(named: "Age Stack")
drainMainQueue()
fixture.window.contentView?.layoutSubtreeIfNeeded()
XCTAssertEqual(fixture.view.debugFirstCardHeaderSubtitle, "Text - 3 minutes ago")
}
func testCollectionChipsExposeManagementMenuActions() { func testCollectionChipsExposeManagementMenuActions() {
let fixture = makePanelFixture() let fixture = makePanelFixture()
fixture.viewModel.createCollection(named: "Research Stack", colorHex: "#0A9EB8") fixture.viewModel.createCollection(named: "Research Stack", colorHex: "#0A9EB8")