diff --git a/Sources/InputField/InputField.swift b/Sources/InputField/InputField.swift index f0be951d47dbeeecebeb8abd5a3d56eb13c6e31c..47fda0152029c2ad3959cb2ff067bdb1bffaf981 100644 --- a/Sources/InputField/InputField.swift +++ b/Sources/InputField/InputField.swift @@ -153,7 +153,13 @@ public final class InputField: UIView { } public func update(placeholder: String) { - field.placeholder = placeholder + field.attributedPlaceholder = NSAttributedString( + string: placeholder, + attributes: [ + .font: Fonts.Mulish.semiBold.font(size: 14.0), + .foregroundColor: Asset.neutralDisabled.color + ] + ) } public func update(status: ValidationStatus) { diff --git a/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift b/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift index e9b48cb44dc6265e9908c69d7c2a0de5e447b639..33642c127af725e10d2d8496219446b776f1f5d6 100644 --- a/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift +++ b/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift @@ -1,7 +1,6 @@ import UIKit import Shared import Combine -import Defaults import Dependencies import AppResources import AppNavigation @@ -11,8 +10,6 @@ import ScrollViewController public final class SettingsDeleteController: UIViewController { @Dependency(\.navigator) var navigator - @KeyObject(.username, defaultValue: "") var username: String - private lazy var screenView = SettingsDeleteView() private lazy var scrollViewController = ScrollViewController() @@ -31,8 +28,6 @@ public final class SettingsDeleteController: UIViewController { setupScrollView() setupBindings() - screenView.update(username: username) - screenView.setInfoClosure { [weak self] in guard let self else { return } self.presentInfo( @@ -55,21 +50,40 @@ public final class SettingsDeleteController: UIViewController { private func setupBindings() { screenView - .cancelButton - .publisher(for: .touchUpInside) + .inputField + .textPublisher + .sink { [unowned self] in + viewModel.didEnterText($0) + }.store(in: &cancellables) + + viewModel + .statePublisher + .map(\.username) .receive(on: DispatchQueue.main) .sink { [unowned self] in - dismiss(animated: true) + screenView.inputField.update(placeholder: $0) + }.store(in: &cancellables) + + viewModel + .statePublisher + .map(\.isButtonEnabled) + .receive(on: DispatchQueue.main) + .dropFirst() + .sink { [unowned self] in + screenView.confirmButton.isEnabled = $0 + screenView.inputField.update( + status: $0 ? .valid("") : .invalid("") + ) }.store(in: &cancellables) screenView .inputField - .textPublisher + .returnPublisher + .receive(on: DispatchQueue.main) .sink { [unowned self] in - screenView.update( - status: $0 == username ? - .valid("") : .invalid("") - ) + if screenView.confirmButton.isEnabled { + viewModel.didTapDelete() + } }.store(in: &cancellables) screenView @@ -82,6 +96,7 @@ public final class SettingsDeleteController: UIViewController { screenView .cancelButton .publisher(for: .touchUpInside) + .receive(on: DispatchQueue.main) .sink { [unowned self] in navigationController?.popViewController(animated: true) }.store(in: &cancellables) diff --git a/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift index 05073defcb5aa9ca0c294776d841fcf575de95ec..e2a1912aa5cd68fc032ac2e54de0a1bc571ede70 100644 --- a/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift +++ b/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift @@ -1,4 +1,5 @@ import AppCore +import Combine import Defaults import Keychain import Foundation @@ -7,45 +8,65 @@ import AppResources import XXMessengerClient final class SettingsDeleteViewModel { + struct ViewState: Equatable { + var input = "" + var username: String + var isButtonEnabled = false + } + @Dependency(\.keychain) var keychain + @Dependency(\.app.bgQueue) var bgQueue @Dependency(\.app.dbManager) var dbManager @Dependency(\.app.messenger) var messenger @Dependency(\.app.hudManager) var hudManager @KeyObject(.username, defaultValue: nil) var username: String? - private var isCurrentlyDeleting = false - - func didTapDelete() { - guard isCurrentlyDeleting == false else { return } - isCurrentlyDeleting = true + var statePublisher: AnyPublisher<ViewState, Never> { + stateSubject.eraseToAnyPublisher() + } + + private let stateSubject: CurrentValueSubject<ViewState, Never> + + init() { + @KeyObject(.username, defaultValue: nil) var username: String? + self.stateSubject = .init(.init(username: username!)) + } + func didEnterText(_ string: String) { + stateSubject.value.input = string + stateSubject.value.isButtonEnabled = string == stateSubject.value.username + } + + func didTapDelete() { hudManager.show() - - do { - try cleanUD() - try messenger.destroy() - try keychain.destroy() - try dbManager.removeDB() - - UserDefaults.resetStandardUserDefaults() - UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) - UserDefaults.standard.synchronize() - - hudManager.show(.init( - title: Localized.Settings.Delete.Success.title, - content: Localized.Settings.Delete.Success.subtitle - )) - } catch { - DispatchQueue.main.async { [weak self] in - guard let self else { return } - self.hudManager.show(.init(error: error)) + + bgQueue.schedule { [weak self] in + guard let self else { return } + do { + try self.messenger.ud.tryGet().permanentDeleteAccount( + username: .init( + type: .username, + value: self.stateSubject.value.username + ) + ) + try self.messenger.destroy() + try self.keychain.destroy() + try self.dbManager.removeDB() + + UserDefaults.resetStandardUserDefaults() + UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) + UserDefaults.standard.synchronize() + + self.hudManager.show(.init( + title: Localized.Settings.Delete.Success.title, + content: Localized.Settings.Delete.Success.subtitle + )) + } catch { + DispatchQueue.main.async { [weak self] in + guard let self else { return } + self.hudManager.show(.init(error: error)) + } } } } - - private func cleanUD() throws { - try messenger.ud.get()!.permanentDeleteAccount( - username: .init(type: .username, value: username!) - ) - } } diff --git a/Sources/SettingsFeature/Views/SettingsDeleteView.swift b/Sources/SettingsFeature/Views/SettingsDeleteView.swift index 7ac68bccbbd95c0f299936ba726744fc3e26023b..8fd9bfab69b0db85fdc968bab03f0ecb1d7c05dc 100644 --- a/Sources/SettingsFeature/Views/SettingsDeleteView.swift +++ b/Sources/SettingsFeature/Views/SettingsDeleteView.swift @@ -99,19 +99,4 @@ final class SettingsDeleteView: UIView { func setInfoClosure(_ closure: @escaping () -> Void) { didTapInfo = closure } - - func update(username: String) { - inputField.update(placeholder: username) - } - - func update(status: InputField.ValidationStatus) { - inputField.update(status: status) - - switch status { - case .valid: - confirmButton.isEnabled = true - case .invalid, .unknown: - confirmButton.isEnabled = false - } - } }