fix: keep emoji selection visible during keyboard navigation

This commit is contained in:
2026-10-16 20:49:10 +02:00
parent cd2e3da330
commit ec32d31c8d
4 changed files with 53 additions and 3 deletions
@@ -51,6 +51,53 @@ import Testing
#expect(defaults.stringArray(forKey: "recentEmoji") == ["👩‍💻", matches[1].value])
}
@Test(arguments: [false, true], [false, true])
@MainActor func emojiKeyboardNavigationKeepsSelectionVisible(controlKeys: Bool, favorites: Bool) throws {
_ = NSApplication.shared
let suite = "ConjureEmojiScroll.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suite)!
let pasteboard = NSPasteboard.withUniqueName()
defer { defaults.removePersistentDomain(forName: suite); pasteboard.releaseGlobally() }
let favored = favorites ? Array(EmojiCatalog.all.suffix(3)) : []
defaults.set(favored.map(\.value), forKey: "favoriteEmoji")
let ordered = favored + EmojiCatalog.all.filter { emoji in !favored.contains { $0.value == emoji.value } }
let picker = EmojiPickerController(defaults: defaults, pasteboard: pasteboard)
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 750, height: 400),
styleMask: [.borderless], backing: .buffered, defer: false)
window.contentView = picker.view
picker.view.layoutSubtreeIfNeeded()
let scroll = try #require(picker.view.subviews.compactMap { $0 as? NSScrollView }.first)
let grid = try #require(scroll.documentView as? NSCollectionView)
func expectVisible() throws {
picker.copySelection()
let index = try #require(ordered.firstIndex { $0.value == pasteboard.string(forType: .string) })
let path = favorites && index >= favored.count
? IndexPath(item: index - favored.count, section: 1) : IndexPath(item: index, section: 0)
let frame = try #require(grid.collectionViewLayout?.layoutAttributesForItem(at: path)?.frame)
try #require(scroll.documentVisibleRect.contains(frame))
}
for down in [true, false] {
for _ in 0..<12 {
if controlKeys {
#expect(picker.handleControlKey(down ? "j" : "k"))
} else {
#expect(picker.handle(down ? #selector(NSResponder.moveDown(_:)) : #selector(NSResponder.moveUp(_:))))
}
try expectVisible()
}
}
for right in [true, false] {
for _ in 0..<80 {
if controlKeys {
#expect(picker.handleControlKey(right ? "l" : "h"))
} else {
#expect(picker.handle(right ? #selector(NSResponder.moveRight(_:)) : #selector(NSResponder.moveLeft(_:))))
}
try expectVisible()
}
}
}
@Test @MainActor func emojiActionsDefaultToPasteAndKeepCopyOnlyAvailable() throws {
_ = NSApplication.shared
let suite = "ConjureEmojiActions.\(UUID().uuidString)"