Added
- Inline AI suggestions (ghost text) in the SQL editor — auto-triggers on typing pause, Tab to accept, Escape to dismiss
- Schema-aware inline suggestions — AI now uses actual table/column names from the connected database (cached with 30s TTL, respects
includeSchemaandmaxSchemaTablessettings) - AI feature highlight row on onboarding features page
- Added VoiceOver accessibility labels to custom controls: data grid (table view, column headers, cells), filter panel (logic toggle, presets, action buttons, filter row controls), toolbar buttons (connection switcher, database switcher, refresh, export, import, filter toggle, history toggle, inspector toggle), editor tab bar (tab items, close buttons, add tab button), and sidebar (table/view rows, search clear button)
Changed
- Migrated notification observers in
MainContentCommandActionsfrom Combine publishers (.publisher(for:).sink) to async sequences (for awaitoverNotificationCenter.default.notifications(named:)) — removesAnyCancellablestorage in favor ofTaskhandles with proper cancellation on deinit - Migrated tab state persistence from UserDefaults to file-based storage in Application Support — prevents large JSON payloads from bloating the plist loaded at app launch, with automatic one-time migration of existing data
- Refactored menu and toolbar commands from NotificationCenter to
@FocusedObjectpattern — menu commands and toolbar buttons now callMainContentCommandActionsmethods directly instead of posting global notifications, with context-aware routing for structure view operations - Redesigned connection form with tab-based layout (General / SSH Tunnel / SSL/TLS / Advanced), replacing the single-scroll layout
- Revamped connection form UI to use native macOS grouped form style (
Form/.formStyle(.grouped)) withLabeledContentfor automatic label-value alignment andSectionheaders — replacing the previous hand-rolledVStacklayout with customFormFieldcomponent - Removed unused
FormFieldcomponent and helper methods (iconForType,colorForType) - SQLite connections now only show General and Advanced tabs (SSH/SSL hidden)
- Added async/await wrapper methods to
QueryHistoryStorage— existing completion-handler API preserved for compatibility, newasyncoverloads usewithCheckedContinuationfor modern Swift concurrency callers
Fixed
- Fixed TOCTOU race condition in
SQLiteDriver— replacednonisolated(unsafe)+ DispatchQueue pattern with a dedicated actor (SQLiteConnectionActor) that serializes all sqlite3 handle access, preventing concurrent task races on the connection state - Consolidated multiple
.sheet(isPresented:)modifiers inMainContentViewinto a single.sheet(item:)with anActiveSheetenum — fixes SwiftUI anti-pattern where only the last.sheetmodifier reliably activates - Replaced blocking
Process.waitUntilExit()calls inSSHTunnelManagerwith asyncwithCheckedContinuation-based waiting, and replaced the fixed 1.5s sleep with active port probing — SSH tunnel setup no longer blocks the actor thread, keeping the UI responsive during connection - Eliminated potential deadlocks in
MariaDBConnectionandLibPQConnection— replaced allqueue.synccalls (indisconnect,deinit,isConnected,serverVersion) with lock-protected cached state andqueue.asynccleanup, preventing deadlocks when callbacks re-enter the connection queue - SQL editor now respects the macOS accessibility text size preference (System Settings > Accessibility > Display > Text Size) — the user's chosen font size is scaled by the system's preferred text size factor, with live updates when the setting changes
- Fixed retain cycle in
UpdaterBridge—.assign(to:on:self)retains self strongly; replaced with.sinkusing[weak self] - Fixed leaked NotificationCenter observer in
SQLEditorCoordinator— observer token is now stored and removed indestroy() - Eliminated tab switching delay — replaced view teardown/recreation with
ZStack+ForEachto keep NSViews alive, moved tab persistence I/O to background threads, skipped unnecessary change-tracking deep copies, and coalesced redundant inspector/sidebar updates during tab switch - Reduced tab-switch CPU spikes from 40-60% to ~10-20% by eliminating redundant
reloadData()calls:configureForTableno longer triggers a reload during tab switch (single controlled bump instead of 2-3),onChange(of: resultColumns)is suppressed while the switch is in progress, andDataGridView.updateNSViewskips all heavy work when the data identity hasn't changed - Table open now shows data instantly — split
executeQueryInternalinto two phases: rows display immediately after SELECT completes, metadata (columns, FKs, enums, row count) loads in the background without blocking the grid - Eliminated 20-80ms overhead when clicking an already-open table in the sidebar —
openTableTabshort-circuits immediately, andTableProTabSmartno longer fires@Publishedwhen the selected tab hasn't changed - Keychain
SecItemAddreturn values are now checked and logged — previously, failed writes (e.g.errSecDuplicateItem,errSecInteractionNotAllowed) were silently discarded, risking password loss - Added
kSecAttrServiceto all Keychain queries acrossConnectionStorage,LicenseStorage, andAIKeyStorage— items now have a proper service identifier, preventing potential collisions with other apps - Ensured proper cleanup for
@Statereference type tokens — tracked untrackedTaskinstances inImportDialog(file selection),AIProviderEditorSheet(model fetching, connection test), and addedonDisappearcancellation to prevent leaked work after view dismissal - Replaced
.onAppearwith.taskfor I/O operations inConnectionTagEditor— uses SwiftUI-idiomatic lifecycle-tied loading instead ofonAppearwhich can re-fire on navigation