| 1 | import Ed |
| 2 | import SwiftUI |
| 3 | |
| 4 | struct ContentView: View { |
| 5 | @StateObject private var model = ChatViewModel() |
| 6 | |
| 7 | var body: some View { |
| 8 | NavigationStack { |
| 9 | VStack(spacing: 16) { |
| 10 | ScrollView { |
| 11 | Text(model.transcript.isEmpty ? "Load Ed, then ask about the battery or save a note." : model.transcript) |
| 12 | .frame(maxWidth: .infinity, alignment: .leading) |
| 13 | } |
| 14 | |
| 15 | TextField("Message Ed", text: $model.input) |
| 16 | .textFieldStyle(.roundedBorder) |
| 17 | |
| 18 | HStack { |
| 19 | Button(model.isLoaded ? "Loaded" : "Load Ed") { |
| 20 | Task { await model.load() } |
| 21 | } |
| 22 | .disabled(model.isBusy || model.isLoaded) |
| 23 | |
| 24 | Button("Send") { |
| 25 | Task { await model.send() } |
| 26 | } |
| 27 | .buttonStyle(.borderedProminent) |
| 28 | .disabled(model.isBusy || !model.isLoaded || model.input.isEmpty) |
| 29 | } |
| 30 | |
| 31 | Text(model.status) |
| 32 | .font(.caption) |
| 33 | .foregroundStyle(.secondary) |
| 34 | } |
| 35 | .padding() |
| 36 | .navigationTitle("Ed") |
| 37 | .confirmationDialog( |
| 38 | "Allow Ed to change app data?", |
| 39 | isPresented: $model.showApproval, |
| 40 | titleVisibility: .visible |
| 41 | ) { |
| 42 | Button("Allow once") { model.resolveApproval(.allowOnce) } |
| 43 | Button("Allow for this session") { model.resolveApproval(.allowForSession) } |
| 44 | Button("Deny", role: .cancel) { model.resolveApproval(.deny) } |
| 45 | } message: { |
| 46 | Text(model.approvalSummary) |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | } |