Skip to content
Snippets Groups Projects
RequestsSentViewModel.swift 2.96 KiB
Newer Older
Bruno Muniz's avatar
Bruno Muniz committed
import HUD
import UIKit
Bruno Muniz's avatar
Bruno Muniz committed
import Models
import Shared
import Combine
Bruno Muniz's avatar
Bruno Muniz committed
import Integration
import ToastFeature
Bruno Muniz's avatar
Bruno Muniz committed
import CombineSchedulers
import DependencyInjection
Bruno Muniz's avatar
Bruno Muniz committed

struct RequestSent: Hashable, Equatable {
    var request: Request
    var isResent: Bool = false
}
Bruno Muniz's avatar
Bruno Muniz committed

final class RequestsSentViewModel {
Bruno Muniz's avatar
Bruno Muniz committed
    @Dependency private var session: SessionType
    @Dependency private var toastController: ToastController
Bruno Muniz's avatar
Bruno Muniz committed

    var hudPublisher: AnyPublisher<HUDStatus, Never> {
        hudSubject.eraseToAnyPublisher()
Bruno Muniz's avatar
Bruno Muniz committed
    }

    var itemsPublisher: AnyPublisher<NSDiffableDataSourceSnapshot<Section, RequestSent>, Never> {
        itemsSubject.eraseToAnyPublisher()
Bruno Muniz's avatar
Bruno Muniz committed
    }

    private var cancellables = Set<AnyCancellable>()
    private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
    private let itemsSubject = CurrentValueSubject<NSDiffableDataSourceSnapshot<Section, RequestSent>, Never>(.init())
Bruno Muniz's avatar
Bruno Muniz committed

    var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()

    init() {
        session.dbManager.fetchContactsPublisher(.init(authStatus: [.requested]))
            .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) }
Bruno Muniz's avatar
Bruno Muniz committed
            .store(in: &cancellables)
    }

    func didTapStateButtonFor(request item: RequestSent) {
        guard case let .contact(contact) = item.request, item.request.status == .requested else { return }
Bruno Muniz's avatar
Bruno Muniz committed

        hudSubject.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed
        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)
Bruno Muniz's avatar
Bruno Muniz committed
            } catch {
                self.hudSubject.send(.error(.init(with: error)))