diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift index e991313f3618a8a6037407c22cf8b96edf34b1dc..79123e057db2e191d888d6732ebcd8b5f82d8196 100644 --- a/Examples/xx-messenger/Package.swift +++ b/Examples/xx-messenger/Package.swift @@ -95,6 +95,7 @@ let package = Package( dependencies: [ .target(name: "AppCore"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"), + .product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"), .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 8e3f48dc36217c97ad7f782db7b892c65b0a4487..514f56bdf187c4c8048d3410dc96a6c41dd5a854 100644 --- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift +++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift @@ -60,7 +60,10 @@ extension AppEnvironment { messenger: messenger, db: dbManager.getDB, mainQueue: mainQueue, - bgQueue: bgQueue + bgQueue: bgQueue, + sendRequest: { + ContactSendRequestEnvironment() + } ) } ) diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift index 7bbb5f3c592294772f207085701fe72d5bbd237c..7671559251c4c96066569607dbeaa50aa5d8247f 100644 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift @@ -1,5 +1,6 @@ import AppCore import ComposableArchitecture +import ComposablePresentation import Foundation import XCTestDynamicOverlay import XXClient @@ -10,16 +11,19 @@ public struct ContactState: Equatable { public init( id: Data, dbContact: XXModels.Contact? = nil, - xxContact: XXClient.Contact? = nil + xxContact: XXClient.Contact? = nil, + sendRequest: ContactSendRequestState? = nil ) { self.id = id self.dbContact = dbContact self.xxContact = xxContact + self.sendRequest = sendRequest } public var id: Data public var dbContact: XXModels.Contact? public var xxContact: XXClient.Contact? + public var sendRequest: ContactSendRequestState? } public enum ContactAction: Equatable { @@ -27,6 +31,8 @@ public enum ContactAction: Equatable { case dbContactFetched(XXModels.Contact?) case saveFactsTapped case sendRequestTapped + case sendRequestDismissed + case sendRequest(ContactSendRequestAction) } public struct ContactEnvironment { @@ -34,18 +40,21 @@ public struct ContactEnvironment { messenger: Messenger, db: DBManagerGetDB, mainQueue: AnySchedulerOf<DispatchQueue>, - bgQueue: AnySchedulerOf<DispatchQueue> + bgQueue: AnySchedulerOf<DispatchQueue>, + sendRequest: @escaping () -> ContactSendRequestEnvironment ) { self.messenger = messenger self.db = db self.mainQueue = mainQueue self.bgQueue = bgQueue + self.sendRequest = sendRequest } public var messenger: Messenger public var db: DBManagerGetDB public var mainQueue: AnySchedulerOf<DispatchQueue> public var bgQueue: AnySchedulerOf<DispatchQueue> + public var sendRequest: () -> ContactSendRequestEnvironment } #if DEBUG @@ -54,7 +63,8 @@ extension ContactEnvironment { messenger: .unimplemented, db: .unimplemented, mainQueue: .unimplemented, - bgQueue: .unimplemented + bgQueue: .unimplemented, + sendRequest: { .unimplemented } ) } #endif @@ -93,6 +103,21 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm .eraseToEffect() case .sendRequestTapped: + state.sendRequest = ContactSendRequestState() + return .none + + case .sendRequestDismissed: + state.sendRequest = nil + return .none + + case .sendRequest(_): return .none } } +.presenting( + contactSendRequestReducer, + state: .keyPath(\.sendRequest), + id: .notNil(), + action: /ContactAction.sendRequest, + environment: { $0.sendRequest() } +) diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestFeature.swift new file mode 100644 index 0000000000000000000000000000000000000000..a0a474e586194d1391f7db3322b73812c4bbdb6a --- /dev/null +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestFeature.swift @@ -0,0 +1,28 @@ +import ComposableArchitecture +import XCTestDynamicOverlay + +public struct ContactSendRequestState: Equatable { + public init() {} +} + +public enum ContactSendRequestAction: Equatable { + case start +} + +public struct ContactSendRequestEnvironment { + public init() {} +} + +#if DEBUG +extension ContactSendRequestEnvironment { + public static let unimplemented = ContactSendRequestEnvironment() +} +#endif + +public let contactSendRequestReducer = Reducer<ContactSendRequestState, ContactSendRequestAction, ContactSendRequestEnvironment> +{ state, action, env in + switch action { + case .start: + return .none + } +} diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestView.swift new file mode 100644 index 0000000000000000000000000000000000000000..4f5048d3d098733425d1f53506c4a60052fae6e5 --- /dev/null +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactSendRequestView.swift @@ -0,0 +1,36 @@ +import ComposableArchitecture +import SwiftUI + +public struct ContactSendRequestView: View { + public init(store: Store<ContactSendRequestState, ContactSendRequestAction>) { + self.store = store + } + + let store: Store<ContactSendRequestState, ContactSendRequestAction> + + struct ViewState: Equatable { + init(state: ContactSendRequestState) {} + } + + public var body: some View { + WithViewStore(store.scope(state: ViewState.init)) { viewStore in + Form { + + } + .navigationTitle("Send Request") + .task { viewStore.send(.start) } + } + } +} + +#if DEBUG +public struct ContactSendRequestView_Previews: PreviewProvider { + public static var previews: some View { + ContactSendRequestView(store: Store( + initialState: ContactSendRequestState(), + reducer: .empty, + environment: () + )) + } +} +#endif diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift index 6bf5015054fbf40955de738479897b07a7499632..44a46c563aea7077dc2e8c0827e9a49464bf600f 100644 --- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift +++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift @@ -1,5 +1,6 @@ import AppCore import ComposableArchitecture +import ComposablePresentation import SwiftUI import XXClient import XXModels @@ -160,6 +161,14 @@ public struct ContactView: View { } .navigationTitle("Contact") .task { viewStore.send(.start) } + .background(NavigationLinkWithStore( + store.scope( + state: \.sendRequest, + action: ContactAction.sendRequest + ), + onDeactivate: { viewStore.send(.sendRequestDismissed) }, + destination: ContactSendRequestView.init(store:) + )) } } } diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift index f14c9e395b290056985e6aed67fa29b051e0b6f6..64d0d72ad9ffce1186b1002c306c1f1e45ecd2cd 100644 --- a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift @@ -103,6 +103,12 @@ final class ContactFeatureTests: XCTestCase { environment: .unimplemented ) - store.send(.sendRequestTapped) + store.send(.sendRequestTapped) { + $0.sendRequest = ContactSendRequestState() + } + + store.send(.sendRequestDismissed) { + $0.sendRequest = nil + } } } diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactSendRequestFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactSendRequestFeatureTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..8d4eb040d37700997205b2d263d25571579bf0f5 --- /dev/null +++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactSendRequestFeatureTests.swift @@ -0,0 +1,15 @@ +import ComposableArchitecture +import XCTest +@testable import ContactFeature + +final class ContactSendRequestFeatureTests: XCTestCase { + func testStart() { + let store = TestStore( + initialState: ContactSendRequestState(), + reducer: contactSendRequestReducer, + environment: .unimplemented + ) + + store.send(.start) + } +}