diff --git a/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/FactHelpers.swift b/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/FactHelpers.swift new file mode 100644 index 0000000000000000000000000000000000000000..83f040328725444dbe4e99413b7061794da20eb0 --- /dev/null +++ b/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/FactHelpers.swift @@ -0,0 +1,55 @@ +import XXClient + +// TODO: Move to XXClient library + +public enum FactType: Equatable { + case username + case email + case phone + case other(Int) + + public static let knownTypes: [Self] = [.username, .email, .phone] + + public init(rawValue: Int) { + if let known = FactType.knownTypes.first(where: { $0.rawValue == rawValue }) { + self = known + } else { + self = .other(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .username: return 0 + case .email: return 1 + case .phone: return 2 + case .other(let rawValue): return rawValue + } + } +} + +extension Array where Element == Fact { + public func get(_ type: FactType) -> Fact? { + first(where: { $0.type == type.rawValue }) + } + + public mutating func set(_ type: FactType, _ value: String?) { + removeAll(where: { $0.type == type.rawValue }) + if let value = value { + append(Fact(fact: value, type: type.rawValue)) + sort(by: { $0.type < $1.type }) + } + } +} + +extension Contact { + public func getFact(_ type: FactType) throws -> Fact? { + try getFacts().get(type) + } + + public mutating func setFact(_ type: FactType, _ value: String?) throws { + var facts = try getFacts() + facts.set(type, value) + try setFacts(facts) + } +} diff --git a/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/XXContact+Helpers.swift b/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/XXContact+Helpers.swift deleted file mode 100644 index d2c9368325bab7d72b3f796248744df636e5f47a..0000000000000000000000000000000000000000 --- a/Examples/xx-messenger/Sources/AppCore/XXClientHelpers/XXContact+Helpers.swift +++ /dev/null @@ -1,15 +0,0 @@ -import XXClient - -extension Contact { - public var username: String? { - try? getFacts().first(where: { $0.type == 0 })?.fact - } - - public var email: String? { - try? getFacts().first(where: { $0.type == 1 })?.fact - } - - public var phone: String? { - try? getFacts().first(where: { $0.type == 2 })?.fact - } -} diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift index b8da32a49dc4abdb6a50e858ce0ef56432ce4517..8126b792074a9a82050228cc0d0edbe8d26742ce 100644 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift @@ -105,13 +105,13 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm var dbContact = state.dbContact ?? XXModels.Contact(id: state.id) dbContact.marshaled = xxContact.data if state.importUsername { - dbContact.username = xxContact.username + dbContact.username = try? xxContact.getFact(.username)?.fact } if state.importEmail { - dbContact.email = xxContact.email + dbContact.email = try? xxContact.getFact(.email)?.fact } if state.importPhone { - dbContact.phone = xxContact.phone + dbContact.phone = try? xxContact.getFact(.phone)?.fact } _ = try! env.db().saveContact(dbContact) } diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift index a3b6ee085a95b3bb0946f3d861d45c37a087c026..48743b07af69b695c6f6ec34159d2b0c75400458 100644 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift @@ -15,14 +15,20 @@ public struct ContactView: View { struct ViewState: Equatable { var dbContact: XXModels.Contact? - var xxContact: XXClient.Contact? + var xxContactIsSet: Bool + var xxContactUsername: String? + var xxContactEmail: String? + var xxContactPhone: String? var importUsername: Bool var importEmail: Bool var importPhone: Bool init(state: ContactState) { dbContact = state.dbContact - xxContact = state.xxContact + xxContactIsSet = state.xxContact != nil + xxContactUsername = try? state.xxContact?.getFact(.username)?.fact + xxContactEmail = try? state.xxContact?.getFact(.email)?.fact + xxContactPhone = try? state.xxContact?.getFact(.phone)?.fact importUsername = state.importUsername importEmail = state.importEmail importPhone = state.importPhone @@ -32,13 +38,13 @@ public struct ContactView: View { public var body: some View { WithViewStore(store.scope(state: ViewState.init)) { viewStore in Form { - if let xxContact = viewStore.xxContact { + if viewStore.xxContactIsSet { Section { Button { viewStore.send(.set(\.$importUsername, !viewStore.importUsername)) } label: { HStack { - Label(xxContact.username ?? "", systemImage: "person") + Label(viewStore.xxContactUsername ?? "", systemImage: "person") .tint(Color.primary) Spacer() Image(systemName: viewStore.importUsername ? "checkmark.circle.fill" : "circle") @@ -50,7 +56,7 @@ public struct ContactView: View { viewStore.send(.set(\.$importEmail, !viewStore.importEmail)) } label: { HStack { - Label(xxContact.email ?? "", systemImage: "envelope") + Label(viewStore.xxContactEmail ?? "", systemImage: "envelope") .tint(Color.primary) Spacer() Image(systemName: viewStore.importEmail ? "checkmark.circle.fill" : "circle") @@ -62,7 +68,7 @@ public struct ContactView: View { viewStore.send(.set(\.$importPhone, !viewStore.importPhone)) } label: { HStack { - Label(xxContact.phone ?? "", systemImage: "phone") + Label(viewStore.xxContactPhone ?? "", systemImage: "phone") .tint(Color.primary) Spacer() Image(systemName: viewStore.importPhone ? "checkmark.circle.fill" : "circle") diff --git a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift index fcb9c62e07c28abad5306b29003b8db32ae61b38..cb43c43056f6d3e53c2b73b4bdfc10189f052b21 100644 --- a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift +++ b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift @@ -83,10 +83,7 @@ public let registerReducer = Reducer<RegisterState, RegisterAction, RegisterEnvi let db = try env.db() try env.messenger.register(username: username) var contact = try env.messenger.e2e.tryGet().getContact() - var facts: [Fact] = try contact.getFacts() - facts.removeAll(where: { $0.type == 0 }) - facts.append(Fact(fact: username, type: 0)) - try contact.setFacts(facts) + try contact.setFact(.username, username) try db.saveContact(Contact( id: try contact.getId(), marshaled: contact.data, diff --git a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift index 684e344a914e4478f4657010fa72da310cad1d8f..f2625b91e6a4042624ad68141515ab34ace7c90c 100644 --- a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift +++ b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift @@ -110,13 +110,13 @@ public let sendRequestReducer = Reducer<SendRequestState, SendRequestAction, Sen try updateAuthStatus(.requesting) let myFacts = try state.myContact?.getFacts() ?? [] var includedFacts: [Fact] = [] - if state.sendUsername, let fact = myFacts.first(where: { $0.type == 0 }) { + if state.sendUsername, let fact = myFacts.get(.username) { includedFacts.append(fact) } - if state.sendEmail, let fact = myFacts.first(where: { $0.type == 1 }) { + if state.sendEmail, let fact = myFacts.get(.email) { includedFacts.append(fact) } - if state.sendPhone, let fact = myFacts.first(where: { $0.type == 2 }) { + if state.sendPhone, let fact = myFacts.get(.phone) { includedFacts.append(fact) } _ = try env.messenger.e2e.tryGet().requestAuthenticatedChannel( diff --git a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestView.swift b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestView.swift index 159d10e82d14e72c64fe778dbf1b94e248f4be02..5f1cd7d53e8300fc55ffc907a410fb66c2b92c77 100644 --- a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestView.swift +++ b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestView.swift @@ -11,8 +11,12 @@ public struct SendRequestView: View { let store: Store<SendRequestState, SendRequestAction> struct ViewState: Equatable { - var contact: XXClient.Contact - var myContact: XXClient.Contact? + 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 @@ -20,8 +24,12 @@ public struct SendRequestView: View { var failure: String? init(state: SendRequestState) { - contact = state.contact - myContact = state.myContact + contactUsername = try? state.contact.getFact(.username)?.fact + contactEmail = try? state.contact.getFact(.email)?.fact + contactPhone = try? state.contact.getFact(.phone)?.fact + myUsername = try? state.myContact?.getFact(.username)?.fact + myEmail = try? state.myContact?.getFact(.email)?.fact + myPhone = try? state.myContact?.getFact(.phone)?.fact sendUsername = state.sendUsername sendEmail = state.sendEmail sendPhone = state.sendPhone @@ -38,7 +46,7 @@ public struct SendRequestView: View { viewStore.send(.set(\.$sendUsername, !viewStore.sendUsername)) } label: { HStack { - Label(viewStore.myContact?.username ?? "", systemImage: "person") + Label(viewStore.myUsername ?? "", systemImage: "person") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendUsername ? "checkmark.circle.fill" : "circle") @@ -51,7 +59,7 @@ public struct SendRequestView: View { viewStore.send(.set(\.$sendEmail, !viewStore.sendEmail)) } label: { HStack { - Label(viewStore.myContact?.email ?? "", systemImage: "envelope") + Label(viewStore.myEmail ?? "", systemImage: "envelope") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendEmail ? "checkmark.circle.fill" : "circle") @@ -64,7 +72,7 @@ public struct SendRequestView: View { viewStore.send(.set(\.$sendPhone, !viewStore.sendPhone)) } label: { HStack { - Label(viewStore.myContact?.phone ?? "", systemImage: "phone") + Label(viewStore.myPhone ?? "", systemImage: "phone") .tint(Color.primary) Spacer() Image(systemName: viewStore.sendPhone ? "checkmark.circle.fill" : "circle") @@ -78,9 +86,9 @@ public struct SendRequestView: View { .disabled(viewStore.isSending) Section { - Label(viewStore.contact.username ?? "", systemImage: "person") - Label(viewStore.contact.email ?? "", systemImage: "envelope") - Label(viewStore.contact.phone ?? "", systemImage: "phone") + Label(viewStore.contactUsername ?? "", systemImage: "person") + Label(viewStore.contactEmail ?? "", systemImage: "envelope") + Label(viewStore.contactPhone ?? "", systemImage: "phone") } header: { Text("Contact") } diff --git a/Examples/xx-messenger/Sources/UserSearchFeature/UserSearchResultFeature.swift b/Examples/xx-messenger/Sources/UserSearchFeature/UserSearchResultFeature.swift index a331df70a0feb76034579df43a23a4ef82d13c32..839e6886236eec081b64616e64b8ff7c59811fbb 100644 --- a/Examples/xx-messenger/Sources/UserSearchFeature/UserSearchResultFeature.swift +++ b/Examples/xx-messenger/Sources/UserSearchFeature/UserSearchResultFeature.swift @@ -44,9 +44,9 @@ public let userSearchResultReducer = Reducer<UserSearchResultState, UserSearchRe { state, action, env in switch action { case .start: - state.username = state.xxContact.username - state.email = state.xxContact.email - state.phone = state.xxContact.phone + state.username = try? state.xxContact.getFact(.username)?.fact + state.email = try? state.xxContact.getFact(.email)?.fact + state.phone = try? state.xxContact.getFact(.phone)?.fact return .none case .tapped: