From 3b52085397797ff7b3b951ef0ac37825b22b037e Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Tue, 4 Oct 2022 22:58:28 +0200
Subject: [PATCH] Present ResetAuth from Conact

---
 Examples/xx-messenger/Package.swift           |  2 +
 .../AppFeature/AppEnvironment+Live.swift      |  4 ++
 .../ContactFeature/ContactFeature.swift       | 32 ++++++++++++++-
 .../Sources/ContactFeature/ContactView.swift  | 22 +++++++++++
 .../ContactFeatureTests.swift                 | 39 +++++++++++++++++++
 5 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index 118b4b14..f7b1252e 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -96,6 +96,7 @@ let package = Package(
         .target(name: "HomeFeature"),
         .target(name: "MyContactFeature"),
         .target(name: "RegisterFeature"),
+        .target(name: "ResetAuthFeature"),
         .target(name: "RestoreFeature"),
         .target(name: "SendRequestFeature"),
         .target(name: "UserSearchFeature"),
@@ -193,6 +194,7 @@ let package = Package(
         .target(name: "CheckContactAuthFeature"),
         .target(name: "ConfirmRequestFeature"),
         .target(name: "ContactLookupFeature"),
+        .target(name: "ResetAuthFeature"),
         .target(name: "SendRequestFeature"),
         .target(name: "VerifyContactFeature"),
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index ce52387f..0e77635b 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -10,6 +10,7 @@ import Foundation
 import HomeFeature
 import MyContactFeature
 import RegisterFeature
+import ResetAuthFeature
 import RestoreFeature
 import SendRequestFeature
 import UserSearchFeature
@@ -77,6 +78,9 @@ extension AppEnvironment {
           bgQueue: bgQueue
         )
       },
+      resetAuth: {
+        ResetAuthEnvironment()
+      },
       chat: {
         ChatEnvironment(
           messenger: messenger,
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
index dc166e4e..be66fc8d 100644
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
@@ -6,6 +6,7 @@ import ComposablePresentation
 import ConfirmRequestFeature
 import ContactLookupFeature
 import Foundation
+import ResetAuthFeature
 import SendRequestFeature
 import VerifyContactFeature
 import XCTestDynamicOverlay
@@ -26,6 +27,7 @@ public struct ContactState: Equatable {
     verifyContact: VerifyContactState? = nil,
     confirmRequest: ConfirmRequestState? = nil,
     checkAuth: CheckContactAuthState? = nil,
+    resetAuth: ResetAuthState? = nil,
     chat: ChatState? = nil
   ) {
     self.id = id
@@ -39,6 +41,7 @@ public struct ContactState: Equatable {
     self.verifyContact = verifyContact
     self.confirmRequest = confirmRequest
     self.checkAuth = checkAuth
+    self.resetAuth = resetAuth
     self.chat = chat
   }
 
@@ -53,6 +56,7 @@ public struct ContactState: Equatable {
   public var verifyContact: VerifyContactState?
   public var confirmRequest: ConfirmRequestState?
   public var checkAuth: CheckContactAuthState?
+  public var resetAuth: ResetAuthState?
   public var chat: ChatState?
 }
 
@@ -75,6 +79,9 @@ public enum ContactAction: Equatable, BindableAction {
   case confirmRequestTapped
   case confirmRequestDismissed
   case confirmRequest(ConfirmRequestAction)
+  case resetAuthTapped
+  case resetAuthDismissed
+  case resetAuth(ResetAuthAction)
   case chatTapped
   case chatDismissed
   case chat(ChatAction)
@@ -92,6 +99,7 @@ public struct ContactEnvironment {
     verifyContact: @escaping () -> VerifyContactEnvironment,
     confirmRequest: @escaping () -> ConfirmRequestEnvironment,
     checkAuth: @escaping () -> CheckContactAuthEnvironment,
+    resetAuth: @escaping () -> ResetAuthEnvironment,
     chat: @escaping () -> ChatEnvironment
   ) {
     self.messenger = messenger
@@ -103,6 +111,7 @@ public struct ContactEnvironment {
     self.verifyContact = verifyContact
     self.confirmRequest = confirmRequest
     self.checkAuth = checkAuth
+    self.resetAuth = resetAuth
     self.chat = chat
   }
 
@@ -115,6 +124,7 @@ public struct ContactEnvironment {
   public var verifyContact: () -> VerifyContactEnvironment
   public var confirmRequest: () -> ConfirmRequestEnvironment
   public var checkAuth: () -> CheckContactAuthEnvironment
+  public var resetAuth: () -> ResetAuthEnvironment
   public var chat: () -> ChatEnvironment
 }
 
@@ -130,6 +140,7 @@ extension ContactEnvironment {
     verifyContact: { .unimplemented },
     confirmRequest: { .unimplemented },
     checkAuth: { .unimplemented },
+    resetAuth: { .unimplemented },
     chat: { .unimplemented }
   )
 }
@@ -247,9 +258,21 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
     state.chat = nil
     return .none
 
+  case .resetAuthTapped:
+    if let marshaled = state.dbContact?.marshaled {
+      state.resetAuth = ResetAuthState(
+        partner: .live(marshaled)
+      )
+    }
+    return .none
+
+  case .resetAuthDismissed:
+    state.resetAuth = nil
+    return .none
+
   case .binding(_), .lookup(_), .sendRequest(_),
       .verifyContact(_), .confirmRequest(_),
-      .checkAuth(_), .chat(_):
+      .checkAuth(_), .resetAuth(_), .chat(_):
     return .none
   }
 }
@@ -289,6 +312,13 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
   action: /ContactAction.checkAuth,
   environment: { $0.checkAuth() }
 )
+.presenting(
+  resetAuthReducer,
+  state: .keyPath(\.resetAuth),
+  id: .notNil(),
+  action: /ContactAction.resetAuth,
+  environment: { $0.resetAuth() }
+)
 .presenting(
   chatReducer,
   state: .keyPath(\.chat),
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
index daa84903..7da763e0 100644
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
@@ -5,6 +5,7 @@ import ComposableArchitecture
 import ComposablePresentation
 import ConfirmRequestFeature
 import ContactLookupFeature
+import ResetAuthFeature
 import SendRequestFeature
 import SwiftUI
 import VerifyContactFeature
@@ -32,6 +33,7 @@ public struct ContactView: View {
     var canVerifyContact: Bool
     var canConfirmRequest: Bool
     var canCheckAuthorization: Bool
+    var canResetAuthorization: Bool
 
     init(state: ContactState) {
       dbContact = state.dbContact
@@ -47,6 +49,7 @@ public struct ContactView: View {
       canVerifyContact = state.dbContact?.marshaled != nil
       canConfirmRequest = state.dbContact?.marshaled != nil
       canCheckAuthorization = state.dbContact?.marshaled != nil
+      canResetAuthorization = state.dbContact?.marshaled != nil
     }
   }
 
@@ -178,6 +181,17 @@ public struct ContactView: View {
               }
             }
             .disabled(!viewStore.canCheckAuthorization)
+
+            Button {
+              viewStore.send(.resetAuthTapped)
+            } label: {
+              HStack {
+                Text("Reset authorization")
+                Spacer()
+                Image(systemName: "chevron.forward")
+              }
+            }
+            .disabled(!viewStore.canResetAuthorization)
           } header: {
             Text("Auth")
           }
@@ -242,6 +256,14 @@ public struct ContactView: View {
         onDeactivate: { viewStore.send(.checkAuthDismissed) },
         destination: CheckContactAuthView.init(store:)
       ))
+      .background(NavigationLinkWithStore(
+        store.scope(
+          state: \.resetAuth,
+          action: ContactAction.resetAuth
+        ),
+        onDeactivate: { viewStore.send(.resetAuthDismissed) },
+        destination: ResetAuthView.init(store:)
+      ))
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.chat,
diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
index c200094f..eba41b7a 100644
--- a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
@@ -5,6 +5,7 @@ import ComposableArchitecture
 import ConfirmRequestFeature
 import ContactLookupFeature
 import CustomDump
+import ResetAuthFeature
 import SendRequestFeature
 import VerifyContactFeature
 import XCTest
@@ -294,6 +295,44 @@ final class ContactFeatureTests: XCTestCase {
     }
   }
 
+  func testResetAuthTapped() {
+    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(.resetAuthTapped) {
+      $0.resetAuth = ResetAuthState(
+        partner: .unimplemented(contactData)
+      )
+    }
+  }
+
+  func testResetAuthDismissed() {
+    let store = TestStore(
+      initialState: ContactState(
+        id: Data(),
+        resetAuth: ResetAuthState(
+          partner: .unimplemented(Data())
+        )
+      ),
+      reducer: contactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.resetAuthDismissed) {
+      $0.resetAuth = nil
+    }
+  }
+
   func testConfirmRequestTapped() {
     let contactData = "contact-data".data(using: .utf8)!
     let store = TestStore(
-- 
GitLab