Skip to content
Snippets Groups Projects
Commit 7735cfe7 authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Present VerifyContact from Contact

parent 946ef9d0
No related branches found
No related tags found
2 merge requests!102Release 1.0.0,!81Messenger example - contact authorization improvements
...@@ -81,6 +81,7 @@ let package = Package( ...@@ -81,6 +81,7 @@ let package = Package(
.target(name: "RestoreFeature"), .target(name: "RestoreFeature"),
.target(name: "SendRequestFeature"), .target(name: "SendRequestFeature"),
.target(name: "UserSearchFeature"), .target(name: "UserSearchFeature"),
.target(name: "VerifyContactFeature"),
.target(name: "WelcomeFeature"), .target(name: "WelcomeFeature"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "ComposablePresentation", package: "swift-composable-presentation"),
...@@ -101,6 +102,7 @@ let package = Package( ...@@ -101,6 +102,7 @@ let package = Package(
dependencies: [ dependencies: [
.target(name: "AppCore"), .target(name: "AppCore"),
.target(name: "SendRequestFeature"), .target(name: "SendRequestFeature"),
.target(name: "VerifyContactFeature"),
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "ComposablePresentation", package: "swift-composable-presentation"), .product(name: "ComposablePresentation", package: "swift-composable-presentation"),
.product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"), .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
...@@ -228,6 +230,7 @@ let package = Package( ...@@ -228,6 +230,7 @@ let package = Package(
name: "VerifyContactFeature", name: "VerifyContactFeature",
dependencies: [ dependencies: [
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"), .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
.product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
] ]
), ),
.testTarget( .testTarget(
......
...@@ -7,6 +7,7 @@ import RegisterFeature ...@@ -7,6 +7,7 @@ import RegisterFeature
import RestoreFeature import RestoreFeature
import SendRequestFeature import SendRequestFeature
import UserSearchFeature import UserSearchFeature
import VerifyContactFeature
import WelcomeFeature import WelcomeFeature
import XXMessengerClient import XXMessengerClient
import XXModels import XXModels
...@@ -41,6 +42,9 @@ extension AppEnvironment { ...@@ -41,6 +42,9 @@ extension AppEnvironment {
mainQueue: mainQueue, mainQueue: mainQueue,
bgQueue: bgQueue bgQueue: bgQueue
) )
},
verifyContact: {
VerifyContactEnvironment()
} }
) )
......
...@@ -3,6 +3,7 @@ import ComposableArchitecture ...@@ -3,6 +3,7 @@ import ComposableArchitecture
import ComposablePresentation import ComposablePresentation
import Foundation import Foundation
import SendRequestFeature import SendRequestFeature
import VerifyContactFeature
import XCTestDynamicOverlay import XCTestDynamicOverlay
import XXClient import XXClient
import XXMessengerClient import XXMessengerClient
...@@ -16,7 +17,8 @@ public struct ContactState: Equatable { ...@@ -16,7 +17,8 @@ public struct ContactState: Equatable {
importUsername: Bool = true, importUsername: Bool = true,
importEmail: Bool = true, importEmail: Bool = true,
importPhone: Bool = true, importPhone: Bool = true,
sendRequest: SendRequestState? = nil sendRequest: SendRequestState? = nil,
verifyContact: VerifyContactState? = nil
) { ) {
self.id = id self.id = id
self.dbContact = dbContact self.dbContact = dbContact
...@@ -25,6 +27,7 @@ public struct ContactState: Equatable { ...@@ -25,6 +27,7 @@ public struct ContactState: Equatable {
self.importEmail = importEmail self.importEmail = importEmail
self.importPhone = importPhone self.importPhone = importPhone
self.sendRequest = sendRequest self.sendRequest = sendRequest
self.verifyContact = verifyContact
} }
public var id: Data public var id: Data
...@@ -34,6 +37,7 @@ public struct ContactState: Equatable { ...@@ -34,6 +37,7 @@ public struct ContactState: Equatable {
@BindableState public var importEmail: Bool @BindableState public var importEmail: Bool
@BindableState public var importPhone: Bool @BindableState public var importPhone: Bool
public var sendRequest: SendRequestState? public var sendRequest: SendRequestState?
public var verifyContact: VerifyContactState?
} }
public enum ContactAction: Equatable, BindableAction { public enum ContactAction: Equatable, BindableAction {
...@@ -43,6 +47,9 @@ public enum ContactAction: Equatable, BindableAction { ...@@ -43,6 +47,9 @@ public enum ContactAction: Equatable, BindableAction {
case sendRequestTapped case sendRequestTapped
case sendRequestDismissed case sendRequestDismissed
case sendRequest(SendRequestAction) case sendRequest(SendRequestAction)
case verifyContactTapped
case verifyContactDismissed
case verifyContact(VerifyContactAction)
case binding(BindingAction<ContactState>) case binding(BindingAction<ContactState>)
} }
...@@ -52,13 +59,15 @@ public struct ContactEnvironment { ...@@ -52,13 +59,15 @@ public struct ContactEnvironment {
db: DBManagerGetDB, db: DBManagerGetDB,
mainQueue: AnySchedulerOf<DispatchQueue>, mainQueue: AnySchedulerOf<DispatchQueue>,
bgQueue: AnySchedulerOf<DispatchQueue>, bgQueue: AnySchedulerOf<DispatchQueue>,
sendRequest: @escaping () -> SendRequestEnvironment sendRequest: @escaping () -> SendRequestEnvironment,
verifyContact: @escaping () -> VerifyContactEnvironment
) { ) {
self.messenger = messenger self.messenger = messenger
self.db = db self.db = db
self.mainQueue = mainQueue self.mainQueue = mainQueue
self.bgQueue = bgQueue self.bgQueue = bgQueue
self.sendRequest = sendRequest self.sendRequest = sendRequest
self.verifyContact = verifyContact
} }
public var messenger: Messenger public var messenger: Messenger
...@@ -66,6 +75,7 @@ public struct ContactEnvironment { ...@@ -66,6 +75,7 @@ public struct ContactEnvironment {
public var mainQueue: AnySchedulerOf<DispatchQueue> public var mainQueue: AnySchedulerOf<DispatchQueue>
public var bgQueue: AnySchedulerOf<DispatchQueue> public var bgQueue: AnySchedulerOf<DispatchQueue>
public var sendRequest: () -> SendRequestEnvironment public var sendRequest: () -> SendRequestEnvironment
public var verifyContact: () -> VerifyContactEnvironment
} }
#if DEBUG #if DEBUG
...@@ -75,7 +85,8 @@ extension ContactEnvironment { ...@@ -75,7 +85,8 @@ extension ContactEnvironment {
db: .unimplemented, db: .unimplemented,
mainQueue: .unimplemented, mainQueue: .unimplemented,
bgQueue: .unimplemented, bgQueue: .unimplemented,
sendRequest: { .unimplemented } sendRequest: { .unimplemented },
verifyContact: { .unimplemented }
) )
} }
#endif #endif
...@@ -135,10 +146,19 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm ...@@ -135,10 +146,19 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
state.sendRequest = nil state.sendRequest = nil
return .none return .none
case .sendRequest(_): case .verifyContactTapped:
if let marshaled = state.dbContact?.marshaled {
state.verifyContact = VerifyContactState(
xxContact: .live(marshaled)
)
}
return .none
case .verifyContactDismissed:
state.verifyContact = nil
return .none return .none
case .binding(_): case .binding(_), .sendRequest(_), .verifyContact(_):
return .none return .none
} }
} }
...@@ -150,3 +170,10 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm ...@@ -150,3 +170,10 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
action: /ContactAction.sendRequest, action: /ContactAction.sendRequest,
environment: { $0.sendRequest() } environment: { $0.sendRequest() }
) )
.presenting(
verifyContactReducer,
state: .keyPath(\.verifyContact),
id: .notNil(),
action: /ContactAction.verifyContact,
environment: { $0.verifyContact() }
)
...@@ -3,6 +3,7 @@ import ComposableArchitecture ...@@ -3,6 +3,7 @@ import ComposableArchitecture
import ComposablePresentation import ComposablePresentation
import SendRequestFeature import SendRequestFeature
import SwiftUI import SwiftUI
import VerifyContactFeature
import XXClient import XXClient
import XXModels import XXModels
...@@ -114,6 +115,15 @@ public struct ContactView: View { ...@@ -114,6 +115,15 @@ public struct ContactView: View {
Image(systemName: "chevron.forward") Image(systemName: "chevron.forward")
} }
} }
Button {
viewStore.send(.verifyContactTapped)
} label: {
HStack {
Text("Verify contact")
Spacer()
Image(systemName: "chevron.forward")
}
}
} header: { } header: {
Text("Auth") Text("Auth")
} }
...@@ -131,6 +141,14 @@ public struct ContactView: View { ...@@ -131,6 +141,14 @@ public struct ContactView: View {
onDeactivate: { viewStore.send(.sendRequestDismissed) }, onDeactivate: { viewStore.send(.sendRequestDismissed) },
destination: SendRequestView.init(store:) destination: SendRequestView.init(store:)
)) ))
.background(NavigationLinkWithStore(
store.scope(
state: \.verifyContact,
action: ContactAction.verifyContact
),
onDeactivate: { viewStore.send(.verifyContactDismissed) },
destination: VerifyContactView.init(store:)
))
} }
} }
} }
......
import ComposableArchitecture import ComposableArchitecture
import XCTestDynamicOverlay import XCTestDynamicOverlay
import XXClient
public struct VerifyContactState: Equatable { public struct VerifyContactState: Equatable {
public init() {} public init(
xxContact: XXClient.Contact
) {
self.xxContact = xxContact
}
public var xxContact: XXClient.Contact
} }
public enum VerifyContactAction: Equatable { public enum VerifyContactAction: Equatable {
......
...@@ -27,7 +27,9 @@ public struct VerifyContactView: View { ...@@ -27,7 +27,9 @@ public struct VerifyContactView: View {
public struct VerifyContactView_Previews: PreviewProvider { public struct VerifyContactView_Previews: PreviewProvider {
public static var previews: some View { public static var previews: some View {
VerifyContactView(store: Store( VerifyContactView(store: Store(
initialState: VerifyContactState(), initialState: VerifyContactState(
xxContact: .unimplemented("contact-data".data(using: .utf8)!)
),
reducer: .empty, reducer: .empty,
environment: () environment: ()
)) ))
......
...@@ -2,6 +2,7 @@ import Combine ...@@ -2,6 +2,7 @@ import Combine
import ComposableArchitecture import ComposableArchitecture
import CustomDump import CustomDump
import SendRequestFeature import SendRequestFeature
import VerifyContactFeature
import XCTest import XCTest
import XXClient import XXClient
import XXModels import XXModels
...@@ -163,4 +164,42 @@ final class ContactFeatureTests: XCTestCase { ...@@ -163,4 +164,42 @@ final class ContactFeatureTests: XCTestCase {
$0.sendRequest = nil $0.sendRequest = nil
} }
} }
func testVerifyContactTapped() {
let contactData = "contact-data".data(using: .utf8)!
let store = TestStore(
initialState: ContactState(
id: Data(),
dbContact: XXModels.Contact(
id: Data(),
marshaled: contactData
)
),
reducer: contactReducer,
environment: .unimplemented
)
store.send(.verifyContactTapped) {
$0.verifyContact = VerifyContactState(
xxContact: .live(contactData)
)
}
}
func testVerifyContactDismissed() {
let store = TestStore(
initialState: ContactState(
id: "contact-id".data(using: .utf8)!,
verifyContact: VerifyContactState(
xxContact: .unimplemented("contact-data".data(using: .utf8)!)
)
),
reducer: contactReducer,
environment: .unimplemented
)
store.send(.verifyContactDismissed) {
$0.verifyContact = nil
}
}
} }
...@@ -5,7 +5,9 @@ import XCTest ...@@ -5,7 +5,9 @@ import XCTest
final class VerifyContactFeatureTests: XCTestCase { final class VerifyContactFeatureTests: XCTestCase {
func testStart() { func testStart() {
let store = TestStore( let store = TestStore(
initialState: VerifyContactState(), initialState: VerifyContactState(
xxContact: .unimplemented("contact-data".data(using: .utf8)!)
),
reducer: verifyContactReducer, reducer: verifyContactReducer,
environment: .unimplemented environment: .unimplemented
) )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment