wire TOML export/import to iOS session browser

This commit is contained in:
jess 2026-04-02 21:16:29 -07:00
parent 311fb8ecc7
commit 8e1153585b
1 changed files with 64 additions and 0 deletions

View File

@ -1,5 +1,6 @@
import SwiftUI
import GRDB
import UniformTypeIdentifiers
struct SessionView: View {
@Bindable var state: AppState
@ -191,6 +192,9 @@ struct SessionDetailView: View {
@State private var editing = false
@State private var editLabel = ""
@State private var editNotes = ""
@State private var showingFileImporter = false
@State private var showingShareSheet = false
@State private var exportFileURL: URL?
var body: some View {
VStack(alignment: .leading, spacing: 0) {
@ -201,6 +205,16 @@ struct SessionDetailView: View {
.onAppear { loadMeasurements() }
.onChange(of: session.id) { loadMeasurements() }
.sheet(isPresented: $editing) { editSheet }
.sheet(isPresented: $showingShareSheet) {
if let url = exportFileURL {
ShareSheet(items: [url])
}
}
.fileImporter(
isPresented: $showingFileImporter,
allowedContentTypes: [.plainText],
onCompletion: handleImportedFile
)
}
private func loadMeasurements() {
@ -208,6 +222,40 @@ struct SessionDetailView: View {
measurements = (try? Storage.shared.fetchMeasurements(sessionId: sid)) ?? []
}
private func exportSession() {
guard let sid = session.id else { return }
do {
let toml = try Storage.shared.exportSession(sid)
let name = (session.label ?? "session").replacingOccurrences(of: " ", with: "_")
let url = FileManager.default.temporaryDirectory.appendingPathComponent("\(name).toml")
try toml.write(to: url, atomically: true, encoding: .utf8)
exportFileURL = url
showingShareSheet = true
} catch {
state.status = "Export failed: \(error.localizedDescription)"
}
}
private func handleImportedFile(_ result: Result<URL, Error>) {
switch result {
case .success(let url):
guard url.startAccessingSecurityScopedResource() else {
state.status = "Cannot access file"
return
}
defer { url.stopAccessingSecurityScopedResource() }
do {
let toml = try String(contentsOf: url, encoding: .utf8)
let _ = try Storage.shared.importSession(from: toml)
state.status = "Session imported"
} catch {
state.status = "Import failed: \(error.localizedDescription)"
}
case .failure(let error):
state.status = "File error: \(error.localizedDescription)"
}
}
private var header: some View {
VStack(alignment: .leading, spacing: 4) {
HStack {
@ -222,6 +270,14 @@ struct SessionDetailView: View {
Image(systemName: "pencil.circle")
.imageScale(.large)
}
Button(action: { exportSession() }) {
Image(systemName: "square.and.arrow.up")
.imageScale(.large)
}
Button(action: { showingFileImporter = true }) {
Image(systemName: "square.and.arrow.down")
.imageScale(.large)
}
}
HStack {
Text(session.startedAt, style: .date)
@ -368,3 +424,11 @@ struct MeasurementRow: View {
return (try? Storage.shared.dataPointCount(measurementId: mid)) ?? 0
}
}
struct ShareSheet: UIViewControllerRepresentable {
let items: [Any]
func makeUIViewController(context: Context) -> UIActivityViewController {
UIActivityViewController(activityItems: items, applicationActivities: nil)
}
func updateUIViewController(_ vc: UIActivityViewController, context: Context) {}
}