Skip to content

Commit ec9e5bb

Browse files
committed
fix: call editor destroy from coordinator teardown since onDisappear doesn't fire on window close
1 parent 5534052 commit ec9e5bb

4 files changed

Lines changed: 19 additions & 1 deletion

File tree

TablePro/Views/Editor/QueryEditorView.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct QueryEditorView: View {
2929
var onAIExplain: ((String) -> Void)?
3030
var onAIOptimize: ((String) -> Void)?
3131
var onSaveAsFavorite: ((String) -> Void)?
32+
var onEditorCoordinatorReady: ((SQLEditorCoordinator) -> Void)?
3233

3334
@State private var vimMode: VimMode = .normal
3435

@@ -54,7 +55,8 @@ struct QueryEditorView: View {
5455
onExecuteQuery: onExecuteQuery,
5556
onAIExplain: onAIExplain,
5657
onAIOptimize: onAIOptimize,
57-
onSaveAsFavorite: onSaveAsFavorite
58+
onSaveAsFavorite: onSaveAsFavorite,
59+
onEditorCoordinatorReady: onEditorCoordinatorReady
5860
)
5961
.frame(minHeight: 100)
6062
.clipped()

TablePro/Views/Editor/SQLEditorView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct SQLEditorView: View {
2626
var onAIExplain: ((String) -> Void)?
2727
var onAIOptimize: ((String) -> Void)?
2828
var onSaveAsFavorite: ((String) -> Void)?
29+
/// Called when the editor coordinator is ready — allows parent to store a reference for teardown.
30+
var onEditorCoordinatorReady: ((SQLEditorCoordinator) -> Void)?
2931

3032
@State private var editorState = SourceEditorState()
3133
@State private var completionAdapter: SQLCompletionAdapter?
@@ -104,6 +106,7 @@ struct SQLEditorView: View {
104106
coordinator.onAIExplain = onAIExplain
105107
coordinator.onAIOptimize = onAIOptimize
106108
coordinator.onSaveAsFavorite = onSaveAsFavorite
109+
onEditorCoordinatorReady?(coordinator)
107110
setupFavoritesObserver()
108111
}
109112
} else {

TablePro/Views/Main/Child/MainEditorContentView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ struct MainEditorContentView: View {
212212
onSaveAsFavorite: { text in
213213
guard !text.isEmpty else { return }
214214
favoriteDialogQuery = FavoriteDialogQuery(query: text)
215+
},
216+
onEditorCoordinatorReady: { editorCoord in
217+
coordinator.editorCoordinator = editorCoord
215218
}
216219
)
217220
}

TablePro/Views/Main/MainContentCoordinator.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ final class MainContentCoordinator {
128128
/// Called during teardown to let the view layer release cached row providers and sort data.
129129
@ObservationIgnored var onTeardown: (() -> Void)?
130130

131+
/// Weak reference to the active SQL editor coordinator for teardown cleanup.
132+
/// Set by SQLEditorCoordinator during prepareCoordinator.
133+
@ObservationIgnored weak var editorCoordinator: SQLEditorCoordinator?
134+
131135
/// True while a database switch is in progress. Guards against
132136
/// side-effect window creation during the switch cascade.
133137
var isSwitchingDatabase = false
@@ -369,6 +373,12 @@ final class MainContentCoordinator {
369373
onTeardown?()
370374
onTeardown = nil
371375

376+
// Release editor heavy state (tree-sitter, highlighter, text storage) —
377+
// SQLEditorView.onDisappear does NOT fire when an NSWindow closes,
378+
// so we must do it here explicitly.
379+
editorCoordinator?.destroy()
380+
editorCoordinator = nil
381+
372382
// Release heavy data so memory drops even if SwiftUI delays deallocation
373383
for tab in tabManager.tabs {
374384
tab.rowBuffer.evict()

0 commit comments

Comments
 (0)