mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
macos: SplitNode must be hashable to detect change
Fixes #761 SplitNode not being hashable meant that when it was set to a value of the same enum case, SwiftUI could not detect a change for re-render.
This commit is contained in:
@ -46,7 +46,7 @@ extension Ghostty {
|
|||||||
/// "container" which has a recursive top/left SplitNode and bottom/right SplitNode. These
|
/// "container" which has a recursive top/left SplitNode and bottom/right SplitNode. These
|
||||||
/// values can further be split infinitely.
|
/// values can further be split infinitely.
|
||||||
///
|
///
|
||||||
enum SplitNode {
|
enum SplitNode: Equatable, Hashable {
|
||||||
case noSplit(Leaf)
|
case noSplit(Leaf)
|
||||||
case horizontal(Container)
|
case horizontal(Container)
|
||||||
case vertical(Container)
|
case vertical(Container)
|
||||||
@ -113,7 +113,22 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Leaf: ObservableObject {
|
// MARK: - Equatable
|
||||||
|
|
||||||
|
static func == (lhs: SplitNode, rhs: SplitNode) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case (.noSplit(let lhs_v), .noSplit(let rhs_v)):
|
||||||
|
return lhs_v === rhs_v
|
||||||
|
case (.horizontal(let lhs_v), .horizontal(let rhs_v)):
|
||||||
|
return lhs_v === rhs_v
|
||||||
|
case (.vertical(let lhs_v), .vertical(let rhs_v)):
|
||||||
|
return lhs_v === rhs_v
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Leaf: ObservableObject, Equatable, Hashable {
|
||||||
let app: ghostty_app_t
|
let app: ghostty_app_t
|
||||||
@Published var surface: SurfaceView
|
@Published var surface: SurfaceView
|
||||||
|
|
||||||
@ -122,9 +137,22 @@ extension Ghostty {
|
|||||||
self.app = app
|
self.app = app
|
||||||
self.surface = SurfaceView(app, baseConfig)
|
self.surface = SurfaceView(app, baseConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Hashable
|
||||||
|
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(app)
|
||||||
|
hasher.combine(surface)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Equatable
|
||||||
|
|
||||||
|
static func == (lhs: Leaf, rhs: Leaf) -> Bool {
|
||||||
|
return lhs.app == rhs.app && lhs.surface === rhs.surface
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Container: ObservableObject {
|
class Container: ObservableObject, Equatable, Hashable {
|
||||||
let app: ghostty_app_t
|
let app: ghostty_app_t
|
||||||
@Published var topLeft: SplitNode
|
@Published var topLeft: SplitNode
|
||||||
@Published var bottomRight: SplitNode
|
@Published var bottomRight: SplitNode
|
||||||
@ -140,6 +168,22 @@ extension Ghostty {
|
|||||||
self.topLeft = .noSplit(from)
|
self.topLeft = .noSplit(from)
|
||||||
self.bottomRight = .noSplit(.init(app, baseConfig))
|
self.bottomRight = .noSplit(.init(app, baseConfig))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Hashable
|
||||||
|
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(app)
|
||||||
|
hasher.combine(topLeft)
|
||||||
|
hasher.combine(bottomRight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Equatable
|
||||||
|
|
||||||
|
static func == (lhs: Container, rhs: Container) -> Bool {
|
||||||
|
return lhs.app == rhs.app &&
|
||||||
|
lhs.topLeft == rhs.topLeft &&
|
||||||
|
lhs.bottomRight == rhs.bottomRight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This keeps track of the "neighbors" of a split: the immediately above/below/left/right
|
/// This keeps track of the "neighbors" of a split: the immediately above/below/left/right
|
||||||
@ -265,6 +309,7 @@ extension Ghostty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle(surfaceTitle ?? "Ghostty")
|
.navigationTitle(surfaceTitle ?? "Ghostty")
|
||||||
|
.id(node) // Required to detect node changes
|
||||||
} else {
|
} else {
|
||||||
// On these events we want to reset the split state and call it.
|
// On these events we want to reset the split state and call it.
|
||||||
let pubSplit = center.publisher(for: Notification.ghosttyNewSplit, object: zoomedSurface!)
|
let pubSplit = center.publisher(for: Notification.ghosttyNewSplit, object: zoomedSurface!)
|
||||||
|
Reference in New Issue
Block a user