field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

TeraSubmissionViews.swift (4445B)


      1 import SwiftUI
      2 
      3 struct TeraSubmissionStatusView: View {
      4   @ObservedObject var store: TeraSubmissionStore
      5 
      6   var body: some View {
      7     if store.hasAction {
      8       Section("Submission") {
      9         if store.status?.canOfferStop != false {
     10           Button("Stop publication") { Task { await store.requestStop() } }
     11             .accessibilityIdentifier("tera.add.submission.stop")
     12         }
     13         if store.isWorking {
     14           ProgressView(store.status?.summary ?? "Checking the original submission request…")
     15             .accessibilityIdentifier("tera.add.submission.progress")
     16           Button("Stop waiting") { store.stopWaiting() }
     17             .accessibilityIdentifier("tera.add.submission.stop_waiting")
     18         }
     19         if !store.isWorking {
     20           if store.request != nil {
     21             Button("Check saved submission status") { Task { await store.refreshSelected() } }
     22               .accessibilityIdentifier("tera.add.submission.check")
     23           }
     24           if store.canContinue {
     25             Button("Continue original submission") { Task { await store.continueSelected() } }
     26               .accessibilityIdentifier("tera.add.submission.continue")
     27           }
     28         }
     29         if let status = store.status {
     30           Text(status.summary)
     31             .accessibilityIdentifier("tera.add.submission.status")
     32           if let explanation = status.retry.explanation {
     33             Text(explanation).accessibilityIdentifier("tera.add.submission.retry_status")
     34           }
     35           TeraPublicationTargetsView(details: status.targetDetails)
     36           if !status.media.isEmpty {
     37             Text(status.mediaSummary)
     38               .accessibilityIdentifier("tera.add.submission.media_status")
     39           }
     40           DisclosureGroup("Captured form") {
     41             Text(status.captured.form.editingValue.commandType.label).font(.headline)
     42             Text(status.captured.form.editingValue.content)
     43             if let title = status.captured.form.editingValue.title {
     44               Text(title)
     45             }
     46             Text("Editing continues separately. This submission keeps the form captured when you tapped Submit.")
     47               .font(.footnote)
     48           }
     49           .accessibilityIdentifier("tera.add.submission.captured")
     50         }
     51         if let message = store.message {
     52           Text(message).accessibilityIdentifier("tera.add.submission.message")
     53         }
     54         Text("Retry uses this original request. Choose New for another intentional submission.")
     55           .font(.footnote)
     56       }
     57     }
     58   }
     59 }
     60 
     61 struct TeraSubmissionInventoryView: View {
     62   @ObservedObject var store: TeraSubmissionStore
     63   @ObservedObject private var inventory: TeraSubmissionInventory
     64 
     65   init(store: TeraSubmissionStore) {
     66     self.store = store
     67     inventory = store.inventory
     68   }
     69 
     70   var body: some View {
     71     Section("Submissions") {
     72       if inventory.isLoading {
     73         ProgressView("Loading submissions…")
     74       }
     75       if let message = inventory.message {
     76         Text(message).foregroundStyle(.secondary)
     77       }
     78       ForEach(inventory.entries) { entry in
     79         switch entry {
     80         case let .submission(summary):
     81           VStack(alignment: .leading, spacing: 8) {
     82             Text(label(summary.state))
     83             Text(Date(timeIntervalSince1970: Double(summary.reservedAtUnixMilliseconds) / 1000),
     84                  format: .dateTime.year().month().day().hour().minute()).font(.caption)
     85             Button("View submission") { Task { await store.select(summary) } }
     86               .disabled(store.isWorking)
     87           }
     88           .accessibilityIdentifier("tera.add.submission.\(summary.id)")
     89         case let .repair(_, _, reason):
     90           Text(reason == .unsupportedSchema
     91             ? "This saved submission needs a compatible app. Its data is preserved."
     92             : "This submission needs attention. Its data is preserved; other work remains available.")
     93             .accessibilityIdentifier("tera.add.submission.repair")
     94         }
     95       }
     96       if inventory.cursor != nil {
     97         Button("Next submissions page") { inventory.more() }.disabled(inventory.isLoading)
     98       }
     99       Button("Reload submissions") { inventory.start() }.disabled(inventory.isLoading)
    100     }
    101     TeraSubmissionStatusView(store: store)
    102   }
    103 
    104   private func label(_ state: TeraSubmissionSummaryState) -> String {
    105     switch state {
    106     case .reserved: "Reserved; local preparation is pending."
    107     case let .operation(_, _, _, state): state.label
    108     }
    109   }
    110 }