WIP: keep selected clip visible in shelf
This commit is contained in:
@@ -566,11 +566,32 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate {
|
||||
}
|
||||
|
||||
private func updateSelection() {
|
||||
var selectedCard: ClipboardItemCardView?
|
||||
for (index, card) in cardViews.enumerated() {
|
||||
card.setSelected(index == viewModel.selectedIndex)
|
||||
let selected = index == viewModel.selectedIndex
|
||||
card.setSelected(selected)
|
||||
if selected {
|
||||
selectedCard = card
|
||||
}
|
||||
}
|
||||
|
||||
if let selectedCard {
|
||||
scrollCardIntoView(selectedCard)
|
||||
}
|
||||
}
|
||||
|
||||
private func scrollCardIntoView(_ card: NSView) {
|
||||
guard scrollView.documentView === itemsStack else { return }
|
||||
guard card.window != nil else { return }
|
||||
scrollView.layoutSubtreeIfNeeded()
|
||||
itemsStack.layoutSubtreeIfNeeded()
|
||||
|
||||
let frame = card.convert(card.bounds, to: itemsStack)
|
||||
let paddedFrame = frame.insetBy(dx: -Metrics.cardSpacing, dy: 0)
|
||||
itemsStack.scrollToVisible(paddedFrame)
|
||||
scrollView.reflectScrolledClipView(scrollView.contentView)
|
||||
}
|
||||
|
||||
private func updateStatus(_ message: String) {
|
||||
let text: String
|
||||
if !message.isEmpty {
|
||||
@@ -846,6 +867,18 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate {
|
||||
cardViews.map(\.debugHeaderBadgeSymbol)
|
||||
}
|
||||
|
||||
var debugSelectedCardFrameInDocument: NSRect {
|
||||
guard viewModel.selectedIndex >= 0, viewModel.selectedIndex < cardViews.count else {
|
||||
return .zero
|
||||
}
|
||||
let card = cardViews[viewModel.selectedIndex]
|
||||
return card.convert(card.bounds, to: itemsStack)
|
||||
}
|
||||
|
||||
var debugCardRailVisibleRect: NSRect {
|
||||
scrollView.contentView.bounds
|
||||
}
|
||||
|
||||
var debugFirstCardMenuTitles: [String] {
|
||||
cardViews.first?.debugMenuTitles ?? []
|
||||
}
|
||||
|
||||
@@ -243,6 +243,38 @@ final class ClipboardPanelViewTests: XCTestCase {
|
||||
XCTAssertTrue(fixture.view.debugCustomCollectionTitles.contains("Product References"))
|
||||
}
|
||||
|
||||
func testSelectionScrollsCardRailToKeepSelectedCardVisible() {
|
||||
let fixture = makePanelFixture()
|
||||
fixture.window.setFrame(NSRect(x: 0, y: 0, width: 620, height: 520), display: true)
|
||||
|
||||
for index in 0..<8 {
|
||||
fixture.store.upsert(makeTextItem("Scrollable clipboard item \(index)", store: fixture.store))
|
||||
drainMainQueue()
|
||||
}
|
||||
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||
|
||||
fixture.viewModel.selectFirstItem()
|
||||
drainMainQueue()
|
||||
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||
XCTAssertLessThanOrEqual(fixture.view.debugCardRailVisibleRect.minX, 1)
|
||||
|
||||
fixture.viewModel.selectItem(at: fixture.viewModel.visibleItems.count - 1)
|
||||
drainMainQueue()
|
||||
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||
|
||||
let visibleRect = fixture.view.debugCardRailVisibleRect
|
||||
let selectedFrame = fixture.view.debugSelectedCardFrameInDocument
|
||||
XCTAssertGreaterThan(visibleRect.minX, 0)
|
||||
XCTAssertLessThanOrEqual(selectedFrame.minX, visibleRect.maxX)
|
||||
XCTAssertGreaterThanOrEqual(visibleRect.maxX + 1, selectedFrame.maxX)
|
||||
|
||||
fixture.viewModel.selectItem(at: 0)
|
||||
drainMainQueue()
|
||||
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||
|
||||
XCTAssertLessThanOrEqual(fixture.view.debugCardRailVisibleRect.minX, 1)
|
||||
}
|
||||
|
||||
func testFilteredEmptyStateNamesCurrentCollection() {
|
||||
let fixture = makePanelFixture()
|
||||
fixture.store.upsert(makeTextItem("Only text exists", store: fixture.store))
|
||||
|
||||
Reference in New Issue
Block a user