mirror of
https://github.com/bitsycore/Allofit.git
synced 2026-10-06 21:07:27 +00:00
56 lines
1.8 KiB
Swift
56 lines
1.8 KiB
Swift
import AppKit
|
|
import UniformTypeIdentifiers
|
|
|
|
// IconCache returns NSImage icons keyed by file extension (or "_dir" for
|
|
// directories). The previous code called NSWorkspace.shared.icon(forFile:)
|
|
// per row, which stat's the file and inspects .app bundle Info.plist - that
|
|
// is what was driving the beachball and the NSTableView reentrance warnings
|
|
// when rendering thousands of rows.
|
|
//
|
|
// NSWorkspace.shared.icon(for: UTType) is a pure in-memory lookup keyed by
|
|
// uniform type identifier, so once the per-extension icon is cached the row
|
|
// renderer touches no filesystem at all.
|
|
enum IconCache {
|
|
|
|
// extension (lowercased) or sentinel key -> cached icon
|
|
// nonisolated(unsafe) because all access is serialized through the lock
|
|
// below - Swift's static-isolation check can't see that, so we vouch.
|
|
nonisolated(unsafe) private static var cache: [String: NSImage] = [:]
|
|
// guard for cache access (Table renderers may run on multiple threads)
|
|
private static let lock = NSLock()
|
|
|
|
// returns the icon for a file or directory with the given name
|
|
static func icon(forName inName: String, isDirectory inIsDir: Bool) -> NSImage {
|
|
let vKey: String
|
|
if inIsDir {
|
|
vKey = "_dir"
|
|
} else {
|
|
let vExt = (inName as NSString).pathExtension.lowercased()
|
|
vKey = vExt.isEmpty ? "_file" : vExt
|
|
}
|
|
|
|
lock.lock()
|
|
if let vCached = cache[vKey] {
|
|
lock.unlock()
|
|
return vCached
|
|
}
|
|
lock.unlock()
|
|
|
|
let vIcon: NSImage
|
|
if inIsDir {
|
|
vIcon = NSWorkspace.shared.icon(for: .folder)
|
|
} else if vKey == "_file" {
|
|
vIcon = NSWorkspace.shared.icon(for: .data)
|
|
} else if let vType = UTType(filenameExtension: vKey) {
|
|
vIcon = NSWorkspace.shared.icon(for: vType)
|
|
} else {
|
|
vIcon = NSWorkspace.shared.icon(for: .data)
|
|
}
|
|
|
|
lock.lock()
|
|
cache[vKey] = vIcon
|
|
lock.unlock()
|
|
return vIcon
|
|
}
|
|
}
|