diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift index 2c22609f63e8b057bf780e2c47305c76f4f6c634..be183c099b55f8840c04f0470ab00cf3fd37ffd4 100644 --- a/Examples/xx-messenger/Package.swift +++ b/Examples/xx-messenger/Package.swift @@ -267,6 +267,7 @@ let package = Package( name: "GroupFeature", dependencies: [ .target(name: "AppCore"), + .target(name: "ChatFeature"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"), diff --git a/Examples/xx-messenger/Sources/GroupFeature/GroupComponent.swift b/Examples/xx-messenger/Sources/GroupFeature/GroupComponent.swift index d9b7d23306b64b6924d5ce7ff3351728667476a3..359ee8991596e56cac72c39626955366588033b0 100644 --- a/Examples/xx-messenger/Sources/GroupFeature/GroupComponent.swift +++ b/Examples/xx-messenger/Sources/GroupFeature/GroupComponent.swift @@ -1,5 +1,7 @@ import AppCore +import ChatFeature import ComposableArchitecture +import ComposablePresentation import Foundation import XXMessengerClient import XXModels @@ -10,18 +12,21 @@ public struct GroupComponent: ReducerProtocol { groupId: XXModels.Group.ID, groupInfo: XXModels.GroupInfo? = nil, isJoining: Bool = false, - joinFailure: String? = nil + joinFailure: String? = nil, + chat: ChatComponent.State? = nil ) { self.groupId = groupId self.groupInfo = groupInfo self.isJoining = isJoining self.joinFailure = joinFailure + self.chat = chat } public var groupId: XXModels.Group.ID public var groupInfo: XXModels.GroupInfo? public var isJoining: Bool public var joinFailure: String? + public var chat: ChatComponent.State? } public enum Action: Equatable { @@ -30,6 +35,9 @@ public struct GroupComponent: ReducerProtocol { case joinButtonTapped case didJoin case didFailToJoin(String) + case chatButtonTapped + case didDismissChat + case chat(ChatComponent.Action) } public init() {} @@ -88,7 +96,24 @@ public struct GroupComponent: ReducerProtocol { state.isJoining = false state.joinFailure = failure return .none + + case .chatButtonTapped: + state.chat = ChatComponent.State(id: .group(state.groupId)) + return .none + + case .didDismissChat: + state.chat = nil + return .none + + case .chat(_): + return .none } } + .presenting( + state: .keyPath(\.chat), + id: .notNil(), + action: /Action.chat, + presented: { ChatComponent() } + ) } } diff --git a/Examples/xx-messenger/Sources/GroupFeature/GroupView.swift b/Examples/xx-messenger/Sources/GroupFeature/GroupView.swift index 67b880f4b1ad3f8e790f51f1202624f195d0d60a..a7520d53802b8fc8a31a306a4305804b94c1cb61 100644 --- a/Examples/xx-messenger/Sources/GroupFeature/GroupView.swift +++ b/Examples/xx-messenger/Sources/GroupFeature/GroupView.swift @@ -1,5 +1,7 @@ import AppCore +import ChatFeature import ComposableArchitecture +import ComposablePresentation import SwiftUI import XXModels @@ -68,8 +70,28 @@ public struct GroupView: View { } } } + + Section { + Button { + viewStore.send(.chatButtonTapped) + } label: { + HStack { + Text("Chat") + Spacer() + Image(systemName: "chevron.forward") + } + } + } } .navigationTitle("Group") + .background(NavigationLinkWithStore( + store.scope( + state: \.chat, + action: Component.Action.chat + ), + onDeactivate: { viewStore.send(.didDismissChat) }, + destination: ChatView.init(store:) + )) .task { viewStore.send(.start) } } } diff --git a/Examples/xx-messenger/Tests/GroupFeatureTests/GroupComponentTests.swift b/Examples/xx-messenger/Tests/GroupFeatureTests/GroupComponentTests.swift index 3c7193fc4ebea418f97800fae37e782d982d497f..b3791b1f107106d9935e6576e664f9ad40cf80f7 100644 --- a/Examples/xx-messenger/Tests/GroupFeatureTests/GroupComponentTests.swift +++ b/Examples/xx-messenger/Tests/GroupFeatureTests/GroupComponentTests.swift @@ -1,3 +1,4 @@ +import ChatFeature import Combine import ComposableArchitecture import CustomDump @@ -140,6 +141,26 @@ final class GroupComponentTests: XCTestCase { $0.joinFailure = failure.localizedDescription } } + + func testPresentChat() { + let groupInfo = GroupInfo.stub() + + let store = TestStore( + initialState: GroupComponent.State( + groupId: groupInfo.group.id, + groupInfo: groupInfo + ), + reducer: GroupComponent() + ) + + store.send(.chatButtonTapped) { + $0.chat = ChatComponent.State(id: .group(groupInfo.id)) + } + + store.send(.didDismissChat) { + $0.chat = nil + } + } } private extension XXModels.GroupInfo {