Refactor workspace theme refresh to shared resolver

This commit is contained in:
Lawrence Chen 2026-02-23 00:06:39 -08:00
parent e90b45f75e
commit 963bb03e99
2 changed files with 61 additions and 6 deletions

View file

@ -9,7 +9,7 @@ struct WorkspaceContentView: View {
let isWorkspaceVisible: Bool
let isWorkspaceInputActive: Bool
let workspacePortalPriority: Int
@State private var config = GhosttyConfig.load()
@State private var config = WorkspaceContentView.resolveGhosttyAppearanceConfig()
@Environment(\.colorScheme) private var colorScheme
@EnvironmentObject var notificationStore: TerminalNotificationStore
@ -87,7 +87,7 @@ struct WorkspaceContentView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear {
syncBonsplitNotificationBadges()
workspace.applyGhosttyChrome(backgroundColor: GhosttyApp.shared.defaultBackgroundColor)
refreshGhosttyAppearanceConfig()
}
.onChange(of: notificationStore.notifications) { _, _ in
syncBonsplitNotificationBadges()
@ -104,9 +104,9 @@ struct WorkspaceContentView: View {
}
.onReceive(NotificationCenter.default.publisher(for: .ghosttyDefaultBackgroundDidChange)) { notification in
if let backgroundColor = notification.userInfo?[GhosttyNotificationKey.backgroundColor] as? NSColor {
workspace.applyGhosttyChrome(backgroundColor: backgroundColor)
refreshGhosttyAppearanceConfig(backgroundOverride: backgroundColor)
} else {
workspace.applyGhosttyChrome(backgroundColor: GhosttyApp.shared.defaultBackgroundColor)
refreshGhosttyAppearanceConfig()
}
}
}
@ -141,8 +141,18 @@ struct WorkspaceContentView: View {
}
}
private func refreshGhosttyAppearanceConfig() {
let next = GhosttyConfig.load()
static func resolveGhosttyAppearanceConfig(
backgroundOverride: NSColor? = nil,
loadConfig: () -> GhosttyConfig = GhosttyConfig.load,
defaultBackground: () -> NSColor = { GhosttyApp.shared.defaultBackgroundColor }
) -> GhosttyConfig {
var next = loadConfig()
next.backgroundColor = backgroundOverride ?? defaultBackground()
return next
}
private func refreshGhosttyAppearanceConfig(backgroundOverride: NSColor? = nil) {
let next = Self.resolveGhosttyAppearanceConfig(backgroundOverride: backgroundOverride)
config = next
workspace.applyGhosttyChrome(from: next)
}

View file

@ -232,6 +232,51 @@ final class WorkspaceChromeThemeTests: XCTestCase {
}
}
final class WorkspaceAppearanceConfigResolutionTests: XCTestCase {
func testResolvedAppearanceConfigPrefersGhosttyRuntimeBackgroundOverLoadedConfig() {
guard let loadedBackground = NSColor(hex: "#112233"),
let runtimeBackground = NSColor(hex: "#FDF6E3"),
let loadedForeground = NSColor(hex: "#ABCDEF") else {
XCTFail("Expected valid test colors")
return
}
var loaded = GhosttyConfig()
loaded.backgroundColor = loadedBackground
loaded.foregroundColor = loadedForeground
loaded.unfocusedSplitOpacity = 0.42
let resolved = WorkspaceContentView.resolveGhosttyAppearanceConfig(
loadConfig: { loaded },
defaultBackground: { runtimeBackground }
)
XCTAssertEqual(resolved.backgroundColor.hexString(), "#FDF6E3")
XCTAssertEqual(resolved.foregroundColor.hexString(), "#ABCDEF")
XCTAssertEqual(resolved.unfocusedSplitOpacity, 0.42, accuracy: 0.0001)
}
func testResolvedAppearanceConfigPrefersExplicitBackgroundOverride() {
guard let loadedBackground = NSColor(hex: "#112233"),
let runtimeBackground = NSColor(hex: "#FDF6E3"),
let explicitOverride = NSColor(hex: "#272822") else {
XCTFail("Expected valid test colors")
return
}
var loaded = GhosttyConfig()
loaded.backgroundColor = loadedBackground
let resolved = WorkspaceContentView.resolveGhosttyAppearanceConfig(
backgroundOverride: explicitOverride,
loadConfig: { loaded },
defaultBackground: { runtimeBackground }
)
XCTAssertEqual(resolved.backgroundColor.hexString(), "#272822")
}
}
final class NotificationBurstCoalescerTests: XCTestCase {
func testSignalsInSameBurstFlushOnce() {
let coalescer = NotificationBurstCoalescer(delay: 0.01)