import HUD import UIKit import Models import Shared import Combine import XXModels import Integration import ToastFeature import CombineSchedulers import DependencyInjection struct RequestSent: Hashable, Equatable { var request: Request var isResent: Bool = false } final class RequestsSentViewModel { @Dependency private var session: SessionType @Dependency private var toastController: ToastController var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() } var itemsPublisher: AnyPublisher<NSDiffableDataSourceSnapshot<Section, RequestSent>, Never> { itemsSubject.eraseToAnyPublisher() } private var cancellables = Set<AnyCancellable>() private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none) private let itemsSubject = CurrentValueSubject<NSDiffableDataSourceSnapshot<Section, RequestSent>, Never>(.init()) var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler() init() { let query = Contact.Query(authStatus: [ .requested, .requesting ]) session.dbManager.fetchContactsPublisher(query) .assertNoFailure() .removeDuplicates() .map { data -> NSDiffableDataSourceSnapshot<Section, RequestSent> in var snapshot = NSDiffableDataSourceSnapshot<Section, RequestSent>() snapshot.appendSections([.appearing]) snapshot.appendItems(data.map { RequestSent(request: .contact($0)) }, toSection: .appearing) return snapshot }.sink { [unowned self] in itemsSubject.send($0) } .store(in: &cancellables) } func didTapStateButtonFor(request item: RequestSent) { guard case let .contact(contact) = item.request, item.request.status == .requested else { return } hudSubject.send(.on(nil)) backgroundScheduler.schedule { [weak self] in guard let self = self else { return } do { try self.session.retryRequest(contact) self.hudSubject.send(.none) var item = item var allRequests = self.itemsSubject.value.itemIdentifiers if let indexOfRequest = allRequests.firstIndex(of: item) { allRequests.remove(at: indexOfRequest) } item.isResent = true allRequests.append(item) self.toastController.enqueueToast(model: .init( title: Localized.Requests.Sent.Toast.resent(contact.nickname ?? contact.username), leftImage: Asset.requestSentToaster.image )) var snapshot = NSDiffableDataSourceSnapshot<Section, RequestSent>() snapshot.appendSections([.appearing]) snapshot.appendItems(allRequests, toSection: .appearing) self.itemsSubject.send(snapshot) } catch { self.hudSubject.send(.error(.init(with: error))) } } } }