Skip to content
Snippets Groups Projects
ContactViewModel.swift 4.33 KiB
Newer Older
Bruno Muniz's avatar
Bruno Muniz committed
import HUD
import UIKit
import Models
import Combine
import XXModels
Bruno Muniz's avatar
Bruno Muniz committed
import Integration
import CombineSchedulers
import DependencyInjection

struct ContactViewState: Equatable {
    var title: String?
    var email: String?
    var phone: String?
    var photo: UIImage?
    var username: String?
    var nickname: String?
}

final class ContactViewModel {
    @Dependency private var session: SessionType

    var contact: Contact

    var popToRootPublisher: AnyPublisher<Void, Never> { popToRootRelay.eraseToAnyPublisher() }
    var popPublisher: AnyPublisher<Void, Never> { popRelay.eraseToAnyPublisher() }
    var hudPublisher: AnyPublisher<HUDStatus, Never> { hudRelay.eraseToAnyPublisher() }
    var successPublisher: AnyPublisher<Void, Never> { successRelay.eraseToAnyPublisher() }
    var statePublisher: AnyPublisher<ContactViewState, Never> { stateRelay.eraseToAnyPublisher() }

    private let popRelay = PassthroughSubject<Void, Never>()
    private let popToRootRelay = PassthroughSubject<Void, Never>()
    private let successRelay = PassthroughSubject<Void, Never>()
    private let hudRelay = CurrentValueSubject<HUDStatus, Never>(.none)
    private let stateRelay = CurrentValueSubject<ContactViewState, Never>(.init())

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

    init(_ contact: Contact) {
        self.contact = contact

        do {
            let email = try session.extract(fact: .email, from: contact.marshaled!)
            let phone = try session.extract(fact: .phone, from: contact.marshaled!)
Bruno Muniz's avatar
Bruno Muniz committed

            stateRelay.value = .init(
                title: contact.nickname ?? contact.username,
                email: email,
                phone: phone,
                photo: contact.photo != nil ? UIImage(data: contact.photo!) : nil,
                username: contact.username,
                nickname: contact.nickname
            )
        } catch {
            print(error.localizedDescription)
        }
    }

    func didChoosePhoto(_ photo: UIImage) {
        stateRelay.value.photo = photo
        contact.photo = photo.jpegData(compressionQuality: 0.0)
        _ = try? session.dbManager.saveContact(contact)
Bruno Muniz's avatar
Bruno Muniz committed
    }

    func didTapDelete() {
Ahmed Shehata's avatar
Ahmed Shehata committed
        hudRelay.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed

        do {
            try session.deleteContact(contact)
            hudRelay.send(.none)
            popToRootRelay.send()
        } catch {
            hudRelay.send(.error(.init(with: error)))
        }
    }

    func didTapReject() {
        try? session.deleteContact(contact)
Bruno Muniz's avatar
Bruno Muniz committed
        popRelay.send()
    }

    func didTapClear() {
        _ = try? session.dbManager.deleteMessages(.init(chat: .direct(session.myId, contact.id)))
Bruno Muniz's avatar
Bruno Muniz committed
    }

    func didUpdateNickname(_ string: String) {
        contact.nickname = string.isEmpty ? nil : string
        stateRelay.value.title = string.isEmpty ? contact.username : string
        _ = try? session.dbManager.saveContact(contact)
Bruno Muniz's avatar
Bruno Muniz committed

        stateRelay.value.nickname = contact.nickname
    }

    func didTapResend() {
Ahmed Shehata's avatar
Ahmed Shehata committed
        hudRelay.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.add(self.contact)
                self.hudRelay.send(.none)
                self.popRelay.send()
            } catch {
                self.hudRelay.send(.error(.init(with: error)))
            }
        }
    }

    func didTapRequest(with nickname: String) {
Ahmed Shehata's avatar
Ahmed Shehata committed
        hudRelay.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed
        contact.nickname = nickname

        backgroundScheduler.schedule { [weak self] in
            guard let self = self else { return }

            do {
                try self.session.add(self.contact)
                self.hudRelay.send(.none)
                self.successRelay.send()
            } catch {
                self.hudRelay.send(.error(.init(with: error)))
            }
        }
    }

    func didTapAccept(_ nickname: String) {
Ahmed Shehata's avatar
Ahmed Shehata committed
        hudRelay.send(.on(nil))
Bruno Muniz's avatar
Bruno Muniz committed
        contact.nickname = nickname

        backgroundScheduler.schedule { [weak self] in
            guard let self = self else { return }

            do {
                try self.session.confirm(self.contact)
                self.hudRelay.send(.none)
                self.popRelay.send()
            } catch {
                self.hudRelay.send(.error(.init(with: error)))
            }
        }
    }
}