Deduplicate high-frequency socket metadata updates
This commit is contained in:
parent
021cc05cf3
commit
68cf29cd2d
3 changed files with 161 additions and 12 deletions
|
|
@ -68,6 +68,41 @@ class TerminalController {
|
|||
|
||||
private init() {}
|
||||
|
||||
nonisolated static func shouldReplaceStatusEntry(
|
||||
current: SidebarStatusEntry?,
|
||||
key: String,
|
||||
value: String,
|
||||
icon: String?,
|
||||
color: String?
|
||||
) -> Bool {
|
||||
guard let current else { return true }
|
||||
return current.key != key || current.value != value || current.icon != icon || current.color != color
|
||||
}
|
||||
|
||||
nonisolated static func shouldReplaceProgress(
|
||||
current: SidebarProgressState?,
|
||||
value: Double,
|
||||
label: String?
|
||||
) -> Bool {
|
||||
guard let current else { return true }
|
||||
return current.value != value || current.label != label
|
||||
}
|
||||
|
||||
nonisolated static func shouldReplaceGitBranch(
|
||||
current: SidebarGitBranchState?,
|
||||
branch: String,
|
||||
isDirty: Bool
|
||||
) -> Bool {
|
||||
guard let current else { return true }
|
||||
return current.branch != branch || current.isDirty != isDirty
|
||||
}
|
||||
|
||||
nonisolated static func shouldReplacePorts(current: [Int]?, next: [Int]) -> Bool {
|
||||
let currentSorted = Array(Set(current ?? [])).sorted()
|
||||
let nextSorted = Array(Set(next)).sorted()
|
||||
return currentSorted != nextSorted
|
||||
}
|
||||
|
||||
/// Update which window's TabManager receives socket commands.
|
||||
/// This is used when the user switches between multiple terminal windows.
|
||||
func setActiveTabManager(_ tabManager: TabManager?) {
|
||||
|
|
@ -194,7 +229,14 @@ class TerminalController {
|
|||
guard let workspace = tabManager.tabs.first(where: { $0.id == workspaceId }) else { return }
|
||||
let validSurfaceIds = Set(workspace.panels.keys)
|
||||
guard validSurfaceIds.contains(panelId) else { return }
|
||||
workspace.surfaceListeningPorts[panelId] = ports.isEmpty ? nil : ports
|
||||
let nextPorts = Array(Set(ports)).sorted()
|
||||
let currentPorts = workspace.surfaceListeningPorts[panelId] ?? []
|
||||
guard currentPorts != nextPorts else { return }
|
||||
if nextPorts.isEmpty {
|
||||
workspace.surfaceListeningPorts.removeValue(forKey: panelId)
|
||||
} else {
|
||||
workspace.surfaceListeningPorts[panelId] = nextPorts
|
||||
}
|
||||
workspace.recomputeListeningPorts()
|
||||
}
|
||||
}
|
||||
|
|
@ -10421,12 +10463,22 @@ class TerminalController {
|
|||
result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected"
|
||||
return
|
||||
}
|
||||
guard Self.shouldReplaceStatusEntry(
|
||||
current: tab.statusEntries[key],
|
||||
key: key,
|
||||
value: value,
|
||||
icon: icon,
|
||||
color: color
|
||||
) else {
|
||||
return
|
||||
}
|
||||
tab.statusEntries[key] = SidebarStatusEntry(
|
||||
key: key,
|
||||
value: value,
|
||||
icon: icon,
|
||||
color: color,
|
||||
timestamp: Date())
|
||||
timestamp: Date()
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -10569,6 +10621,9 @@ class TerminalController {
|
|||
result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected"
|
||||
return
|
||||
}
|
||||
guard Self.shouldReplaceProgress(current: tab.progress, value: clamped, label: label) else {
|
||||
return
|
||||
}
|
||||
tab.progress = SidebarProgressState(value: clamped, label: label)
|
||||
}
|
||||
return result
|
||||
|
|
@ -10581,7 +10636,9 @@ class TerminalController {
|
|||
result = "ERROR: Tab not found"
|
||||
return
|
||||
}
|
||||
tab.progress = nil
|
||||
if tab.progress != nil {
|
||||
tab.progress = nil
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -10599,6 +10656,9 @@ class TerminalController {
|
|||
result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected"
|
||||
return
|
||||
}
|
||||
guard Self.shouldReplaceGitBranch(current: tab.gitBranch, branch: branch, isDirty: isDirty) else {
|
||||
return
|
||||
}
|
||||
tab.gitBranch = SidebarGitBranchState(branch: branch, isDirty: isDirty)
|
||||
}
|
||||
return result
|
||||
|
|
@ -10611,7 +10671,9 @@ class TerminalController {
|
|||
result = "ERROR: Tab not found"
|
||||
return
|
||||
}
|
||||
tab.gitBranch = nil
|
||||
if tab.gitBranch != nil {
|
||||
tab.gitBranch = nil
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -10628,6 +10690,7 @@ class TerminalController {
|
|||
}
|
||||
ports.append(port)
|
||||
}
|
||||
let normalizedPorts = Array(Set(ports)).sorted()
|
||||
|
||||
var result = "OK"
|
||||
DispatchQueue.main.sync {
|
||||
|
|
@ -10664,7 +10727,11 @@ class TerminalController {
|
|||
return
|
||||
}
|
||||
|
||||
tab.surfaceListeningPorts[surfaceId] = ports
|
||||
guard Self.shouldReplacePorts(current: tab.surfaceListeningPorts[surfaceId], next: normalizedPorts) else {
|
||||
return
|
||||
}
|
||||
|
||||
tab.surfaceListeningPorts[surfaceId] = normalizedPorts
|
||||
tab.recomputeListeningPorts()
|
||||
}
|
||||
return result
|
||||
|
|
@ -10744,11 +10811,15 @@ class TerminalController {
|
|||
result = "ERROR: Panel not found '\(surfaceId.uuidString)'"
|
||||
return
|
||||
}
|
||||
tab.surfaceListeningPorts.removeValue(forKey: surfaceId)
|
||||
if tab.surfaceListeningPorts.removeValue(forKey: surfaceId) != nil {
|
||||
tab.recomputeListeningPorts()
|
||||
}
|
||||
} else {
|
||||
tab.surfaceListeningPorts.removeAll()
|
||||
if !tab.surfaceListeningPorts.isEmpty {
|
||||
tab.surfaceListeningPorts.removeAll()
|
||||
tab.recomputeListeningPorts()
|
||||
}
|
||||
}
|
||||
tab.recomputeListeningPorts()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -10792,6 +10863,7 @@ class TerminalController {
|
|||
return
|
||||
}
|
||||
|
||||
guard tab.surfaceTTYNames[surfaceId] != ttyName else { return }
|
||||
tab.surfaceTTYNames[surfaceId] = ttyName
|
||||
PortScanner.shared.registerTTY(workspaceId: tab.id, panelId: surfaceId, ttyName: ttyName)
|
||||
}
|
||||
|
|
@ -10799,15 +10871,14 @@ class TerminalController {
|
|||
}
|
||||
|
||||
private func portsKick(_ args: String) -> String {
|
||||
let parsed = parseOptions(args)
|
||||
var result = "OK"
|
||||
DispatchQueue.main.sync {
|
||||
guard let tab = resolveTabForReport(args) else {
|
||||
let parsed = parseOptions(args)
|
||||
result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected"
|
||||
return
|
||||
}
|
||||
|
||||
let parsed = parseOptions(args)
|
||||
let panelArg = parsed.options["panel"] ?? parsed.options["surface"]
|
||||
let surfaceId: UUID
|
||||
if let panelArg {
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
panelDirectories[panelId] = trimmed
|
||||
}
|
||||
// Update current directory if this is the focused panel
|
||||
if panelId == focusedPanelId {
|
||||
if panelId == focusedPanelId, currentDirectory != trimmed {
|
||||
currentDirectory = trimmed
|
||||
}
|
||||
}
|
||||
|
|
@ -616,7 +616,10 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
|
||||
func recomputeListeningPorts() {
|
||||
let unique = Set(surfaceListeningPorts.values.flatMap { $0 })
|
||||
listeningPorts = unique.sorted()
|
||||
let next = unique.sorted()
|
||||
if listeningPorts != next {
|
||||
listeningPorts = next
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Panel Operations
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue