added typeaheead and introspetion

This commit is contained in:
Mark Gregory
2026-10-18 17:28:38 +01:00
parent 543b639ffc
commit c102bef2a6
4 changed files with 34 additions and 8 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ struct DBSynApp: App {
NSApplication.shared.orderFrontStandardAboutPanel(options: [
.applicationName: "DBSyn",
.applicationIcon: icon ?? NSApplication.shared.applicationIconImage,
.version: "Phase 61",
.version: Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "1.0",
.credits: NSAttributedString(string: "Native MySQL client for macOS")
])
}
+2 -1
View File
@@ -462,7 +462,8 @@ final class DatabaseModel: ObservableObject {
columns[row[0], default: []].append(column)
}
// Ignore results from a connection that has been removed while loading.
guard profiles.contains(where: { $0.id == profile.id }) else { return }
guard profiles.contains(where: { $0.id == profile.id }),
selected?.id == profile.id else { return }
let previous = introspections[key]
let current = SchemaIntrospection(
connectionID: profile.id, database: database,
+10 -6
View File
@@ -1553,10 +1553,9 @@ struct SQLTextView: NSViewRepresentable {
let selection = editor.selectedRange()
editor.string = text
let safeLocation = min(
selection.location,
(text as NSString).length
)
let safeLocation = selection.location == NSNotFound
? 0
: min(selection.location, (text as NSString).length)
editor.setSelectedRange(
NSRange(location: safeLocation, length: 0)
@@ -1579,6 +1578,7 @@ struct SQLTextView: NSViewRepresentable {
deinit {
pendingCompletion?.cancel()
suggestionPopover?.close()
if let keyMonitor { NSEvent.removeMonitor(keyMonitor) }
}
@@ -1617,7 +1617,10 @@ struct SQLTextView: NSViewRepresentable {
let source = editor.string as NSString
guard selection.location <= source.length else { dismissSuggestions(); return }
let before = source.substring(to: selection.location)
let expression = try! NSRegularExpression(pattern: #"[A-Za-z_][A-Za-z0-9_]*$"#)
guard let expression = try? NSRegularExpression(pattern: #"[A-Za-z_][A-Za-z0-9_]*$"#) else {
dismissSuggestions()
return
}
let beforeRange = NSRange(location: 0, length: (before as NSString).length)
guard let match = expression.matches(in: before, range: beforeRange).last else { dismissSuggestions(); return }
let prefix = (before as NSString).substring(with: match.range)
@@ -1678,7 +1681,8 @@ struct SQLTextView: NSViewRepresentable {
if keyMonitor == nil {
keyMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [weak self, weak editor] event in
guard let self, let editor, self.suggestionPopover?.isShown == true,
editor.window != nil else { return event }
let window = editor.window, window.isKeyWindow,
window.firstResponder === editor else { return event }
switch event.keyCode {
case 53: self.dismissSuggestions(); return nil // Escape
case 36, 48: self.acceptSuggestion(editor); return nil // Return / Tab
+21
View File
@@ -0,0 +1,21 @@
# Phase 70 — UI and stability hardening
This phase deliberately avoids adding new database-changing operations.
## Editor stability
- Avoids a forced regular-expression unwrap when preparing suggestions.
- Prevents the SQL editor's local key monitor from consuming Enter, Tab, Escape or arrow keys when another control/window has focus.
- Closes suggestion popovers and removes event monitors when the editor coordinator is released.
- Handles invalid text-selection positions safely when SQL is updated programmatically.
## Introspection consistency
- Discards introspection results from a connection that is no longer selected, preventing an asynchronous response from applying a different connection's metadata to the active editor.
## About panel
- Reads the application version from its actual bundle metadata rather than displaying an obsolete phase label.
## Verification still required on macOS
- Build the Xcode scheme and test SQL editing, completion navigation and keyboard focus changes.
- Switch connections during a long introspection request and confirm stale results are not shown.
- Check System, Light and Dark appearance, and the existing graphs and administration screens.
- Run live MySQL regression tests before treating this as a release candidate.