Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import HUD
import UIKit
import Combine
import XXModels
import Integration
import DependencyInjection
typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>
struct SearchUsernameViewState {
var input = ""
var snapshot: SearchSnapshot?
}
final class SearchUsernameViewModel {
@Dependency var session: SessionType
var hudPublisher: AnyPublisher<HUDStatus, Never> {
hudSubject.eraseToAnyPublisher()
}
var successPublisher: AnyPublisher<Contact, Never> {
successSubject.eraseToAnyPublisher()
}
var statePublisher: AnyPublisher<SearchUsernameViewState, Never> {
stateSubject.eraseToAnyPublisher()
}
private let successSubject = PassthroughSubject<Contact, Never>()
private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
private let stateSubject = CurrentValueSubject<SearchUsernameViewState, Never>(.init())
func didEnterInput(_ string: String) {
stateSubject.value.input = string
}
func didStartSearching() {
hudSubject.send(.on(nil))
do {
try session.search(fact: "U\(stateSubject.value.input)") { [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):
self.appendToLocalSearch(nil)
self.hudSubject.send(.error(.init(with: error)))
}
}
} catch {
hudSubject.send(.error(.init(with: error)))
}
}
func didTapRequest(contact: Contact) {
hudSubject.send(.on(nil))
var contact = contact
contact.nickname = contact.username
do {
try self.session.add(contact)
hudSubject.send(.none)
successSubject.send(contact)
} catch {
hudSubject.send(.error(.init(with: error)))
}
}
func didSet(nickname: String, for contact: Contact) {
if var contact = try? session.dbManager.fetchContacts(.init(id: [contact.id])).first {
contact.nickname = nickname
_ = try? session.dbManager.saveContact(contact)
}
}
private func appendToLocalSearch(_ contact: Contact?) {
var snapshot = SearchSnapshot()
if let contact = contact {
snapshot.appendSections([.stranger])
snapshot.appendItems([.stranger(contact)], toSection: .stranger)
}
if let locals = try? session.dbManager.fetchContacts(Contact.Query(username: stateSubject.value.input)), locals.count > 0 {
snapshot.appendSections([.connections])
snapshot.appendItems(locals.map(SearchItem.connection), toSection: .connections)
}
stateSubject.value.snapshot = snapshot
}
}