From d0f0e6e06c8bc1182c07ed2b76f5043c9e52577e Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Thu, 8 Sep 2022 13:46:46 +0200 Subject: [PATCH] Present Contact from Contacts --- Examples/xx-messenger/Package.swift | 1 + .../AppFeature/AppEnvironment+Live.swift | 35 +++++++++--------- .../ContactsFeature/ContactsFeature.swift | 36 +++++++++++++++++-- .../ContactsFeature/ContactsView.swift | 12 ++++++- .../ContactsFeatureTests.swift | 32 +++++++++++++++++ 5 files changed, 95 insertions(+), 21 deletions(-) diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift index 25e6d083..db3097ee 100644 --- a/Examples/xx-messenger/Package.swift +++ b/Examples/xx-messenger/Package.swift @@ -117,6 +117,7 @@ let package = Package( name: "ContactsFeature", dependencies: [ .target(name: "AppCore"), + .target(name: "ContactFeature"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "XXModels", package: "client-ios-db"), diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift index 8ac88751..f57003f0 100644 --- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift +++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift @@ -19,6 +19,21 @@ extension AppEnvironment { let mainQueue = DispatchQueue.main.eraseToAnyScheduler() let bgQueue = DispatchQueue.global(qos: .background).eraseToAnyScheduler() + let contactEnvironment = ContactEnvironment( + messenger: messenger, + db: dbManager.getDB, + mainQueue: mainQueue, + bgQueue: bgQueue, + sendRequest: { + SendRequestEnvironment( + messenger: messenger, + db: dbManager.getDB, + mainQueue: mainQueue, + bgQueue: bgQueue + ) + } + ) + return AppEnvironment( dbManager: dbManager, messenger: messenger, @@ -53,7 +68,8 @@ extension AppEnvironment { ContactsEnvironment( db: dbManager.getDB, mainQueue: mainQueue, - bgQueue: bgQueue + bgQueue: bgQueue, + contact: { contactEnvironment } ) }, userSearch: { @@ -61,22 +77,7 @@ extension AppEnvironment { messenger: messenger, mainQueue: mainQueue, bgQueue: bgQueue, - contact: { - ContactEnvironment( - messenger: messenger, - db: dbManager.getDB, - mainQueue: mainQueue, - bgQueue: bgQueue, - sendRequest: { - SendRequestEnvironment( - messenger: messenger, - db: dbManager.getDB, - mainQueue: mainQueue, - bgQueue: bgQueue - ) - } - ) - } + contact: { contactEnvironment } ) } ) diff --git a/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift b/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift index c5780594..79690934 100644 --- a/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift +++ b/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift @@ -1,38 +1,49 @@ import AppCore import ComposableArchitecture +import ComposablePresentation +import ContactFeature import Foundation import XCTestDynamicOverlay import XXModels public struct ContactsState: Equatable { public init( - contacts: IdentifiedArrayOf<Contact> = [] + contacts: IdentifiedArrayOf<Contact> = [], + contact: ContactState? = nil ) { self.contacts = contacts + self.contact = contact } public var contacts: IdentifiedArrayOf<XXModels.Contact> + public var contact: ContactState? } public enum ContactsAction: Equatable { case start case didFetchContacts([XXModels.Contact]) + case contactSelected(XXModels.Contact) + case contactDismissed + case contact(ContactAction) } public struct ContactsEnvironment { public init( db: DBManagerGetDB, mainQueue: AnySchedulerOf<DispatchQueue>, - bgQueue: AnySchedulerOf<DispatchQueue> + bgQueue: AnySchedulerOf<DispatchQueue>, + contact: @escaping () -> ContactEnvironment ) { self.db = db self.mainQueue = mainQueue self.bgQueue = bgQueue + self.contact = contact } public var db: DBManagerGetDB public var mainQueue: AnySchedulerOf<DispatchQueue> public var bgQueue: AnySchedulerOf<DispatchQueue> + public var contact: () -> ContactEnvironment } #if DEBUG @@ -40,7 +51,8 @@ extension ContactsEnvironment { public static let unimplemented = ContactsEnvironment( db: .unimplemented, mainQueue: .unimplemented, - bgQueue: .unimplemented + bgQueue: .unimplemented, + contact: { .unimplemented } ) } #endif @@ -61,5 +73,23 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi case .didFetchContacts(let contacts): state.contacts = IdentifiedArray(uniqueElements: contacts) return .none + + case .contactSelected(let contact): + state.contact = ContactState(id: contact.id, dbContact: contact) + return .none + + case .contactDismissed: + state.contact = nil + return .none + + case .contact(_): + return .none } } +.presenting( + contactReducer, + state: .keyPath(\.contact), + id: .keyPath(\.?.id), + action: /ContactsAction.contact, + environment: { $0.contact() } +) diff --git a/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift b/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift index ad5d1a37..7b02efd1 100644 --- a/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift +++ b/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift @@ -1,5 +1,7 @@ import AppCore import ComposableArchitecture +import ComposablePresentation +import ContactFeature import SwiftUI import XXModels @@ -24,7 +26,7 @@ public struct ContactsView: View { ForEach(viewStore.contacts) { contact in Section { Button { - // TODO: + viewStore.send(.contactSelected(contact)) } label: { HStack { VStack(alignment: .leading, spacing: 8) { @@ -44,6 +46,14 @@ public struct ContactsView: View { } .navigationTitle("Contacts") .task { viewStore.send(.start) } + .background(NavigationLinkWithStore( + store.scope( + state: \.contact, + action: ContactsAction.contact + ), + onDeactivate: { viewStore.send(.contactDismissed) }, + destination: ContactView.init(store:) + )) } } } diff --git a/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift b/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift index 04533b34..6c68f406 100644 --- a/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift @@ -1,5 +1,6 @@ import Combine import ComposableArchitecture +import ContactFeature import CustomDump import XCTest import XXModels @@ -44,4 +45,35 @@ final class ContactsFeatureTests: XCTestCase { contactsPublisher.send(completion: .finished) } + + func testSelectContact() { + let store = TestStore( + initialState: ContactsState(), + reducer: contactsReducer, + environment: .unimplemented + ) + + let contact = XXModels.Contact(id: "id".data(using: .utf8)!) + + store.send(.contactSelected(contact)) { + $0.contact = ContactState(id: contact.id, dbContact: contact) + } + } + + func testDismissContact() { + let store = TestStore( + initialState: ContactsState( + contact: ContactState( + id: "id".data(using: .utf8)!, + dbContact: Contact(id: "id".data(using: .utf8)!) + ) + ), + reducer: contactsReducer, + environment: .unimplemented + ) + + store.send(.contactDismissed) { + $0.contact = nil + } + } } -- GitLab