File tree Expand file tree Collapse file tree 5 files changed +66
-15
lines changed
Core/Services/Infrastructure Expand file tree Collapse file tree 5 files changed +66
-15
lines changed Original file line number Diff line number Diff line change @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
88## [ Unreleased]
99
10+ ### Fixed
11+
12+ - Fix potential hang when coordinator deallocates during save
13+ - Fix Cmd+W save not persisting data grid changes (sidebar edits intercepted save path)
14+
1015## [ 0.27.5] - 2026-04-06
1116
1217### Added
Original file line number Diff line number Diff line change @@ -15,15 +15,17 @@ internal final class WindowOpener {
1515
1616 internal static let shared = WindowOpener ( )
1717
18- private var readyContinuation : CheckedContinuation < Void , Never > ?
18+ private var readyContinuations : [ CheckedContinuation < Void , Never > ] = [ ]
1919
2020 /// Set on appear by ContentView, WelcomeViewModel, or ConnectionFormView.
2121 /// Safe to store — OpenWindowAction is app-scoped, not view-scoped.
2222 internal var openWindow : OpenWindowAction ? {
2323 didSet {
2424 if openWindow != nil {
25- readyContinuation? . resume ( )
26- readyContinuation = nil
25+ for continuation in readyContinuations {
26+ continuation. resume ( )
27+ }
28+ readyContinuations. removeAll ( )
2729 }
2830 }
2931 }
@@ -35,7 +37,7 @@ internal final class WindowOpener {
3537 if openWindow != nil {
3638 continuation. resume ( )
3739 } else {
38- readyContinuation = continuation
40+ readyContinuations . append ( continuation)
3941 }
4042 }
4143 }
Original file line number Diff line number Diff line change 59645964 }
59655965 }
59665966 }
5967+ },
5968+ "Change Primary Key" : {
5969+
59675970 },
59685971 "Character Set" : {
59695972 "localizations" : {
1061010613 }
1061110614 },
1061210615 "Delete Column" : {
10613- "extractionState" : "stale",
1061410616 "localizations" : {
1061510617 "tr" : {
1061610618 "stringUnit" : {
1069910701 }
1070010702 },
1070110703 "Delete Foreign Key" : {
10702- "extractionState" : "stale",
1070310704 "localizations" : {
1070410705 "tr" : {
1070510706 "stringUnit" : {
1074410745 }
1074510746 },
1074610747 "Delete Index" : {
10747- "extractionState" : "stale",
1074810748 "localizations" : {
1074910749 "tr" : {
1075010750 "stringUnit" : {
1081510815 }
1081610816 }
1081710817 }
10818+ },
10819+ "Delete Row" : {
10820+
10821+ },
10822+ "Delete Rows" : {
10823+
1081810824 },
1081910825 "Delete Selected" : {
1082010826 "localizations" : {
1168911695 }
1169011696 }
1169111697 }
11698+ },
11699+ "Edit Cell" : {
11700+
11701+ },
11702+ "Edit Column" : {
11703+
1169211704 },
1169311705 "Edit Connection" : {
1169411706 "localizations" : {
1173411746 }
1173511747 }
1173611748 }
11749+ },
11750+ "Edit Foreign Key" : {
11751+
11752+ },
11753+ "Edit Index" : {
11754+
1173711755 },
1173811756 "Edit Profile..." : {
1173911757 "localizations" : {
1711517133 }
1711617134 }
1711717135 }
17136+ },
17137+ "Insert Row" : {
17138+
17139+ },
17140+ "Insert Rows" : {
17141+
1711817142 },
1711917143 "INSERT Statement(s)" : {
1712017144 "localizations" : {
2852528549 }
2852628550 },
2852728551 "Search for field..." : {
28552+ "extractionState" : "stale",
2852828553 "localizations" : {
2852928554 "tr" : {
2853028555 "stringUnit" : {
2863628661 }
2863728662 },
2863828663 "Search shortcuts..." : {
28664+ "extractionState" : "stale",
2863928665 "localizations" : {
2864028666 "tr" : {
2864128667 "stringUnit" : {
2865828684 }
2865928685 },
2866028686 "Search tables, views, databases..." : {
28687+ "extractionState" : "stale",
2866128688 "localizations" : {
2866228689 "tr" : {
2866328690 "stringUnit" : {
Original file line number Diff line number Diff line change @@ -358,22 +358,36 @@ final class MainContentCommandActions {
358358 return
359359 }
360360
361- // Sidebar edits
361+ // Data grid changes or pending table operations take priority
362+ let hasDataChanges = coordinator. changeManager. hasChanges
363+ || !pendingTruncates. wrappedValue. isEmpty
364+ || !pendingDeletes. wrappedValue. isEmpty
365+ if hasDataChanges {
366+ let saved = await withCheckedContinuation { continuation in
367+ coordinator. saveCompletionContinuation = continuation
368+ saveChanges ( )
369+ }
370+ if saved {
371+ performClose ( )
372+ }
373+ return
374+ }
375+
376+ // Sidebar-only edits (made directly in the inspector panel)
362377 if rightPanelState. editState. hasEdits {
363378 rightPanelState. onSave ? ( )
364379 performClose ( )
365380 return
366381 }
367382
368- // Data grid changes: await the async save via continuation
369- let saved = await withCheckedContinuation { continuation in
370- coordinator. saveCompletionContinuation = continuation
371- saveChanges ( )
372- }
373-
374- if saved {
383+ // File save (query editor with source file)
384+ if coordinator. tabManager. selectedTab? . isFileDirty == true {
385+ saveFileToSourceURL ( )
375386 performClose ( )
387+ return
376388 }
389+
390+ performClose ( )
377391 }
378392
379393 private func saveFileToSourceURL( ) {
Original file line number Diff line number Diff line change @@ -410,6 +410,9 @@ final class MainContentCoordinator {
410410 }
411411
412412 deinit {
413+ saveCompletionContinuation? . resume ( returning: false )
414+ saveCompletionContinuation = nil
415+
413416 let connectionId = connection. id
414417 let alreadyHandled = _didTeardown. withLock { $0 } || _teardownScheduled. withLock { $0 }
415418
You can’t perform that action at this time.
0 commit comments