Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed the separate Copilot settings tab and the per-feature routing UI
- Existing AI providers are preserved on upgrade; the first one is auto-set as active
- Filter value field uses a native SwiftUI suggestion dropdown instead of the AppKit autocomplete popup
- Undo/Redo routes through macOS responder chain, eliminating manual first-responder dispatch
- Native macOS UI patterns: Picker(.menu) for cell editors, native alerts, native List selection, .navigationTitle for sheets, NSSearchField for welcome search, borderless toolbar buttons, chevron indicator on SET picker
- Quit dialog defaults to Cancel on Return key
- Connection form delete button moved to far left
- SSH/SSL browse panels show descriptive message text

### Added

Expand Down
14 changes: 10 additions & 4 deletions TablePro/Core/ChangeTracking/AnyChangeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import Observation
@Observable
@MainActor
final class AnyChangeManager {
@ObservationIgnored private var dataManager: DataChangeManager?
@ObservationIgnored private var structureManager: StructureChangeManager?
@ObservationIgnored private(set) var dataManager: DataChangeManager?
@ObservationIgnored private(set) var structureManager: StructureChangeManager?

var hasChanges: Bool {
dataManager?.hasChanges ?? structureManager?.hasChanges ?? false
Expand Down Expand Up @@ -44,7 +44,7 @@ final class AnyChangeManager {
dataManager.changes
}
self._canRedo = {
dataManager.canRedo
dataManager.undoManager.canRedo
}
self._recordCellChange = { rowIndex, columnIndex, columnName, oldValue, newValue, originalRow in
dataManager.recordCellChange(
Expand Down Expand Up @@ -75,7 +75,7 @@ final class AnyChangeManager {
Array(structureManager.pendingChanges.values)
}
self._canRedo = {
structureManager.canRedo
structureManager.undoManager.canRedo
}
self._recordCellChange = nil // Structure uses custom editing logic
self._undoRowDeletion = nil
Expand All @@ -87,6 +87,12 @@ final class AnyChangeManager {

// MARK: - Public API

var undoManager: UndoManager? {
if let dataManager { return dataManager.undoManager }
if let structureManager { return structureManager.undoManager }
return nil
}

var canRedo: Bool {
_canRedo()
}
Expand Down
730 changes: 387 additions & 343 deletions TablePro/Core/ChangeTracking/DataChangeManager.swift

Large diffs are not rendered by default.

19 changes: 0 additions & 19 deletions TablePro/Core/ChangeTracking/DataChangeModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,6 @@ struct RowChangeKey: Hashable {
let type: ChangeType
}

/// Represents an action that can be undone
enum UndoAction {
case cellEdit(
rowIndex: Int,
columnIndex: Int,
columnName: String,
previousValue: String?,
newValue: String?
)
case rowInsertion(rowIndex: Int)
case rowDeletion(rowIndex: Int, originalRow: [String?])
/// Batch deletion of multiple rows (for undo as a single action)
case batchRowDeletion(rows: [(rowIndex: Int, originalRow: [String?])])
/// Batch insertion undo - when user deletes multiple inserted rows at once
case batchRowInsertion(rowIndices: [Int], rowValues: [[String?]])
}

// Note: TabPendingChanges is defined in QueryTab.swift

// MARK: - Array Extension

extension Array {
Expand Down
2 changes: 1 addition & 1 deletion TablePro/Core/SchemaTracking/StructureChangeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ final class StructureChangeManager {

// MARK: - Undo/Redo Support

private let undoManager: UndoManager = {
let undoManager: UndoManager = {
let manager = UndoManager()
manager.levelsOfUndo = 100
return manager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ internal final class MainSplitViewController: NSSplitViewController, InspectorVi
tableOperationOptions: sessionTableOperationOptionsBinding,
rightPanelState: rightPanelState,
tabManager: sessionState.tabManager,
changeManager: sessionState.changeManager,
filterStateManager: sessionState.filterStateManager,
toolbarState: sessionState.toolbarState,
coordinator: sessionState.coordinator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import Foundation
enum SessionStateFactory {
struct SessionState {
let tabManager: QueryTabManager
let changeManager: DataChangeManager
let filterStateManager: FilterStateManager
let columnVisibilityManager: ColumnVisibilityManager
let toolbarState: ConnectionToolbarState
Expand Down Expand Up @@ -44,8 +43,6 @@ enum SessionStateFactory {
payload: EditorTabPayload?
) -> SessionState {
let tabMgr = QueryTabManager()
let changeMgr = DataChangeManager()
changeMgr.databaseType = connection.type
let filterMgr = FilterStateManager()
let colVisMgr = ColumnVisibilityManager()
let toolbarSt = ConnectionToolbarState(connection: connection)
Expand Down Expand Up @@ -138,15 +135,13 @@ enum SessionStateFactory {
let coord = MainContentCoordinator(
connection: connection,
tabManager: tabMgr,
changeManager: changeMgr,
filterStateManager: filterMgr,
columnVisibilityManager: colVisMgr,
toolbarState: toolbarSt
)

return SessionState(
tabManager: tabMgr,
changeManager: changeMgr,
filterStateManager: filterMgr,
columnVisibilityManager: colVisMgr,
toolbarState: toolbarSt,
Expand Down
Loading
Loading