new ui
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import Foundation
|
||||
import AppKit
|
||||
import Security
|
||||
|
||||
struct ConnectionProfile: Identifiable, Codable, Hashable {
|
||||
@@ -39,10 +40,40 @@ enum PasswordStore {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct WorkbenchQueryTab: Identifiable {
|
||||
let id: UUID
|
||||
var title: String
|
||||
var sql: String
|
||||
var result: QueryResult
|
||||
var fileURL: URL?
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
title: String,
|
||||
sql: String = "",
|
||||
result: QueryResult = QueryResult(),
|
||||
fileURL: URL? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.sql = sql
|
||||
self.result = result
|
||||
self.fileURL = fileURL
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class DatabaseModel: ObservableObject {
|
||||
@Published var profiles: [ConnectionProfile] = []
|
||||
@Published var selectedID: UUID?
|
||||
@Published var queryTabs: [WorkbenchQueryTab] = [
|
||||
WorkbenchQueryTab(
|
||||
title: "Query 1",
|
||||
sql: "SELECT VERSION() AS server_version;"
|
||||
)
|
||||
]
|
||||
@Published var activeQueryID: UUID?
|
||||
@Published var sql = "SELECT VERSION() AS server_version;"
|
||||
@Published var result = QueryResult()
|
||||
@Published var databases: [String] = []
|
||||
@@ -58,7 +89,109 @@ final class DatabaseModel: ObservableObject {
|
||||
let decoded = try? JSONDecoder().decode([ConnectionProfile].self, from: data) { profiles = decoded }
|
||||
if profiles.isEmpty { profiles = [ConnectionProfile()] }
|
||||
selectedID = profiles.first?.id
|
||||
activeQueryID = queryTabs.first?.id
|
||||
}
|
||||
|
||||
func newQueryTab() {
|
||||
saveActiveQuery()
|
||||
let tab = WorkbenchQueryTab(
|
||||
title: "Query \\(queryTabs.count + 1)"
|
||||
)
|
||||
queryTabs.append(tab)
|
||||
activeQueryID = tab.id
|
||||
sql = tab.sql
|
||||
result = tab.result
|
||||
}
|
||||
|
||||
func saveActiveQuery() {
|
||||
guard let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
queryTabs[index].sql = sql
|
||||
queryTabs[index].result = result
|
||||
}
|
||||
|
||||
func activateQuery(_ id: UUID) {
|
||||
saveActiveQuery()
|
||||
|
||||
guard let tab = queryTabs.first(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
activeQueryID = tab.id
|
||||
sql = tab.sql
|
||||
result = tab.result
|
||||
}
|
||||
|
||||
func closeQuery(_ id: UUID) {
|
||||
saveActiveQuery()
|
||||
queryTabs.removeAll { $0.id == id }
|
||||
|
||||
if queryTabs.isEmpty {
|
||||
let tab = WorkbenchQueryTab(title: "Query 1")
|
||||
queryTabs.append(tab)
|
||||
}
|
||||
|
||||
if activeQueryID == id {
|
||||
activeQueryID = nil
|
||||
activateQuery(queryTabs[0].id)
|
||||
}
|
||||
}
|
||||
|
||||
func openSQLScript() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.allowedContentTypes = [.plainText]
|
||||
panel.allowsOtherFileTypes = true
|
||||
panel.canChooseDirectories = false
|
||||
|
||||
guard panel.runModal() == .OK,
|
||||
let url = panel.url,
|
||||
let contents = try? String(contentsOf: url, encoding: .utf8)
|
||||
else { return }
|
||||
|
||||
saveActiveQuery()
|
||||
|
||||
let tab = WorkbenchQueryTab(
|
||||
title: url.lastPathComponent,
|
||||
sql: contents,
|
||||
fileURL: url
|
||||
)
|
||||
|
||||
queryTabs.append(tab)
|
||||
activateQuery(tab.id)
|
||||
status = "Opened \\(url.lastPathComponent)"
|
||||
}
|
||||
|
||||
func saveSQLScript(asNewFile: Bool = false) {
|
||||
saveActiveQuery()
|
||||
|
||||
guard let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id })
|
||||
else { return }
|
||||
|
||||
var destination = asNewFile ? nil : queryTabs[index].fileURL
|
||||
|
||||
if destination == nil {
|
||||
let panel = NSSavePanel()
|
||||
panel.nameFieldStringValue = "query.sql"
|
||||
panel.canCreateDirectories = true
|
||||
|
||||
guard panel.runModal() == .OK else { return }
|
||||
destination = panel.url
|
||||
}
|
||||
|
||||
guard let url = destination else { return }
|
||||
|
||||
do {
|
||||
try sql.write(to: url, atomically: true, encoding: .utf8)
|
||||
queryTabs[index].fileURL = url
|
||||
queryTabs[index].title = url.lastPathComponent
|
||||
status = "Saved \\(url.lastPathComponent)"
|
||||
} catch {
|
||||
status = "Save failed: \\(error.localizedDescription)"
|
||||
}
|
||||
}
|
||||
|
||||
var selected: ConnectionProfile? { profiles.first { $0.id == selectedID } }
|
||||
func save(_ profile: ConnectionProfile, password: String) {
|
||||
if let i = profiles.firstIndex(where: { $0.id == profile.id }) { profiles[i] = profile }
|
||||
@@ -178,6 +311,11 @@ final class DatabaseModel: ObservableObject {
|
||||
status = "Connected to \(profile.name)"
|
||||
} else {
|
||||
result = parsed
|
||||
if let id = activeQueryID,
|
||||
let index = queryTabs.firstIndex(where: { $0.id == id }) {
|
||||
queryTabs[index].sql = sql
|
||||
queryTabs[index].result = parsed
|
||||
}
|
||||
status = "Query completed (\(parsed.rows.count) rows)"
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user