macos: move icon codable/equatable to extension

This commit is contained in:
Mitchell Hashimoto
2026-02-24 10:20:25 -08:00
parent c72788894e
commit f451ea8e46

View File

@@ -1,33 +1,6 @@
import Cocoa
struct ColorizedGhosttyIcon: Codable, Equatable {
init(screenColors: [NSColor], ghostColor: NSColor, frame: Ghostty.MacOSIconFrame) {
self.screenColors = screenColors
self.ghostColor = ghostColor
self.frame = frame
}
init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let screenColorHexes = try container.decode([String].self, forKey: .screenColors)
let screenColors = screenColorHexes.compactMap(NSColor.init(hex:))
let ghostColorHex = try container.decode(String.self, forKey: .ghostColor)
guard let ghostColor = NSColor(hex: ghostColorHex) else {
throw NSError(domain: "Custom Icon Error", code: 1, userInfo: [
NSLocalizedDescriptionKey: "Failed to decode ghost color from \(ghostColorHex)"
])
}
let frame = try container.decode(Ghostty.MacOSIconFrame.self, forKey: .frame)
self.init(screenColors: screenColors, ghostColor: ghostColor, frame: frame)
}
func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(screenColors.compactMap(\.hexString), forKey: .screenColors)
try container.encode(ghostColor.hexString, forKey: .ghostColor)
try container.encode(frame, forKey: .frame)
}
struct ColorizedGhosttyIcon {
/// The colors that make up the gradient of the screen.
let screenColors: [NSColor]
@@ -37,12 +10,6 @@ struct ColorizedGhosttyIcon: Codable, Equatable {
/// The frame type to use
let frame: Ghostty.MacOSIconFrame
private enum CodingKeys: String, CodingKey {
case screenColors
case ghostColor
case frame
}
/// Make a custom colorized ghostty icon.
func makeImage(in bundle: Bundle) -> NSImage? {
// All of our layers (not in order)
@@ -86,3 +53,63 @@ struct ColorizedGhosttyIcon: Codable, Equatable {
])
}
}
// MARK: Codable
extension ColorizedGhosttyIcon: Codable {
private enum CodingKeys: String, CodingKey {
case version
case screenColors
case ghostColor
case frame
static let currentVersion: Int = 1
}
init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
// If no version exists then this is the legacy v0 format.
let version = try container.decodeIfPresent(Int.self, forKey: .version) ?? 0
guard version == 0 || version == CodingKeys.currentVersion else {
throw DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Unsupported ColorizedGhosttyIcon version: \(version)"
)
)
}
let screenColorHexes = try container.decode([String].self, forKey: .screenColors)
let screenColors = screenColorHexes.compactMap(NSColor.init(hex:))
let ghostColorHex = try container.decode(String.self, forKey: .ghostColor)
guard let ghostColor = NSColor(hex: ghostColorHex) else {
throw DecodingError.dataCorruptedError(
forKey: .ghostColor,
in: container,
debugDescription: "Failed to decode ghost color from \(ghostColorHex)"
)
}
let frame = try container.decode(Ghostty.MacOSIconFrame.self, forKey: .frame)
self.init(screenColors: screenColors, ghostColor: ghostColor, frame: frame)
}
func encode(to encoder: any Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(CodingKeys.currentVersion, forKey: .version)
try container.encode(screenColors.compactMap(\.hexString), forKey: .screenColors)
try container.encode(ghostColor.hexString, forKey: .ghostColor)
try container.encode(frame, forKey: .frame)
}
}
// MARK: Equatable
extension ColorizedGhosttyIcon: Equatable {
static func == (lhs: Self, rhs: Self) -> Bool {
lhs.frame == rhs.frame &&
lhs.screenColors.compactMap(\.hexString) == rhs.screenColors.compactMap(\.hexString) &&
lhs.ghostColor.hexString == rhs.ghostColor.hexString
}
}