WIP: add visible clips to stack
This commit is contained in:
@@ -68,6 +68,7 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
|
|||||||
35. Confirm the shelf chrome uses one row with compact search, collection chips, and utility buttons; typing a search expands the search field without pushing cards out of view.
|
35. Confirm the shelf chrome uses one row with compact search, collection chips, and utility buttons; typing a search expands the search field without pushing cards out of view.
|
||||||
36. Copy a color swatch from a design tool and confirm it appears as a Color card, can be filtered with the Colors chip, and copies back as both a color and hex text.
|
36. Copy a color swatch from a design tool and confirm it appears as a Color card, can be filtered with the Colors chip, and copies back as both a color and hex text.
|
||||||
37. Copy a code snippet from an editor and confirm it appears as a Code card, remains visible in the Text chip, can be isolated with the Code chip or `type:code`, and copies back as plain text.
|
37. Copy a code snippet from an editor and confirm it appears as a Code card, remains visible in the Text chip, can be isolated with the Code chip or `type:code`, and copies back as plain text.
|
||||||
|
38. Filter to a few clips, right-click a card or the Stack chip, choose Add Visible Clips to Stack, and confirm only the visible clips are queued once in shelf order.
|
||||||
|
|
||||||
## Copy And Paste
|
## Copy And Paste
|
||||||
|
|
||||||
|
|||||||
@@ -575,6 +575,18 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate {
|
|||||||
stackChip.onPress = { [weak self] in
|
stackChip.onPress = { [weak self] in
|
||||||
self?.viewModel.selectStack()
|
self?.viewModel.selectStack()
|
||||||
}
|
}
|
||||||
|
stackChip.onAddVisibleToStack = { [weak self] in
|
||||||
|
self?.viewModel.addVisibleItemsToStack()
|
||||||
|
}
|
||||||
|
stackChip.onPasteStackNext = { [weak self] in
|
||||||
|
self?.viewModel.pasteNextStackItem()
|
||||||
|
}
|
||||||
|
stackChip.onCopyStackNext = { [weak self] in
|
||||||
|
self?.viewModel.copyNextStackItem()
|
||||||
|
}
|
||||||
|
stackChip.onClearStack = { [weak self] in
|
||||||
|
self?.viewModel.clearStack()
|
||||||
|
}
|
||||||
configureCollectionKeyboardNavigation(for: stackChip)
|
configureCollectionKeyboardNavigation(for: stackChip)
|
||||||
if viewModel.stackCount > 0 {
|
if viewModel.stackCount > 0 {
|
||||||
collectionChipOrder.append(stackChip)
|
collectionChipOrder.append(stackChip)
|
||||||
@@ -782,6 +794,9 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate {
|
|||||||
self?.viewModel.selectItem(at: selected)
|
self?.viewModel.selectItem(at: selected)
|
||||||
self?.viewModel.toggleSelectedStackMembership()
|
self?.viewModel.toggleSelectedStackMembership()
|
||||||
}
|
}
|
||||||
|
card.onAddVisibleToStack = { [weak self] in
|
||||||
|
self?.viewModel.addVisibleItemsToStack()
|
||||||
|
}
|
||||||
card.onPasteStackNext = { [weak self] in
|
card.onPasteStackNext = { [weak self] in
|
||||||
self?.viewModel.pasteNextStackItem()
|
self?.viewModel.pasteNextStackItem()
|
||||||
}
|
}
|
||||||
@@ -1630,6 +1645,14 @@ final class ClipboardPanelView: NSVisualEffectView, NSSearchFieldDelegate {
|
|||||||
stackChip.isSelected
|
stackChip.isSelected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var debugStackChipMenuTitles: [String] {
|
||||||
|
stackChip.debugMenuTitles
|
||||||
|
}
|
||||||
|
|
||||||
|
func debugAddVisibleClipsToStackFromStackChip() {
|
||||||
|
stackChip.debugPerformMenuItem(titled: "Add Visible Clips to Stack")
|
||||||
|
}
|
||||||
|
|
||||||
func debugPressStackChip() {
|
func debugPressStackChip() {
|
||||||
stackChip.onPress()
|
stackChip.onPress()
|
||||||
}
|
}
|
||||||
@@ -2110,6 +2133,10 @@ private final class CollectionChipView: NSView {
|
|||||||
var onSelectFirst: () -> Void = {}
|
var onSelectFirst: () -> Void = {}
|
||||||
var onSelectLast: () -> Void = {}
|
var onSelectLast: () -> Void = {}
|
||||||
var onDropItem: ((UUID) -> Void)?
|
var onDropItem: ((UUID) -> Void)?
|
||||||
|
var onAddVisibleToStack: (() -> Void)?
|
||||||
|
var onPasteStackNext: (() -> Void)?
|
||||||
|
var onCopyStackNext: (() -> Void)?
|
||||||
|
var onClearStack: (() -> Void)?
|
||||||
var onEdit: (() -> Void)?
|
var onEdit: (() -> Void)?
|
||||||
var onDelete: (() -> Void)?
|
var onDelete: (() -> Void)?
|
||||||
|
|
||||||
@@ -2308,13 +2335,45 @@ private final class CollectionChipView: NSView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func menu(for event: NSEvent) -> NSMenu? {
|
override func menu(for event: NSEvent) -> NSMenu? {
|
||||||
guard onEdit != nil || onDelete != nil else { return nil }
|
guard hasContextMenuActions else { return nil }
|
||||||
return contextMenu()
|
return contextMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var hasContextMenuActions: Bool {
|
||||||
|
onAddVisibleToStack != nil
|
||||||
|
|| onPasteStackNext != nil
|
||||||
|
|| onCopyStackNext != nil
|
||||||
|
|| onClearStack != nil
|
||||||
|
|| onEdit != nil
|
||||||
|
|| onDelete != nil
|
||||||
|
}
|
||||||
|
|
||||||
private func contextMenu() -> NSMenu {
|
private func contextMenu() -> NSMenu {
|
||||||
let menu = NSMenu(title: titleText)
|
let menu = NSMenu(title: titleText)
|
||||||
menu.autoenablesItems = false
|
menu.autoenablesItems = false
|
||||||
|
if onAddVisibleToStack != nil {
|
||||||
|
let item = NSMenuItem(title: "Add Visible Clips to Stack", action: #selector(addVisibleToStackFromMenu), keyEquivalent: "")
|
||||||
|
item.target = self
|
||||||
|
menu.addItem(item)
|
||||||
|
}
|
||||||
|
if onPasteStackNext != nil {
|
||||||
|
let item = NSMenuItem(title: "Paste Stack Next", action: #selector(pasteStackNextFromMenu), keyEquivalent: "")
|
||||||
|
item.target = self
|
||||||
|
menu.addItem(item)
|
||||||
|
}
|
||||||
|
if onCopyStackNext != nil {
|
||||||
|
let item = NSMenuItem(title: "Copy Stack Next", action: #selector(copyStackNextFromMenu), keyEquivalent: "")
|
||||||
|
item.target = self
|
||||||
|
menu.addItem(item)
|
||||||
|
}
|
||||||
|
if onClearStack != nil {
|
||||||
|
let item = NSMenuItem(title: "Clear Stack", action: #selector(clearStackFromMenu), keyEquivalent: "")
|
||||||
|
item.target = self
|
||||||
|
menu.addItem(item)
|
||||||
|
}
|
||||||
|
if (onEdit != nil || onDelete != nil) && !menu.items.isEmpty {
|
||||||
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
}
|
||||||
if onEdit != nil {
|
if onEdit != nil {
|
||||||
let item = NSMenuItem(title: "Edit Collection...", action: #selector(editFromMenu), keyEquivalent: "")
|
let item = NSMenuItem(title: "Edit Collection...", action: #selector(editFromMenu), keyEquivalent: "")
|
||||||
item.target = self
|
item.target = self
|
||||||
@@ -2331,6 +2390,22 @@ private final class CollectionChipView: NSView {
|
|||||||
return menu
|
return menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func addVisibleToStackFromMenu() {
|
||||||
|
onAddVisibleToStack?()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func pasteStackNextFromMenu() {
|
||||||
|
onPasteStackNext?()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func copyStackNextFromMenu() {
|
||||||
|
onCopyStackNext?()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func clearStackFromMenu() {
|
||||||
|
onClearStack?()
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func editFromMenu() {
|
@objc private func editFromMenu() {
|
||||||
onEdit?()
|
onEdit?()
|
||||||
}
|
}
|
||||||
@@ -2407,6 +2482,11 @@ private final class CollectionChipView: NSView {
|
|||||||
var debugMenuTitles: [String] {
|
var debugMenuTitles: [String] {
|
||||||
contextMenu().items.map { $0.isSeparatorItem ? "-" : $0.title }
|
contextMenu().items.map { $0.isSeparatorItem ? "-" : $0.title }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func debugPerformMenuItem(titled title: String) {
|
||||||
|
guard let item = contextMenu().items.first(where: { $0.title == title }) else { return }
|
||||||
|
_ = item.target?.perform(item.action, with: item)
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2502,6 +2582,7 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
var onPastePlainText: (Int) -> Void = { _ in }
|
var onPastePlainText: (Int) -> Void = { _ in }
|
||||||
var onCopyPlainText: (Int) -> Void = { _ in }
|
var onCopyPlainText: (Int) -> Void = { _ in }
|
||||||
var onToggleStack: (Int) -> Void = { _ in }
|
var onToggleStack: (Int) -> Void = { _ in }
|
||||||
|
var onAddVisibleToStack: () -> Void = {}
|
||||||
var onPasteStackNext: () -> Void = {}
|
var onPasteStackNext: () -> Void = {}
|
||||||
var onCopyStackNext: () -> Void = {}
|
var onCopyStackNext: () -> Void = {}
|
||||||
var onClearStack: () -> Void = {}
|
var onClearStack: () -> Void = {}
|
||||||
@@ -2882,6 +2963,7 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
}
|
}
|
||||||
addMenuItem("Rename...", action: #selector(renameFromMenu), to: menu)
|
addMenuItem("Rename...", action: #selector(renameFromMenu), to: menu)
|
||||||
addMenuItem(itemIsStacked ? "Remove from Stack" : "Add to Stack", action: #selector(toggleStackFromMenu), to: menu)
|
addMenuItem(itemIsStacked ? "Remove from Stack" : "Add to Stack", action: #selector(toggleStackFromMenu), to: menu)
|
||||||
|
addMenuItem("Add Visible Clips to Stack", action: #selector(addVisibleToStackFromMenu), to: menu)
|
||||||
if stackCount > 0 {
|
if stackCount > 0 {
|
||||||
addMenuItem("Paste Stack Next", action: #selector(pasteStackNextFromMenu), to: menu)
|
addMenuItem("Paste Stack Next", action: #selector(pasteStackNextFromMenu), to: menu)
|
||||||
addMenuItem("Copy Stack Next", action: #selector(copyStackNextFromMenu), to: menu)
|
addMenuItem("Copy Stack Next", action: #selector(copyStackNextFromMenu), to: menu)
|
||||||
@@ -3291,6 +3373,10 @@ private final class ClipboardItemCardView: NSView, NSDraggingSource {
|
|||||||
onToggleStack(index)
|
onToggleStack(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func addVisibleToStackFromMenu() {
|
||||||
|
onAddVisibleToStack()
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func toggleStackFromCornerButton() {
|
@objc private func toggleStackFromCornerButton() {
|
||||||
onSelect(index)
|
onSelect(index)
|
||||||
onToggleStack(index)
|
onToggleStack(index)
|
||||||
|
|||||||
@@ -308,6 +308,27 @@ final class ClipboardPanelViewModel {
|
|||||||
statusMessage = "Added to Stack"
|
statusMessage = "Added to Stack"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addVisibleItemsToStack() {
|
||||||
|
pruneStackItems()
|
||||||
|
guard !visibleItems.isEmpty else {
|
||||||
|
statusMessage = "No visible clips to stack"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let existingIDs = Set(stackItemIDs)
|
||||||
|
let newIDs = visibleItems
|
||||||
|
.map(\.id)
|
||||||
|
.filter { !existingIDs.contains($0) }
|
||||||
|
guard !newIDs.isEmpty else {
|
||||||
|
statusMessage = "Visible clips are already in Stack"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stackItemIDs.append(contentsOf: newIDs)
|
||||||
|
let noun = newIDs.count == 1 ? "clip" : "clips"
|
||||||
|
statusMessage = "Added \(newIDs.count) \(noun) to Stack"
|
||||||
|
}
|
||||||
|
|
||||||
func selectStack() {
|
func selectStack() {
|
||||||
guard !stackItemIDs.isEmpty else { return }
|
guard !stackItemIDs.isEmpty else { return }
|
||||||
selectedCollectionName = nil
|
selectedCollectionName = nil
|
||||||
|
|||||||
@@ -855,6 +855,36 @@ final class ClipboardPanelViewModelTests: XCTestCase {
|
|||||||
XCTAssertEqual(viewModel.statusMessage, "Cleared Stack")
|
XCTAssertEqual(viewModel.statusMessage, "Cleared Stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAddVisibleItemsToStackQueuesFilteredShelfInOrder() {
|
||||||
|
let settings = makeSettings()
|
||||||
|
let cacheService = makeCacheService()
|
||||||
|
let store = makeStore(settings: settings, cacheService: cacheService)
|
||||||
|
let olderNeedle = makeTextItem("older visible needle", createdAt: Date(timeIntervalSince1970: 100))
|
||||||
|
let hidden = makeTextItem("hidden meeting note", createdAt: Date(timeIntervalSince1970: 200))
|
||||||
|
let newerNeedle = makeTextItem("newer visible needle", createdAt: Date(timeIntervalSince1970: 300))
|
||||||
|
store.upsert(olderNeedle)
|
||||||
|
store.upsert(hidden)
|
||||||
|
store.upsert(newerNeedle)
|
||||||
|
store.flushPersistenceForTesting()
|
||||||
|
|
||||||
|
let viewModel = ClipboardPanelViewModel(store: store, settings: settings, cacheService: cacheService)
|
||||||
|
waitForVisibleItems(in: viewModel, count: 3)
|
||||||
|
viewModel.searchText = "needle"
|
||||||
|
|
||||||
|
XCTAssertEqual(viewModel.visibleItems.map(\.id), [newerNeedle.id, olderNeedle.id])
|
||||||
|
|
||||||
|
viewModel.addVisibleItemsToStack()
|
||||||
|
XCTAssertEqual(viewModel.stackCount, 2)
|
||||||
|
XCTAssertEqual(viewModel.statusMessage, "Added 2 clips to Stack")
|
||||||
|
|
||||||
|
viewModel.selectStack()
|
||||||
|
XCTAssertEqual(viewModel.visibleItems.map(\.payload), ["newer visible needle", "older visible needle"])
|
||||||
|
|
||||||
|
viewModel.addVisibleItemsToStack()
|
||||||
|
XCTAssertEqual(viewModel.stackCount, 2)
|
||||||
|
XCTAssertEqual(viewModel.statusMessage, "Visible clips are already in Stack")
|
||||||
|
}
|
||||||
|
|
||||||
func testIgnoreSelectedSourceAppAddsPreciseCaptureRule() {
|
func testIgnoreSelectedSourceAppAddsPreciseCaptureRule() {
|
||||||
let settings = makeSettings()
|
let settings = makeSettings()
|
||||||
let cacheService = makeCacheService()
|
let cacheService = makeCacheService()
|
||||||
|
|||||||
@@ -500,7 +500,7 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
XCTAssertEqual(fixture.view.debugFirstCardHeaderBadgeFrame.maxY, 220, accuracy: 0.5)
|
XCTAssertEqual(fixture.view.debugFirstCardHeaderBadgeFrame.maxY, 220, accuracy: 0.5)
|
||||||
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", "Add Visible Clips to Stack", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,7 +899,7 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardMenuTitles,
|
fixture.view.debugFirstCardMenuTitles,
|
||||||
["Paste", "Copy", "Rename...", "Add to Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
["Paste", "Copy", "Rename...", "Add to Stack", "Add Visible Clips to Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
)
|
)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardCollectionMenuTitles,
|
fixture.view.debugFirstCardCollectionMenuTitles,
|
||||||
@@ -933,7 +933,7 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardMenuTitles,
|
fixture.view.debugFirstCardMenuTitles,
|
||||||
["Paste", "Copy", "Show in Clipboard", "Rename...", "Add to Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
["Paste", "Copy", "Show in Clipboard", "Rename...", "Add to Stack", "Add Visible Clips to Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
)
|
)
|
||||||
|
|
||||||
fixture.view.debugShowFirstCardInClipboard()
|
fixture.view.debugShowFirstCardInClipboard()
|
||||||
@@ -953,7 +953,7 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
|
|
||||||
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", "Add Visible Clips to Stack", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
)
|
)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardCaptureRuleMenuTitles,
|
fixture.view.debugFirstCardCaptureRuleMenuTitles,
|
||||||
@@ -973,7 +973,7 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
fixture.view.debugFirstCardMenuTitles,
|
fixture.view.debugFirstCardMenuTitles,
|
||||||
["Paste", "Copy", "Rename...", "Remove from Stack", "Paste Stack Next", "Copy Stack Next", "Clear Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
["Paste", "Copy", "Rename...", "Remove from Stack", "Add Visible Clips to Stack", "Paste Stack Next", "Copy Stack Next", "Clear Stack", "Edit", "Quick Look", "Pin", "Add to Collection", "Capture Rules", "-", "Open", "Reveal in Finder", "-", "Delete"]
|
||||||
)
|
)
|
||||||
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Pin", "Collect", "Edit", "Preview", "Delete"])
|
XCTAssertEqual(fixture.view.debugFirstCardVisibleActionLabels, ["Paste", "Copy", "Pin", "Collect", "Edit", "Preview", "Delete"])
|
||||||
XCTAssertEqual(fixture.view.debugStackCornerLabels, ["Remove from Stack"])
|
XCTAssertEqual(fixture.view.debugStackCornerLabels, ["Remove from Stack"])
|
||||||
@@ -1046,6 +1046,51 @@ final class ClipboardPanelViewTests: XCTestCase {
|
|||||||
XCTAssertEqual(fixture.view.debugStackChipCount, 0)
|
XCTAssertEqual(fixture.view.debugStackChipCount, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testStackChipMenuAddsVisibleShelfToQueue() {
|
||||||
|
let fixture = makePanelFixture()
|
||||||
|
var older = makeTextItem("Older batch stack item", store: fixture.store)
|
||||||
|
older.createdAt = Date(timeIntervalSince1970: 100)
|
||||||
|
older.lastUsedAt = older.createdAt
|
||||||
|
var middle = makeTextItem("Middle batch stack item", store: fixture.store)
|
||||||
|
middle.createdAt = Date(timeIntervalSince1970: 200)
|
||||||
|
middle.lastUsedAt = middle.createdAt
|
||||||
|
var newest = makeTextItem("Newest batch stack item", store: fixture.store)
|
||||||
|
newest.createdAt = Date(timeIntervalSince1970: 300)
|
||||||
|
newest.lastUsedAt = newest.createdAt
|
||||||
|
fixture.store.upsert(older)
|
||||||
|
fixture.store.upsert(middle)
|
||||||
|
fixture.store.upsert(newest)
|
||||||
|
drainMainQueue()
|
||||||
|
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||||
|
|
||||||
|
fixture.viewModel.selectItem(at: 0)
|
||||||
|
fixture.viewModel.toggleSelectedStackMembership()
|
||||||
|
drainMainQueue()
|
||||||
|
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||||
|
|
||||||
|
XCTAssertTrue(fixture.view.debugStackChipIsVisible)
|
||||||
|
XCTAssertEqual(fixture.view.debugStackChipCount, 1)
|
||||||
|
XCTAssertEqual(
|
||||||
|
fixture.view.debugStackChipMenuTitles,
|
||||||
|
["Add Visible Clips to Stack", "Paste Stack Next", "Copy Stack Next", "Clear Stack"]
|
||||||
|
)
|
||||||
|
|
||||||
|
fixture.view.debugAddVisibleClipsToStackFromStackChip()
|
||||||
|
drainMainQueue()
|
||||||
|
fixture.window.contentView?.layoutSubtreeIfNeeded()
|
||||||
|
|
||||||
|
XCTAssertEqual(fixture.view.debugStackChipCount, 3)
|
||||||
|
XCTAssertEqual(fixture.view.debugStatusText, "Added 2 clips to Stack")
|
||||||
|
|
||||||
|
fixture.view.debugPressStackChip()
|
||||||
|
drainMainQueue()
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
fixture.viewModel.visibleItems.map(\.payload),
|
||||||
|
["Newest batch stack item", "Middle batch stack item", "Older batch stack item"]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func testCollectionMenuOffersExistingCustomCollections() {
|
func testCollectionMenuOffersExistingCustomCollections() {
|
||||||
let fixture = makePanelFixture()
|
let fixture = makePanelFixture()
|
||||||
var existing = makeTextItem("Existing client note", store: fixture.store)
|
var existing = makeTextItem("Existing client note", store: fixture.store)
|
||||||
|
|||||||
Reference in New Issue
Block a user