TeraTodayDetailView.swift (2231B)
1 import SwiftUI 2 3 struct TeraTodayDetailView: View { 4 let card: TeraTodayCard 5 let context: TeraLocalNetwork? 6 @ObservedObject var mediaStore: TeraMediaStore 7 let canRevise: Bool 8 let canRetract: Bool 9 let revise: (TeraTodayCard) -> Void 10 let retract: (TeraTodayCard) -> Void 11 @State private var showsRetractionConfirmation = false 12 13 var body: some View { 14 List { 15 Section { 16 TeraTodayCardView(card: card, context: context, mediaStore: mediaStore, presentation: .detail) 17 } 18 if !card.thread.isEmpty { 19 Section("Conversation") { 20 ForEach(card.thread) { entry in 21 VStack(alignment: .leading, spacing: 4) { 22 Text(entry.authorProfile?.preferredName ?? entry.authorPublicKey) 23 .font(.subheadline.weight(.semibold)) 24 Text(entry.content) 25 TeraAuthorVisibilityMenu(author: entry.authorPublicKey) 26 Text(entry.type.rawValue.capitalized) 27 .font(.caption) 28 .foregroundStyle(.secondary) 29 } 30 .accessibilityElement(children: .contain) 31 } 32 } 33 } 34 } 35 .navigationTitle(card.type.label) 36 .navigationBarTitleDisplayMode(.inline) 37 .toolbar { 38 ToolbarItem(placement: .topBarTrailing) { 39 TeraAuthorVisibilityMenu(author: card.authorPublicKey) 40 } 41 if canRevise { 42 ToolbarItem(placement: .topBarTrailing) { 43 Button("Revise") { revise(card) } 44 .accessibilityIdentifier("radroots.today.revise") 45 } 46 } 47 if canRetract { 48 ToolbarItem(placement: .topBarTrailing) { 49 Button("Retract", role: .destructive) { showsRetractionConfirmation = true } 50 .accessibilityIdentifier("radroots.today.retract") 51 } 52 } 53 } 54 .confirmationDialog( 55 "Retract this post?", 56 isPresented: $showsRetractionConfirmation, 57 titleVisibility: .visible 58 ) { 59 Button("Retract post", role: .destructive) { retract(card) } 60 Button("Keep post", role: .cancel) {} 61 } message: { 62 Text("A signed retraction will be saved to the durable outbox before relay delivery.") 63 } 64 .accessibilityIdentifier("radroots.today.detail.\(card.id)") 65 } 66 }