WIP: preserve source badge beside action rail
This commit is contained in:
@@ -54,7 +54,7 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
|
|||||||
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.
|
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.
|
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.
|
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`; on a narrow shelf, confirm 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.
|
||||||
|
|
||||||
## Copy And Paste
|
## Copy And Paste
|
||||||
|
|
||||||
|
|||||||
@@ -2320,7 +2320,8 @@ private final class AspectFillImageView: NSView {
|
|||||||
private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
||||||
private enum Metrics {
|
private enum Metrics {
|
||||||
static let dragThreshold: CGFloat = 4
|
static let dragThreshold: CGFloat = 4
|
||||||
static let actionRailHorizontalMargin: CGFloat = 12
|
static let actionRailBadgeGap: CGFloat = 8
|
||||||
|
static let actionRailLeadingMargin: CGFloat = 10
|
||||||
}
|
}
|
||||||
private enum Palette {
|
private enum Palette {
|
||||||
static let border = NSColor.separatorColor.withAlphaComponent(0.20).cgColor
|
static let border = NSColor.separatorColor.withAlphaComponent(0.20).cgColor
|
||||||
@@ -2942,7 +2943,7 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func fittedActionRailButtonSpecs(from specs: [ActionRailButtonSpec]) -> [ActionRailButtonSpec] {
|
private func fittedActionRailButtonSpecs(from specs: [ActionRailButtonSpec]) -> [ActionRailButtonSpec] {
|
||||||
let maximumWidth = layout.width - (Metrics.actionRailHorizontalMargin * 2)
|
let maximumWidth = maximumVisibleActionRailWidth
|
||||||
guard actionRailWidth(for: specs) > maximumWidth else { return specs }
|
guard actionRailWidth(for: specs) > maximumWidth else { return specs }
|
||||||
|
|
||||||
let moreSpec = ActionRailButtonSpec("ellipsis.circle", toolTip: "More", action: #selector(showMoreActionsFromActionRail(_:)))
|
let moreSpec = ActionRailButtonSpec("ellipsis.circle", toolTip: "More", action: #selector(showMoreActionsFromActionRail(_:)))
|
||||||
@@ -2980,6 +2981,22 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
+ actionRail.edgeInsets.right
|
+ actionRail.edgeInsets.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var maximumVisibleActionRailWidth: CGFloat {
|
||||||
|
layout.width
|
||||||
|
- Metrics.actionRailLeadingMargin
|
||||||
|
- layout.inset
|
||||||
|
- Metrics.actionRailBadgeGap
|
||||||
|
- headerBadgeSize
|
||||||
|
}
|
||||||
|
|
||||||
|
private var headerBadgeSize: CGFloat {
|
||||||
|
layout.isCompact ? 36 : 42
|
||||||
|
}
|
||||||
|
|
||||||
|
private var actionRailHeaderTopInset: CGFloat {
|
||||||
|
max(8, (layout.headerHeight - layout.actionRailHeight) / 2)
|
||||||
|
}
|
||||||
|
|
||||||
private func cardActionButton(
|
private func cardActionButton(
|
||||||
_ systemName: String,
|
_ systemName: String,
|
||||||
toolTip: String,
|
toolTip: String,
|
||||||
@@ -3018,7 +3035,7 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
|
|
||||||
private func updateActionRailVisibility() {
|
private func updateActionRailVisibility() {
|
||||||
actionRail.isHidden = !isSelected
|
actionRail.isHidden = !isSelected
|
||||||
headerBadgeView?.isHidden = isSelected
|
headerBadgeView?.isHidden = false
|
||||||
headerPinView?.isHidden = isSelected
|
headerPinView?.isHidden = isSelected
|
||||||
footerDetailLabel.isHidden = false
|
footerDetailLabel.isHidden = false
|
||||||
for button in actionRailButtons {
|
for button in actionRailButtons {
|
||||||
@@ -3199,9 +3216,18 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
footer.widthAnchor.constraint(equalTo: stack.widthAnchor)
|
footer.widthAnchor.constraint(equalTo: stack.widthAnchor)
|
||||||
])
|
])
|
||||||
contentView.addSubview(actionRail)
|
contentView.addSubview(actionRail)
|
||||||
|
let actionRailTrailingConstraint: NSLayoutConstraint
|
||||||
|
if let headerBadgeView {
|
||||||
|
actionRailTrailingConstraint = actionRail.trailingAnchor.constraint(
|
||||||
|
equalTo: headerBadgeView.leadingAnchor,
|
||||||
|
constant: -Metrics.actionRailBadgeGap
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
actionRailTrailingConstraint = actionRail.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12)
|
||||||
|
}
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
actionRail.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12),
|
actionRailTrailingConstraint,
|
||||||
actionRail.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 11)
|
actionRail.topAnchor.constraint(equalTo: contentView.topAnchor, constant: actionRailHeaderTopInset)
|
||||||
])
|
])
|
||||||
setSelected(false)
|
setSelected(false)
|
||||||
}
|
}
|
||||||
@@ -3264,8 +3290,8 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
labelStack.trailingAnchor.constraint(lessThanOrEqualTo: badge.leadingAnchor, constant: -12),
|
labelStack.trailingAnchor.constraint(lessThanOrEqualTo: badge.leadingAnchor, constant: -12),
|
||||||
badge.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -layout.inset),
|
badge.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -layout.inset),
|
||||||
badge.centerYAnchor.constraint(equalTo: header.centerYAnchor),
|
badge.centerYAnchor.constraint(equalTo: header.centerYAnchor),
|
||||||
badge.widthAnchor.constraint(equalToConstant: layout.isCompact ? 36 : 42),
|
badge.widthAnchor.constraint(equalToConstant: headerBadgeSize),
|
||||||
badge.heightAnchor.constraint(equalToConstant: layout.isCompact ? 36 : 42),
|
badge.heightAnchor.constraint(equalToConstant: headerBadgeSize),
|
||||||
separator.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: layout.inset),
|
separator.leadingAnchor.constraint(equalTo: header.leadingAnchor, constant: layout.inset),
|
||||||
separator.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -layout.inset),
|
separator.trailingAnchor.constraint(equalTo: header.trailingAnchor, constant: -layout.inset),
|
||||||
separator.bottomAnchor.constraint(equalTo: header.bottomAnchor),
|
separator.bottomAnchor.constraint(equalTo: header.bottomAnchor),
|
||||||
|
|||||||
@@ -366,17 +366,17 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Pin", "Collect", "Add to Stack", "Edit", "Preview", "Delete"])
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Pin", "Collect", "Add to Stack", "Edit", "Preview", "Delete"])
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 238)
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 238)
|
||||||
XCTAssertFalse(fixture.view.debugFirstCardFooterDetailIsHidden)
|
XCTAssertFalse(fixture.view.debugFirstCardFooterDetailIsHidden)
|
||||||
XCTAssertTrue(fixture.view.debugFirstCardHeaderBadgeIsHidden)
|
XCTAssertFalse(fixture.view.debugFirstCardHeaderBadgeIsHidden)
|
||||||
|
|
||||||
fixture.store.upsert(makeItem(kind: .file, text: "/tmp/report.txt", store: fixture.store))
|
fixture.store.upsert(makeItem(kind: .file, text: "/tmp/report.txt", store: fixture.store))
|
||||||
drainMainQueue()
|
drainMainQueue()
|
||||||
|
|
||||||
fixture.viewModel.selectFirstItem()
|
fixture.viewModel.selectFirstItem()
|
||||||
XCTAssertEqual(fixture.viewModel.visibleItems.first?.kind, .file)
|
XCTAssertEqual(fixture.viewModel.visibleItems.first?.kind, .file)
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Paste Plain Text", "Pin", "Collect", "Add to Stack", "Preview", "Open", "Reveal", "More"])
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Paste Plain Text", "Collect", "Add to Stack", "Preview", "Open", "More"])
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 294)
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 238)
|
||||||
XCTAssertFalse(fixture.view.debugFirstCardFooterDetailIsHidden)
|
XCTAssertFalse(fixture.view.debugFirstCardFooterDetailIsHidden)
|
||||||
XCTAssertTrue(fixture.view.debugFirstCardHeaderBadgeIsHidden)
|
XCTAssertFalse(fixture.view.debugFirstCardHeaderBadgeIsHidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCompactFileCardActionsFitInsideShelfWithOverflowMenu() {
|
func testCompactFileCardActionsFitInsideShelfWithOverflowMenu() {
|
||||||
@@ -387,9 +387,10 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||||
|
|
||||||
XCTAssertEqual(fixture.view.debugCardDensity, "compact")
|
XCTAssertEqual(fixture.view.debugCardDensity, "compact")
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Paste Plain Text", "Collect", "Add to Stack", "Preview", "Open", "More"])
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Paste Plain Text", "Collect", "Add to Stack", "Preview", "More"])
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 222)
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 196)
|
||||||
XCTAssertLessThanOrEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 240)
|
XCTAssertLessThanOrEqual(fixture.view.debugFirstCardVisibleActionRailWidth, 197)
|
||||||
|
XCTAssertFalse(fixture.view.debugFirstCardHeaderBadgeIsHidden)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardMenuTitles,
|
fixture.view.debugFirstCardMenuTitles,
|
||||||
["Paste", "Copy", "Paste Plain Text", "Copy Plain Text", "Rename...", "Add to Stack", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
["Paste", "Copy", "Paste Plain Text", "Copy Plain Text", "Rename...", "Add to Stack", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
|
|||||||
Reference in New Issue
Block a user