TeraDraftInventoryModels.swift (3474B)
1 import Foundation 2 3 enum TeraDraftRecoverySelection { 4 case composer(String) 5 case legacy(String) 6 } 7 8 enum TeraRecoveredDraft { 9 case composer(TeraComposerDraft) 10 case legacy(TeraDraftStatus) 11 } 12 13 /// Metadata for an author-owned legacy operation. It carries no composer context. 14 struct TeraLegacyDraftSummary: Sendable, Equatable, Identifiable { 15 let id: String 16 let revision: UInt64 17 let kind: TeraDraftKind 18 let commandType: TeraAddCommandType 19 let state: TeraOutboxState 20 let hasForm: Bool 21 let isRevision: Bool 22 let createdAtUnixMilliseconds: UInt64 23 let updatedAtUnixMilliseconds: UInt64 24 let mediaCount: UInt64 25 let verifiedMediaCount: UInt64 26 let possibleOrphanCount: UInt64 27 let settlement: TeraOperationSettlement? 28 var revisionParentID: String? 29 var coordinateWritable = true 30 var coordinateCaptured = false 31 32 var canAdvance: Bool { 33 coordinateWritable && state.canAdvance 34 } 35 36 var canQueue: Bool { 37 coordinateWritable && (state.isEditable || state == .readyToSign) 38 } 39 40 var isEditable: Bool { 41 !coordinateCaptured && state.isEditable 42 } 43 44 var honestSummary: String { 45 if !coordinateWritable, ![.complete, .cancelled, .terminal].contains(state) { 46 return TeraPublicationActionReason.coordinateChanged.explanation 47 } 48 if isRevision { 49 return "Saved revision; open details for current relay outcomes." 50 } 51 if revisionParentID != nil { 52 return "Retraction belongs to a saved revision." 53 } 54 return state.summary(settlement: settlement) 55 } 56 57 var mediaSummary: String { 58 let verified = "\(verifiedMediaCount) of \(mediaCount) photos verified" 59 return possibleOrphanCount > 0 ? "\(verified); \(possibleOrphanCount) possible orphan" : verified 60 } 61 } 62 63 enum TeraLegacyDraftRepairReason: Sendable, Equatable { 64 case unsupportedSchema 65 case corruptRecord 66 case needsAttention 67 } 68 69 enum TeraLegacyDraftListEntry: Sendable, Equatable { 70 case draft(TeraLegacyDraftSummary) 71 case repair(draftKey: String, revision: UInt64, reason: TeraLegacyDraftRepairReason) 72 } 73 74 struct TeraLegacyDraftPage: Sendable, Equatable { 75 let authorPublicKey: String 76 let entries: [TeraLegacyDraftListEntry] 77 let nextCursor: String? 78 } 79 80 extension TeraComposerForm { 81 /// Rehydrates editing metadata only; a reference is never an open file or 82 /// proof that an upload exists. The media owner must reopen and validate it. 83 var editingValue: TeraAddForm { 84 var form = TeraAddForm(commandType: commandType) 85 form.content = content 86 form.identifier = identifier 87 form.title = title 88 form.summary = summary 89 form.location = location 90 form.eventTiming = eventTiming 91 form.eventStartDate = eventStartDate 92 form.eventEndDate = eventEndDate 93 form.eventStartUnixSeconds = eventStartUnixSeconds 94 form.eventEndUnixSeconds = eventEndUnixSeconds 95 form.eventTimezone = eventTimezone 96 form.priceAmount = priceAmount 97 form.currency = currency 98 form.unit = unit 99 form.quantity = quantity 100 form.foodPublishedAtUnixSeconds = foodPublishedAtUnixSeconds 101 form.foodStatus = foodStatus 102 form.media = media.map { value in 103 TeraPreparedMedia(opaqueReference: value.opaqueReference, remoteURL: nil, 104 sha256: value.sha256, mediaType: value.mediaType, byteSize: value.byteSize, 105 width: value.width, height: value.height, alt: value.alt, 106 preparedAtUnixSeconds: value.preparedAtUnixSeconds) 107 } 108 return form 109 } 110 }