Newer
Older
import Defaults
import Integration
import DependencyInjection
enum SearchItem: Equatable, Hashable {
case chat(Chat)
case connection(Contact)
typealias RecentsSnapshot = NSDiffableDataSourceSnapshot<SectionId, Contact>
typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>
final class ChatListViewModel {
var isOnline: AnyPublisher<Bool, Never> {
session.isOnline
}
var chatsPublisher: AnyPublisher<[Chat], Never> {
chatsSubject.eraseToAnyPublisher()
}
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
var hudPublisher: AnyPublisher<HUDStatus, Never> {
hudSubject.eraseToAnyPublisher()
}
var recentsPublisher: AnyPublisher<RecentsSnapshot, Never> {
session.contacts(.isRecent).map {
let section = SectionId()
var snapshot = RecentsSnapshot()
snapshot.appendSections([section])
snapshot.appendItems($0, toSection: section)
return snapshot
}.eraseToAnyPublisher()
}
var searchPublisher: AnyPublisher<SearchSnapshot, Never> {
Publishers.CombineLatest3(
session.contacts(.all),
chatsPublisher,
searchSubject
.removeDuplicates()
.debounce(for: .milliseconds(100), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
)
.map { (contacts, chats, query) in
let connectionItems = contacts.filter {
let username = $0.username.lowercased().contains(query.lowercased())
let nickname = $0.nickname?.lowercased().contains(query.lowercased()) ?? false
return username || nickname
}.map(SearchItem.connection)
let chatItems = chats.filter {
switch $0 {
case .contact(let info):
let username = info.contact.username.lowercased().contains(query.lowercased())
let nickname = info.contact.nickname?.lowercased().contains(query.lowercased()) ?? false
let lastMessage = info.lastMessage?.payload.text.lowercased().contains(query.lowercased()) ?? false
return username || nickname || lastMessage
case .group(let info):
let name = info.group.name.lowercased().contains(query.lowercased())
let last = info.lastMessage?.payload.text.lowercased().contains(query.lowercased()) ?? false
return name || last
}
}.map(SearchItem.chat)
var snapshot = SearchSnapshot()
if connectionItems.count > 0 {
snapshot.appendSections([.connections])
snapshot.appendItems(connectionItems, toSection: .connections)
}
if chatItems.count > 0 {
snapshot.appendSections([.chats])
snapshot.appendItems(chatItems, toSection: .chats)
}
return snapshot
}.eraseToAnyPublisher()
}
Publishers.CombineLatest(
session.contacts(.received),
session.groups(.pending)
private var cancellables = Set<AnyCancellable>()
private let searchSubject = CurrentValueSubject<String, Never>("")
private let chatsSubject = CurrentValueSubject<[Chat], Never>([])
private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
session.groupChats(.accepted)
).map {
let groups = $0.1.map(Chat.group)
let chats = $0.0.map(Chat.contact)
return (chats + groups).sorted { $0.orderingDate > $1.orderingDate }
}
.sink { [unowned self] in chatsSubject.send($0) }
func updateSearch(query: String) {
searchSubject.send(query)
func clear(_ contact: Contact) {
session.deleteAll(from: contact)