From 3f1517d0d30580350bbd30c980c0ac96b75dbd7d Mon Sep 17 00:00:00 2001
From: Bruno Muniz Azevedo Filho <bruno@elixxir.io>
Date: Wed, 20 Jul 2022 16:27:22 -0300
Subject: [PATCH] Implemented searching cancellation

---
 Sources/Integration/Session/Session+UD.swift  | 27 ++++++++++++++++++
 Sources/Integration/Session/SessionType.swift |  2 ++
 .../ViewModels/SearchLeftViewModel.swift      | 28 +++++++++----------
 3 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/Sources/Integration/Session/Session+UD.swift b/Sources/Integration/Session/Session+UD.swift
index 1fd8fc38..1fe3e2e0 100644
--- a/Sources/Integration/Session/Session+UD.swift
+++ b/Sources/Integration/Session/Session+UD.swift
@@ -1,8 +1,35 @@
 import Models
 import XXModels
 import Foundation
+import Combine
 
 extension Session {
+    public func search(fact: String) -> AnyPublisher<Contact, Error> {
+        Deferred {
+            Future { promise in
+                guard let ud = self.client.userDiscovery else {
+                    let error = NSError(domain: "", code: 0)
+                    promise(.failure(error))
+                    return
+                }
+
+                do {
+                    try self.client.bindings.nodeRegistrationStatus()
+                    try ud.search(fact: fact) {
+                        switch $0 {
+                        case .success(let contact):
+                            promise(.success(contact))
+                        case .failure(let error):
+                            promise(.failure(error))
+                        }
+                    }
+                } catch {
+                    promise(.failure(error))
+                }
+            }
+        }.eraseToAnyPublisher()
+    }
+
     public func search(fact: String, _ completion: @escaping (Result<Contact, Error>) -> Void) throws {
         guard let ud = client.userDiscovery else { return }
         try client.bindings.nodeRegistrationStatus()
diff --git a/Sources/Integration/Session/SessionType.swift b/Sources/Integration/Session/SessionType.swift
index e99c6f37..b871332b 100644
--- a/Sources/Integration/Session/SessionType.swift
+++ b/Sources/Integration/Session/SessionType.swift
@@ -66,4 +66,6 @@ public protocol SessionType {
         members: [Contact],
         _ completion: @escaping (Result<GroupInfo, Error>) -> Void
     )
+
+    func search(fact: String) -> AnyPublisher<Contact, Error>
 }
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 94b87690..d1c01dfa 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -30,6 +30,7 @@ final class SearchLeftViewModel {
         stateSubject.eraseToAnyPublisher()
     }
 
+    private var searchCancellables = Set<AnyCancellable>()
     private let successSubject = PassthroughSubject<Contact, Never>()
     private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
     private let stateSubject = CurrentValueSubject<SearchLeftViewState, Never>(.init())
@@ -46,6 +47,12 @@ final class SearchLeftViewModel {
         stateSubject.value.item = item
     }
 
+    func didTapCancelSearch() {
+        searchCancellables.forEach { $0.cancel() }
+        searchCancellables.removeAll()
+        hudSubject.send(.none)
+    }
+
     func didStartSearching() {
         guard stateSubject.value.input.isEmpty == false else { return }
 
@@ -58,23 +65,16 @@ final class SearchLeftViewModel {
             content += stateSubject.value.country.code
         }
 
-        do {
-            try session.search(fact: "\(prefix)\(content)") { [weak self] in
-                guard let self = self else { return }
-
-                switch $0 {
-                case .success(let contact):
-                    self.hudSubject.send(.none)
-                    self.appendToLocalSearch(contact)
-
-                case .failure(let error):
+        session.search(fact: "\(prefix)\(content)")
+            .sink { [unowned self] in
+                if case .failure(let error) = $0 {
                     self.appendToLocalSearch(nil)
                     self.hudSubject.send(.error(.init(with: error)))
                 }
-            }
-        } catch {
-            hudSubject.send(.error(.init(with: error)))
-        }
+            } receiveValue: { contact in
+                self.hudSubject.send(.none)
+                self.appendToLocalSearch(contact)
+            }.store(in: &searchCancellables)
     }
 
     func didTapRequest(contact: Contact) {
-- 
GitLab