fix: center emoji artwork in launcher icon slot
This commit is contained in:
@@ -81,7 +81,7 @@ Currency and crypto conversions require internet access and use [currency-api](h
|
|||||||
|
|
||||||
## Emoji picker
|
## Emoji picker
|
||||||
|
|
||||||
Search for **Conjure Emoji** and open it. Browse the grid or search by name, keyword, `:shortcode:`, or emoji. Use the category menu to filter results or show **Recently Used**. Your last 30 selections are saved locally. Favorites appear first, followed by recent selections when browsing All Emoji.
|
Search for **Conjure Emoji**, identified by its centered 🤔 icon, and open it. Browse the grid or search by name, keyword, `:shortcode:`, or emoji. Use the category menu to filter results or show **Recently Used**. Your last 30 selections are saved locally. Favorites appear first, followed by recent selections when browsing All Emoji.
|
||||||
|
|
||||||
Use the arrow keys or Control-H/J/K/L to navigate left/down/up/right. Return or clicking an emoji copies it and dismisses Conjure, restoring focus to the previous app. Paste with Command-V; no Accessibility permission is needed. Escape or the Back chevron returns to the launcher and restores your search.
|
Use the arrow keys or Control-H/J/K/L to navigate left/down/up/right. Return or clicking an emoji copies it and dismisses Conjure, restoring focus to the previous app. Paste with Command-V; no Accessibility permission is needed. Escape or the Back chevron returns to the launcher and restores your search.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import AppKit
|
import AppKit
|
||||||
import ConjureKit
|
import ConjureKit
|
||||||
|
import CoreText
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSearchFieldDelegate, NSTableViewDataSource, NSTableViewDelegate {
|
final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSearchFieldDelegate, NSTableViewDataSource, NSTableViewDelegate {
|
||||||
@@ -40,9 +41,13 @@ final class LauncherWindowController: NSWindowController, NSWindowDelegate, NSSe
|
|||||||
private var pendingPresentation: (() -> Void)?
|
private var pendingPresentation: (() -> Void)?
|
||||||
private static let emojiIcon: NSImage = {
|
private static let emojiIcon: NSImage = {
|
||||||
let text = NSAttributedString(string: "🤔", attributes: [.font: NSFont.systemFont(ofSize: 28)])
|
let text = NSAttributedString(string: "🤔", attributes: [.font: NSFont.systemFont(ofSize: 28)])
|
||||||
let size = text.size()
|
let line = CTLineCreateWithAttributedString(text)
|
||||||
return NSImage(size: size, flipped: false) { _ in
|
return NSImage(size: NSSize(width: 32, height: 32), flipped: false) { rect in
|
||||||
text.draw(at: .zero)
|
guard let context = NSGraphicsContext.current?.cgContext else { return false }
|
||||||
|
context.textPosition = .zero
|
||||||
|
let bounds = CTLineGetImageBounds(line, context)
|
||||||
|
context.textPosition = CGPoint(x: rect.midX - bounds.midX, y: rect.midY - bounds.midY)
|
||||||
|
CTLineDraw(line, context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import AppKit
|
||||||
|
import Testing
|
||||||
|
@testable import Conjure
|
||||||
|
|
||||||
|
@Test @MainActor func emojiCommandArtworkHasBalancedVisiblePadding() throws {
|
||||||
|
_ = NSApplication.shared
|
||||||
|
let launcher = LauncherWindowController()
|
||||||
|
func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) }
|
||||||
|
let views = descendants(try #require(launcher.window?.contentView))
|
||||||
|
let search = try #require(views.compactMap { $0 as? NSSearchField }.first)
|
||||||
|
search.stringValue = "emoji"
|
||||||
|
launcher.controlTextDidChange(Notification(name: NSControl.textDidChangeNotification, object: search))
|
||||||
|
let table = try #require(views.compactMap { $0 as? NSTableView }.first)
|
||||||
|
let cell = try #require(launcher.tableView(table, viewFor: nil, row: 0) as? ApplicationCell)
|
||||||
|
let image = try #require(cell.imageView?.image)
|
||||||
|
let data = try #require(image.tiffRepresentation)
|
||||||
|
let bitmap = try #require(NSBitmapImageRep(data: data))
|
||||||
|
var left = bitmap.pixelsWide, right = -1, top = bitmap.pixelsHigh, bottom = -1
|
||||||
|
for y in 0..<bitmap.pixelsHigh {
|
||||||
|
for x in 0..<bitmap.pixelsWide where (bitmap.colorAt(x: x, y: y)?.alphaComponent ?? 0) > 0.5 {
|
||||||
|
left = min(left, x); right = max(right, x)
|
||||||
|
top = min(top, y); bottom = max(bottom, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#expect(right > left && bottom > top)
|
||||||
|
#expect(abs(left - (bitmap.pixelsWide - right - 1)) <= 2)
|
||||||
|
#expect(abs(top - (bitmap.pixelsHigh - bottom - 1)) <= 2)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user