Something went wrong on our end
-
Bruno Muniz authoredBruno Muniz authored
SearchViewModel.swift 5.60 KiB
import HUD
import UIKit
import Models
import Combine
import Defaults
import XXModels
import Countries
import Foundation
import Integration
import PushFeature
import CombineSchedulers
import DependencyInjection
enum SelectedFilter {
case username
case email
case phone
var prefix: String {
switch self {
case .username:
return "U"
case .phone:
return "P"
case .email:
return "E"
}
}
}
struct SearchViewState: Equatable {
var input: String = ""
var phoneInput: String = ""
var selectedFilter: SelectedFilter = .username
var country: Country = .fromMyPhone()
}
final class SearchViewModel {
@KeyObject(.dummyTrafficOn, defaultValue: false) var isCoverTrafficEnabled: Bool
@KeyObject(.pushNotifications, defaultValue: false) private var pushNotifications
@KeyObject(.askedDummyTrafficOnce, defaultValue: false) var offeredCoverTraffic: Bool
@Dependency private var session: SessionType
@Dependency private var pushHandler: PushHandling
var hudPublisher: AnyPublisher<HUDStatus, Never> {
hudSubject.eraseToAnyPublisher()
}
var placeholderPublisher: AnyPublisher<Bool, Never> {
placeholderSubject.eraseToAnyPublisher()
}
var coverTrafficPublisher: AnyPublisher<Void, Never> {
coverTrafficSubject.eraseToAnyPublisher()
}
var statePublisher: AnyPublisher<SearchViewState, Never> {
stateSubject.eraseToAnyPublisher()
}
var successPublisher: AnyPublisher<Contact, Never> {
successSubject.eraseToAnyPublisher()
}
var backgroundScheduler: AnySchedulerOf<DispatchQueue>
= DispatchQueue.global().eraseToAnyScheduler()
let itemsRelay = CurrentValueSubject<[Contact], Never>([])
private let successSubject = PassthroughSubject<Contact, Never>()
private let coverTrafficSubject = PassthroughSubject<Void, Never>()
private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
private let placeholderSubject = CurrentValueSubject<Bool, Never>(true)
private let stateSubject = CurrentValueSubject<SearchViewState, Never>(.init())
func didAppear() {
verifyCoverTraffic()
verifyNotifications()
}
func didSelect(filter: SelectedFilter) {
stateSubject.value.selectedFilter = filter
}
func didInput(_ string: String) {
stateSubject.value.input = string.trimmingCharacters(in: .whitespacesAndNewlines)
}
func didInputPhone(_ string: String) {
stateSubject.value.phoneInput = string.trimmingCharacters(in: .whitespacesAndNewlines)
}
func didChooseCountry(_ country: Country) {
stateSubject.value.country = country
}
func didEnableCoverTraffic() {
isCoverTrafficEnabled = true
session.setDummyTraffic(status: true)
}
func didTapSearch() {
hudSubject.send(.on(nil))
backgroundScheduler.schedule { [weak self] in
guard let self = self else { return }
do {
var content = self.stateSubject.value.selectedFilter.prefix
if self.stateSubject.value.selectedFilter == .phone {
content += self.stateSubject.value.phoneInput + self.stateSubject.value.country.code
} else {
content += self.stateSubject.value.input
}
try self.session.search(fact: content) { result in
self.placeholderSubject.send(false)
switch result {
case .success(let searched):
self.hudSubject.send(.none)
self.itemsRelay.send([searched])
case .failure(let error):
self.hudSubject.send(.error(.init(with: error)))
self.itemsRelay.send([])
}
}
} catch {
self.hudSubject.send(.error(.init(with: error)))
}
}
}
private func verifyCoverTraffic() {
guard offeredCoverTraffic == false else {
return
}
offeredCoverTraffic = true
coverTrafficSubject.send()
}
private func verifyNotifications() {
guard pushNotifications == false else { return }
pushHandler.requestAuthorization { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let granted):
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
self.pushNotifications = granted
case .failure:
self.pushNotifications = false
}
}
}
func didSet(nickname: String, for contact: Contact) {
var contact = contact
contact.nickname = nickname
backgroundScheduler.schedule { [weak self] in
guard let self = self else { return }
_ = try? self.session.dbManager.saveContact(contact)
}
}
func didTapRequest(contact: Contact) {
hudSubject.send(.on(nil))
var contact = contact
contact.nickname = contact.username
backgroundScheduler.schedule { [weak self] in
guard let self = self else { return }
do {
try self.session.add(contact)
self.hudSubject.send(.none)
self.successSubject.send(contact)
} catch {
self.hudSubject.send(.error(.init(with: error)))
}
}
}
}