From 42d12de2743b12d44a9843a59f515269b21812ed Mon Sep 17 00:00:00 2001
From: Dariusz Rybicki <dariusz@elixxir.io>
Date: Thu, 8 Sep 2022 13:10:08 +0200
Subject: [PATCH] Present Contacts from Home

---
 Examples/xx-messenger/Package.swift           |  2 ++
 .../AppFeature/AppEnvironment+Live.swift      |  4 +++
 .../Sources/HomeFeature/HomeFeature.swift     | 28 ++++++++++++++++++-
 .../Sources/HomeFeature/HomeView.swift        | 21 ++++++++++++++
 .../HomeFeatureTests/HomeFeatureTests.swift   | 27 ++++++++++++++++++
 5 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index 54f5035c..25e6d083 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -73,6 +73,7 @@ let package = Package(
       dependencies: [
         .target(name: "AppCore"),
         .target(name: "ContactFeature"),
+        .target(name: "ContactsFeature"),
         .target(name: "HomeFeature"),
         .target(name: "RegisterFeature"),
         .target(name: "RestoreFeature"),
@@ -133,6 +134,7 @@ let package = Package(
       name: "HomeFeature",
       dependencies: [
         .target(name: "AppCore"),
+        .target(name: "ContactsFeature"),
         .target(name: "RegisterFeature"),
         .target(name: "UserSearchFeature"),
         .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 01e31519..2caa4f0f 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -1,5 +1,6 @@
 import AppCore
 import ContactFeature
+import ContactsFeature
 import Foundation
 import HomeFeature
 import RegisterFeature
@@ -48,6 +49,9 @@ extension AppEnvironment {
               bgQueue: bgQueue
             )
           },
+          contacts: {
+            ContactsEnvironment()
+          },
           userSearch: {
             UserSearchEnvironment(
               messenger: messenger,
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
index 9df6d745..faa5757c 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
@@ -2,6 +2,7 @@ import AppCore
 import Combine
 import ComposableArchitecture
 import ComposablePresentation
+import ContactsFeature
 import Foundation
 import RegisterFeature
 import UserSearchFeature
@@ -16,6 +17,7 @@ public struct HomeState: Equatable {
     isDeletingAccount: Bool = false,
     alert: AlertState<HomeAction>? = nil,
     register: RegisterState? = nil,
+    contacts: ContactsState? = nil,
     userSearch: UserSearchState? = nil
   ) {
     self.failure = failure
@@ -23,6 +25,7 @@ public struct HomeState: Equatable {
     self.isDeletingAccount = isDeletingAccount
     self.alert = alert
     self.register = register
+    self.contacts = contacts
     self.userSearch = userSearch
   }
 
@@ -32,6 +35,7 @@ public struct HomeState: Equatable {
   public var isDeletingAccount: Bool
   public var alert: AlertState<HomeAction>?
   public var register: RegisterState?
+  public var contacts: ContactsState?
   public var userSearch: UserSearchState?
 }
 
@@ -64,7 +68,10 @@ public enum HomeAction: Equatable {
   case didDismissRegister
   case userSearchButtonTapped
   case didDismissUserSearch
+  case contactsButtonTapped
+  case didDismissContacts
   case register(RegisterAction)
+  case contacts(ContactsAction)
   case userSearch(UserSearchAction)
 }
 
@@ -75,6 +82,7 @@ public struct HomeEnvironment {
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>,
     register: @escaping () -> RegisterEnvironment,
+    contacts: @escaping () -> ContactsEnvironment,
     userSearch: @escaping () -> UserSearchEnvironment
   ) {
     self.messenger = messenger
@@ -82,6 +90,7 @@ public struct HomeEnvironment {
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
     self.register = register
+    self.contacts = contacts
     self.userSearch = userSearch
   }
 
@@ -90,6 +99,7 @@ public struct HomeEnvironment {
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
   public var register: () -> RegisterEnvironment
+  public var contacts: () -> ContactsEnvironment
   public var userSearch: () -> UserSearchEnvironment
 }
 
@@ -100,6 +110,7 @@ extension HomeEnvironment {
     mainQueue: .unimplemented,
     bgQueue: .unimplemented,
     register: { .unimplemented },
+    contacts: { .unimplemented },
     userSearch: { .unimplemented }
   )
 }
@@ -238,11 +249,19 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
     state.userSearch = nil
     return .none
 
+  case .contactsButtonTapped:
+    state.contacts = ContactsState()
+    return .none
+
+  case .didDismissContacts:
+    state.contacts = nil
+    return .none
+
   case .register(.finished):
     state.register = nil
     return Effect(value: .messenger(.start))
 
-  case .register(_), .userSearch(_):
+  case .register(_), .contacts(_), .userSearch(_):
     return .none
   }
 }
@@ -253,6 +272,13 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
   action: /HomeAction.register,
   environment: { $0.register() }
 )
+.presenting(
+  contactsReducer,
+  state: .keyPath(\.contacts),
+  id: .notNil(),
+  action: /HomeAction.contacts,
+  environment: { $0.contacts() }
+)
 .presenting(
   userSearchReducer,
   state: .keyPath(\.userSearch),
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
index e52e8d1b..414bf928 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
@@ -1,5 +1,6 @@
 import ComposableArchitecture
 import ComposablePresentation
+import ContactsFeature
 import RegisterFeature
 import SwiftUI
 import UserSearchFeature
@@ -88,6 +89,16 @@ public struct HomeView: View {
           }
 
           Section {
+            Button {
+              viewStore.send(.contactsButtonTapped)
+            } label: {
+              HStack {
+                Text("Contacts")
+                Spacer()
+                Image(systemName: "chevron.forward")
+              }
+            }
+
             Button {
               viewStore.send(.userSearchButtonTapped)
             } label: {
@@ -123,6 +134,16 @@ public struct HomeView: View {
           store.scope(state: \.alert),
           dismiss: HomeAction.didDismissAlert
         )
+        .background(NavigationLinkWithStore(
+          store.scope(
+            state: \.contacts,
+            action: HomeAction.contacts
+          ),
+          onDeactivate: {
+            viewStore.send(.didDismissContacts)
+          },
+          destination: ContactsView.init(store:)
+        ))
         .background(NavigationLinkWithStore(
           store.scope(
             state: \.userSearch,
diff --git a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
index 2d7f6daf..89aef4c9 100644
--- a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
@@ -1,4 +1,5 @@
 import ComposableArchitecture
+import ContactsFeature
 import RegisterFeature
 import UserSearchFeature
 import XCTest
@@ -464,4 +465,30 @@ final class HomeFeatureTests: XCTestCase {
       $0.userSearch = nil
     }
   }
+
+  func testContactsButtonTapped() {
+    let store = TestStore(
+      initialState: HomeState(),
+      reducer: homeReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.contactsButtonTapped) {
+      $0.contacts = ContactsState()
+    }
+  }
+
+  func testDidDismissContacts() {
+    let store = TestStore(
+      initialState: HomeState(
+        contacts: ContactsState()
+      ),
+      reducer: homeReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.didDismissContacts) {
+      $0.contacts = nil
+    }
+  }
 }
-- 
GitLab