feat: restyle emoji picker with sectioned tiles

This commit is contained in:
Valdemar Lorenzen
2026-10-21 11:47:50 +02:00
parent abdaa70c0d
commit 81cb5c5dfb
4 changed files with 173 additions and 53 deletions
+38 -1
View File
@@ -18,7 +18,7 @@ import Testing
let grid = try #require(scroll.documentView as? NSCollectionView)
let layout = try #require(grid.collectionViewLayout)
let first = try #require(layout.layoutAttributesForItem(at: IndexPath(item: 0, section: 0)))
let nextRow = try #require((1..<EmojiCatalog.all.count).first { index in
let nextRow = try #require((1..<grid.numberOfItems(inSection: 0)).first { index in
guard let frame = layout.layoutAttributesForItem(at: IndexPath(item: index, section: 0))?.frame else { return false }
return frame.minY > first.frame.minY
})
@@ -27,3 +27,40 @@ import Testing
#expect(pasteboard.string(forType: .string) == EmojiCatalog.all[nextRow].value)
print("Emoji grid: \(nextRow) columns at 750 points; down navigation follows the rendered row.")
}
@Test @MainActor func emojiNavigationCrossesFavoritesRecentAndCategorySections() throws {
_ = NSApplication.shared
let suite = "EmojiSections.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suite)!
let pasteboard = NSPasteboard.withUniqueName()
defer { defaults.removePersistentDomain(forName: suite); pasteboard.releaseGlobally() }
defaults.set(["👩‍💻", "🙏"], forKey: "favoriteEmoji")
defaults.set(["🚀", "👩‍💻", "😀"], forKey: "recentEmoji")
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)
#expect(grid.numberOfItems(inSection: 0) == 2)
#expect(grid.numberOfItems(inSection: 1) == 2)
#expect((0..<grid.numberOfSections).reduce(0) { $0 + grid.numberOfItems(inSection: $1) } == EmojiCatalog.all.count)
func expectCopied(_ emoji: String) {
picker.copySelection()
#expect(pasteboard.string(forType: .string) == emoji)
}
expectCopied("👩‍💻")
picker.moveSelection(by: 1)
#expect(picker.handleControlKey("j"))
expectCopied("😀")
#expect(picker.handleControlKey("k"))
expectCopied("🙏")
picker.moveSelection(by: -1)
#expect(picker.handleControlKey("j"))
expectCopied("🚀")
#expect(picker.handleControlKey("j"))
expectCopied(try #require(EmojiCatalog.all.first { !["👩‍💻", "🙏", "🚀", "😀"].contains($0.value) }).value)
#expect(picker.handleControlKey("k"))
expectCopied("🚀")
}