From f893860df269d18c8148af7238bd3c83a0115999 Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Tue, 20 Sep 2022 09:29:33 +0200
Subject: [PATCH] Present MyContact from Contacts

---
 Examples/xx-messenger/Package.swift           |  2 ++
 .../AppFeature/AppEnvironment+Live.swift      |  6 +++-
 .../ContactsFeature/ContactsFeature.swift     | 34 ++++++++++++++++---
 .../ContactsFeature/ContactsView.swift        | 29 ++++++++++++----
 .../ContactsFeatureTests.swift                | 27 +++++++++++++++
 5 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index be093741..c184020f 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -84,6 +84,7 @@ let package = Package(
         .target(name: "ContactFeature"),
         .target(name: "ContactsFeature"),
         .target(name: "HomeFeature"),
+        .target(name: "MyContactFeature"),
         .target(name: "RegisterFeature"),
         .target(name: "RestoreFeature"),
         .target(name: "SendRequestFeature"),
@@ -182,6 +183,7 @@ let package = Package(
       dependencies: [
         .target(name: "AppCore"),
         .target(name: "ContactFeature"),
+        .target(name: "MyContactFeature"),
         .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/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index 611123e0..b93b0359 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -6,6 +6,7 @@ import ContactFeature
 import ContactsFeature
 import Foundation
 import HomeFeature
+import MyContactFeature
 import RegisterFeature
 import RestoreFeature
 import SendRequestFeature
@@ -122,7 +123,10 @@ extension AppEnvironment {
               db: dbManager.getDB,
               mainQueue: mainQueue,
               bgQueue: bgQueue,
-              contact: { contactEnvironment }
+              contact: { contactEnvironment },
+              myContact: {
+                MyContactEnvironment()
+              }
             )
           },
           userSearch: {
diff --git a/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift b/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift
index 1ded89de..680a231e 100644
--- a/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift
+++ b/Examples/xx-messenger/Sources/ContactsFeature/ContactsFeature.swift
@@ -3,6 +3,7 @@ import ComposableArchitecture
 import ComposablePresentation
 import ContactFeature
 import Foundation
+import MyContactFeature
 import XCTestDynamicOverlay
 import XXClient
 import XXMessengerClient
@@ -12,16 +13,19 @@ public struct ContactsState: Equatable {
   public init(
     myId: Data? = nil,
     contacts: IdentifiedArrayOf<XXModels.Contact> = [],
-    contact: ContactState? = nil
+    contact: ContactState? = nil,
+    myContact: MyContactState? = nil
   ) {
     self.myId = myId
     self.contacts = contacts
     self.contact = contact
+    self.myContact = myContact
   }
 
   public var myId: Data?
   public var contacts: IdentifiedArrayOf<XXModels.Contact>
   public var contact: ContactState?
+  public var myContact: MyContactState?
 }
 
 public enum ContactsAction: Equatable {
@@ -30,6 +34,9 @@ public enum ContactsAction: Equatable {
   case contactSelected(XXModels.Contact)
   case contactDismissed
   case contact(ContactAction)
+  case myContactSelected
+  case myContactDismissed
+  case myContact(MyContactAction)
 }
 
 public struct ContactsEnvironment {
@@ -38,13 +45,15 @@ public struct ContactsEnvironment {
     db: DBManagerGetDB,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>,
-    contact: @escaping () -> ContactEnvironment
+    contact: @escaping () -> ContactEnvironment,
+    myContact: @escaping () -> MyContactEnvironment
   ) {
     self.messenger = messenger
     self.db = db
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
     self.contact = contact
+    self.myContact = myContact
   }
 
   public var messenger: Messenger
@@ -52,6 +61,7 @@ public struct ContactsEnvironment {
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
   public var contact: () -> ContactEnvironment
+  public var myContact: () -> MyContactEnvironment
 }
 
 #if DEBUG
@@ -61,7 +71,8 @@ extension ContactsEnvironment {
     db: .unimplemented,
     mainQueue: .unimplemented,
     bgQueue: .unimplemented,
-    contact: { .unimplemented }
+    contact: { .unimplemented },
+    myContact: { .unimplemented }
   )
 }
 #endif
@@ -96,7 +107,15 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
     state.contact = nil
     return .none
 
-  case .contact(_):
+  case .myContactSelected:
+    state.myContact = MyContactState()
+    return .none
+
+  case .myContactDismissed:
+    state.myContact = nil
+    return .none
+
+  case .contact(_), .myContact(_):
     return .none
   }
 }
@@ -107,3 +126,10 @@ public let contactsReducer = Reducer<ContactsState, ContactsAction, ContactsEnvi
   action: /ContactsAction.contact,
   environment: { $0.contact() }
 )
+.presenting(
+  myContactReducer,
+  state: .keyPath(\.myContact),
+  id: .notNil(),
+  action: /ContactsAction.myContact,
+  environment: { $0.myContact() }
+)
diff --git a/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift b/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift
index ce811f9d..e09725d9 100644
--- a/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift
+++ b/Examples/xx-messenger/Sources/ContactsFeature/ContactsView.swift
@@ -2,6 +2,7 @@ import AppCore
 import ComposableArchitecture
 import ComposablePresentation
 import ContactFeature
+import MyContactFeature
 import SwiftUI
 import XXModels
 
@@ -28,13 +29,21 @@ public struct ContactsView: View {
         ForEach(viewStore.contacts) { contact in
           if contact.id == viewStore.myId {
             Section {
-              VStack(alignment: .leading, spacing: 8) {
-                Label(contact.username ?? "", systemImage: "person")
-                Label(contact.email ?? "", systemImage: "envelope")
-                Label(contact.phone ?? "", systemImage: "phone")
+              Button {
+                viewStore.send(.myContactSelected)
+              } label: {
+                HStack {
+                  VStack(alignment: .leading, spacing: 8) {
+                    Label(contact.username ?? "", systemImage: "person")
+                    Label(contact.email ?? "", systemImage: "envelope")
+                    Label(contact.phone ?? "", systemImage: "phone")
+                  }
+                  .font(.callout)
+                  .tint(Color.primary)
+                  Spacer()
+                  Image(systemName: "chevron.forward")
+                }
               }
-              .font(.callout)
-              .tint(Color.primary)
             } header: {
               Text("My contact")
             }
@@ -70,6 +79,14 @@ public struct ContactsView: View {
         onDeactivate: { viewStore.send(.contactDismissed) },
         destination: ContactView.init(store:)
       ))
+      .background(NavigationLinkWithStore(
+        store.scope(
+          state: \.myContact,
+          action: ContactsAction.myContact
+        ),
+        onDeactivate: { viewStore.send(.myContactDismissed) },
+        destination: MyContactView.init(store:)
+      ))
     }
   }
 }
diff --git a/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift b/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift
index a0c0291e..ffd3eafe 100644
--- a/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ContactsFeatureTests/ContactsFeatureTests.swift
@@ -2,6 +2,7 @@ import Combine
 import ComposableArchitecture
 import ContactFeature
 import CustomDump
+import MyContactFeature
 import XCTest
 import XXClient
 import XXMessengerClient
@@ -94,4 +95,30 @@ final class ContactsFeatureTests: XCTestCase {
       $0.contact = nil
     }
   }
+
+  func testSelectMyContact() {
+    let store = TestStore(
+      initialState: ContactsState(),
+      reducer: contactsReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.myContactSelected) {
+      $0.myContact = MyContactState()
+    }
+  }
+
+  func testDismissMyContact() {
+    let store = TestStore(
+      initialState: ContactsState(
+        myContact: MyContactState()
+      ),
+      reducer: contactsReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.myContactDismissed) {
+      $0.myContact = nil
+    }
+  }
 }
-- 
GitLab