macOS: split tree zoom state should encode as path, not full node (#8505)
Fixes #8356 Zoom state should encode as a path so that it can be mapped to a reference to the node in `root`. Previously, we were encoding a full node which was instantiating an extra terminal on restore. AI disclaimer: Claude code did the Codable implementation.pull/8506/head
commit
e6d60dee07
|
|
@ -1,7 +1,7 @@
|
|||
import AppKit
|
||||
|
||||
/// SplitTree represents a tree of views that can be divided.
|
||||
struct SplitTree<ViewType: NSView & Codable>: Codable {
|
||||
struct SplitTree<ViewType: NSView & Codable> {
|
||||
/// The root of the tree. This can be nil to indicate the tree is empty.
|
||||
let root: Node?
|
||||
|
||||
|
|
@ -29,12 +29,12 @@ struct SplitTree<ViewType: NSView & Codable>: Codable {
|
|||
}
|
||||
|
||||
/// The path to a specific node in the tree.
|
||||
struct Path {
|
||||
struct Path: Codable {
|
||||
let path: [Component]
|
||||
|
||||
var isEmpty: Bool { path.isEmpty }
|
||||
|
||||
enum Component {
|
||||
enum Component: Codable {
|
||||
case left
|
||||
case right
|
||||
}
|
||||
|
|
@ -334,6 +334,60 @@ extension SplitTree {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: SplitTree Codable
|
||||
|
||||
fileprivate enum CodingKeys: String, CodingKey {
|
||||
case version
|
||||
case root
|
||||
case zoomed
|
||||
|
||||
static let currentVersion: Int = 1
|
||||
}
|
||||
|
||||
extension SplitTree: Codable {
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Check version
|
||||
let version = try container.decode(Int.self, forKey: .version)
|
||||
guard version == CodingKeys.currentVersion else {
|
||||
throw DecodingError.dataCorrupted(
|
||||
DecodingError.Context(
|
||||
codingPath: decoder.codingPath,
|
||||
debugDescription: "Unsupported SplitTree version: \(version)"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Decode root
|
||||
self.root = try container.decodeIfPresent(Node.self, forKey: .root)
|
||||
|
||||
// Zoomed is encoded as its path. Get the path and then find it.
|
||||
if let zoomedPath = try container.decodeIfPresent(Path.self, forKey: .zoomed),
|
||||
let root = self.root {
|
||||
self.zoomed = root.node(at: zoomedPath)
|
||||
} else {
|
||||
self.zoomed = nil
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Encode version
|
||||
try container.encode(CodingKeys.currentVersion, forKey: .version)
|
||||
|
||||
// Encode root
|
||||
try container.encodeIfPresent(root, forKey: .root)
|
||||
|
||||
// Zoomed is encoded as its path since its a reference type. This lets us
|
||||
// map it on decode back to the correct node in root.
|
||||
if let zoomed, let path = root?.path(to: zoomed) {
|
||||
try container.encode(path, forKey: .zoomed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: SplitTree.Node
|
||||
|
||||
extension SplitTree.Node {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Cocoa
|
|||
class TerminalRestorableState: Codable {
|
||||
static let selfKey = "state"
|
||||
static let versionKey = "version"
|
||||
static let version: Int = 4
|
||||
static let version: Int = 5
|
||||
|
||||
let focusedSurface: String?
|
||||
let surfaceTree: SplitTree<Ghostty.SurfaceView>
|
||||
|
|
|
|||
Loading…
Reference in New Issue