import AppCore import ComposableArchitecture import SwiftUI import XXClient public struct SendRequestView: View { public init(store: StoreOf<SendRequestComponent>) { self.store = store } let store: StoreOf<SendRequestComponent> struct ViewState: Equatable { var contactUsername: String? var contactEmail: String? var contactPhone: String? var myUsername: String? var myEmail: String? var myPhone: String? var sendUsername: Bool var sendEmail: Bool var sendPhone: Bool var isSending: Bool var failure: String? init(state: SendRequestComponent.State) { contactUsername = try? state.contact.getFact(.username)?.value contactEmail = try? state.contact.getFact(.email)?.value contactPhone = try? state.contact.getFact(.phone)?.value myUsername = try? state.myContact?.getFact(.username)?.value myEmail = try? state.myContact?.getFact(.email)?.value myPhone = try? state.myContact?.getFact(.phone)?.value sendUsername = state.sendUsername sendEmail = state.sendEmail sendPhone = state.sendPhone isSending = state.isSending failure = state.failure } } public var body: some View { WithViewStore(store, observe: ViewState.init) { viewStore in Form { Section { Button { viewStore.send(.set(\.$sendUsername, !viewStore.sendUsername)) } label: { HStack { Label(viewStore.myUsername ?? "", systemImage: "person") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendUsername ? "checkmark.circle.fill" : "circle") .foregroundColor(.accentColor) } } .animation(.default, value: viewStore.sendUsername) Button { viewStore.send(.set(\.$sendEmail, !viewStore.sendEmail)) } label: { HStack { Label(viewStore.myEmail ?? "", systemImage: "envelope") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendEmail ? "checkmark.circle.fill" : "circle") .foregroundColor(.accentColor) } } .animation(.default, value: viewStore.sendEmail) Button { viewStore.send(.set(\.$sendPhone, !viewStore.sendPhone)) } label: { HStack { Label(viewStore.myPhone ?? "", systemImage: "phone") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendPhone ? "checkmark.circle.fill" : "circle") .foregroundColor(.accentColor) } } .animation(.default, value: viewStore.sendPhone) } header: { Text("My facts") } .disabled(viewStore.isSending) Section { Label(viewStore.contactUsername ?? "", systemImage: "person") Label(viewStore.contactEmail ?? "", systemImage: "envelope") Label(viewStore.contactPhone ?? "", systemImage: "phone") } header: { Text("Contact") } Section { Button { viewStore.send(.sendTapped) } label: { HStack { Text("Send request") Spacer() if viewStore.isSending { ProgressView() } else { Image(systemName: "paperplane") } } } } .disabled(viewStore.isSending) if let failure = viewStore.failure { Section { Text(failure) } header: { Text("Error") } } } .navigationTitle("Send Request") .task { viewStore.send(.start) } } } } #if DEBUG public struct SendRequestView_Previews: PreviewProvider { public static var previews: some View { NavigationView { SendRequestView(store: Store( initialState: SendRequestComponent.State( contact: { var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!) contact.getFactsFromContact.run = { _ in [ Fact(type: .username, value: "contact-username"), Fact(type: .email, value: "contact-email"), Fact(type: .phone, value: "contact-phone"), ] } return contact }(), myContact: { var contact = XXClient.Contact.unimplemented("my-data".data(using: .utf8)!) contact.getFactsFromContact.run = { _ in [ Fact(type: .username, value: "my-username"), Fact(type: .email, value: "my-email"), Fact(type: .phone, value: "my-phone"), ] } return contact }(), sendUsername: true, sendEmail: false, sendPhone: true, isSending: false, failure: "Something went wrong" ), reducer: EmptyReducer() )) } } } #endif