@@ -71,9 +71,8 @@ struct QueryView: View {
71 .disabled(viewModel.sqlQuery.isEmpty)
71 .disabled(viewModel.sqlQuery.isEmpty)
72 .accessibilityLabel("Save query")
72 .accessibilityLabel("Save query")
75− Button("Export as JSON") { exportJSON() }
75+ exportResults()
76− Button("Export as CSV") { exportCSV() }
77 } label: {
76 } label: {
78 Image(systemName: "square.and.arrow.up")
77 Image(systemName: "square.and.arrow.up")
@@ -337,36 +336,26 @@ struct QueryView: View {
340− private func exportJSON() {
339+ private func exportResults() {
341− let results = viewModel.results
342− saveToFile(type: "json") {
343− let encoder = JSONEncoder()
344− encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
346− let data = try encoder.encode(results)
347− return String(data: data, encoding: .utf8) ?? "[]"
354− private func exportCSV() {
355− let results = viewModel.results
356− let columns = viewModel.visibleColumns
357− saveToFile(type: "csv") {
358− QueryViewModel.buildCSV(records: results, columns: columns)
362− private func saveToFile(type: String, generate: @Sendable @escaping () -> String?) {
363 let panel = NSSavePanel()
340 let panel = NSSavePanel()
364− panel.allowedContentTypes = type == "json" ? [.json] : [.commaSeparatedText]
341+ panel.allowedContentTypes = [.json, .commaSeparatedText]
365− panel.nameFieldStringValue = "export.\(type)"
342+ panel.nameFieldStringValue = "export.json"
366 panel.begin { result in
343 panel.begin { result in
367 guard result == .OK, let url = panel.url else { return }
344 guard result == .OK, let url = panel.url else { return }
345+ let isCSV = url.pathExtension.lowercased() == "csv"
346+ let results = viewModel.results
347+ let columns = viewModel.visibleColumns
368 Task.detached(priority: .userInitiated) {
348 Task.detached(priority: .userInitiated) {
349+ let content: String?
351+ content = QueryViewModel.buildCSV(records: results, columns: columns)
353+ let encoder = JSONEncoder()
354+ encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
355+ content = (try? encoder.encode(results))
356+ .flatMap { String(data: $0, encoding: .utf8) }
369− guard let content = generate() else {
358+ guard let content else {
370 await MainActor.run {
359 await MainActor.run {
371 exportError = "Failed to encode data for export"
360 exportError = "Failed to encode data for export"
372 showExportError = true
361 showExportError = true