refactor: remove UI part from ReportViewmodel
This commit is contained in:
parent
479f21fd9f
commit
cbc828eec2
|
@ -362,7 +362,6 @@ extension HomeTimelineViewController {
|
|||
// 106093402888557459
|
||||
let viewModel = ReportViewModel(
|
||||
context: self.context,
|
||||
coordinator: self.coordinator,
|
||||
domain: authenticationBox.domain,
|
||||
userId: userId,
|
||||
statusId: statusId
|
||||
|
|
|
@ -12,6 +12,7 @@ import CoreDataStack
|
|||
import os.log
|
||||
import UIKit
|
||||
import TwitterTextEditor
|
||||
import MastodonSDK
|
||||
|
||||
class ReportViewController: UIViewController, NeedsDependency {
|
||||
static let kAnimationDuration: TimeInterval = 0.33
|
||||
|
@ -84,6 +85,12 @@ class ReportViewController: UIViewController, NeedsDependency {
|
|||
super.viewDidLoad()
|
||||
|
||||
setupView()
|
||||
|
||||
viewModel.setupDiffableDataSource(
|
||||
for: tableView,
|
||||
dependency: self
|
||||
)
|
||||
|
||||
bindViewModel()
|
||||
bindActions()
|
||||
}
|
||||
|
@ -127,8 +134,7 @@ class ReportViewController: UIViewController, NeedsDependency {
|
|||
step1Skip: step1Skip.eraseToAnyPublisher(),
|
||||
step2Continue: step2Continue.eraseToAnyPublisher(),
|
||||
step2Skip: step2Skip.eraseToAnyPublisher(),
|
||||
cancel: cancel.eraseToAnyPublisher(),
|
||||
tableView: tableView
|
||||
cancel: cancel.eraseToAnyPublisher()
|
||||
)
|
||||
let output = viewModel.transform(input: input)
|
||||
output?.currentStep
|
||||
|
@ -161,10 +167,26 @@ class ReportViewController: UIViewController, NeedsDependency {
|
|||
.assign(to: \.nextStepButton.isEnabled, on: footer)
|
||||
.store(in: &disposeBag)
|
||||
|
||||
output?.reportSuccess
|
||||
output?.reportResult
|
||||
.print()
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] (_) in
|
||||
.sink(receiveCompletion: { _ in
|
||||
}, receiveValue: { [weak self] data in
|
||||
let (success, error) = data
|
||||
if success {
|
||||
self?.dismiss(animated: true, completion: nil)
|
||||
} else if let error = error {
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fail to file a report : %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||
|
||||
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
self?.coordinator.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
)
|
||||
}
|
||||
})
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import MastodonSDK
|
|||
import UIKit
|
||||
import os.log
|
||||
|
||||
class ReportViewModel: NSObject, NeedsDependency {
|
||||
class ReportViewModel: NSObject {
|
||||
typealias FileReportQuery = Mastodon.API.Reports.FileReportQuery
|
||||
|
||||
enum Step: Int {
|
||||
|
@ -23,7 +23,6 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
|
||||
// confirm set only once
|
||||
weak var context: AppContext! { willSet { precondition(context == nil) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(coordinator == nil) } }
|
||||
var userId: String
|
||||
var statusId: String?
|
||||
|
||||
|
@ -34,7 +33,6 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
var diffableDataSource: UITableViewDiffableDataSource<ReportSection, Item>?
|
||||
let continueEnableSubject = CurrentValueSubject<Bool, Never>(false)
|
||||
let sendEnableSubject = CurrentValueSubject<Bool, Never>(false)
|
||||
let reportSuccess = PassthroughSubject<Void, Never>()
|
||||
|
||||
struct Input {
|
||||
let didToggleSelected: AnyPublisher<Item, Never>
|
||||
|
@ -44,24 +42,21 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
let step2Continue: AnyPublisher<Void, Never>
|
||||
let step2Skip: AnyPublisher<Void, Never>
|
||||
let cancel: AnyPublisher<Void, Never>
|
||||
let tableView: UITableView
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let currentStep: AnyPublisher<Step, Never>
|
||||
let continueEnableSubject: AnyPublisher<Bool, Never>
|
||||
let sendEnableSubject: AnyPublisher<Bool, Never>
|
||||
let reportSuccess: AnyPublisher<Void, Never>
|
||||
let reportResult: AnyPublisher<(Bool, Error?), Never>
|
||||
}
|
||||
|
||||
init(context: AppContext,
|
||||
coordinator: SceneCoordinator,
|
||||
domain: String,
|
||||
userId: String,
|
||||
statusId: String?
|
||||
) {
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
self.userId = userId
|
||||
self.statusId = statusId
|
||||
self.statusFetchedResultsController = StatusFetchedResultsController(
|
||||
|
@ -86,17 +81,12 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
}
|
||||
let domain = activeMastodonAuthenticationBox.domain
|
||||
|
||||
setupDiffableDataSource(
|
||||
for: input.tableView,
|
||||
dependency: self
|
||||
)
|
||||
|
||||
// data binding
|
||||
bindData(input: input)
|
||||
|
||||
// step1 and step2 binding
|
||||
bindForStep1(input: input)
|
||||
bindForStep2(
|
||||
let reportResult = bindForStep2(
|
||||
input: input,
|
||||
domain: domain,
|
||||
activeMastodonAuthenticationBox: activeMastodonAuthenticationBox
|
||||
|
@ -114,7 +104,7 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
currentStep: currentStep.eraseToAnyPublisher(),
|
||||
continueEnableSubject: continueEnableSubject.eraseToAnyPublisher(),
|
||||
sendEnableSubject: sendEnableSubject.eraseToAnyPublisher(),
|
||||
reportSuccess: reportSuccess.eraseToAnyPublisher()
|
||||
reportResult: reportResult
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -172,42 +162,35 @@ class ReportViewModel: NSObject, NeedsDependency {
|
|||
.store(in: &disposeBag)
|
||||
}
|
||||
|
||||
func bindForStep2(input: Input, domain: String, activeMastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) {
|
||||
func bindForStep2(input: Input, domain: String, activeMastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) -> AnyPublisher<(Bool, Error?), Never> {
|
||||
let skip = input.step2Skip.map { [weak self] value -> Void in
|
||||
guard let self = self else { return value }
|
||||
self.reportQuery.comment = nil
|
||||
return value
|
||||
}
|
||||
|
||||
Publishers.Merge(skip, input.step2Continue)
|
||||
.sink { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.context.apiService.report(
|
||||
return Publishers.Merge(skip, input.step2Continue)
|
||||
.flatMap { [weak self] (_) -> AnyPublisher<(Bool, Error?), Never> in
|
||||
guard let self = self else {
|
||||
return Empty(completeImmediately: true).eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
return self.context.apiService.report(
|
||||
domain: domain,
|
||||
query: self.reportQuery,
|
||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox
|
||||
)
|
||||
.sink { [weak self](data) in
|
||||
switch data {
|
||||
case .failure(let error):
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fail to file a report : %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
|
||||
|
||||
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: "OK", style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
self?.coordinator.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
)
|
||||
case .finished:
|
||||
self?.reportSuccess.send()
|
||||
.map({ (content) -> (Bool, Error?) in
|
||||
return (true, nil)
|
||||
})
|
||||
.eraseToAnyPublisher()
|
||||
.tryCatch({ (error) -> AnyPublisher<(Bool, Error?), Never> in
|
||||
return Just((false, error)).eraseToAnyPublisher()
|
||||
})
|
||||
// to covert to AnyPublisher<(Bool, Error?), Never>
|
||||
.replaceError(with: (false, nil))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
} receiveValue: { (data) in
|
||||
}
|
||||
.store(in: &self.disposeBag)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Combine
|
||||
import Foundation
|
||||
import enum NIOHTTP1.HTTPResponseStatus
|
||||
|
||||
extension Mastodon.API.Reports {
|
||||
static func reportsEndpointURL(domain: String) -> URL {
|
||||
|
@ -39,13 +40,23 @@ extension Mastodon.API.Reports {
|
|||
)
|
||||
return session.dataTaskPublisher(for: request)
|
||||
.tryMap { data, response in
|
||||
if let response = response as? HTTPURLResponse {
|
||||
guard let response = response as? HTTPURLResponse else {
|
||||
assertionFailure()
|
||||
throw NSError()
|
||||
}
|
||||
|
||||
if response.statusCode == 200 {
|
||||
return Mastodon.Response.Content(
|
||||
value: response.statusCode == 200,
|
||||
value: true,
|
||||
response: response
|
||||
)
|
||||
} else {
|
||||
let httpResponseStatus = HTTPResponseStatus(statusCode: response.statusCode)
|
||||
throw Mastodon.API.Error(
|
||||
httpResponseStatus: httpResponseStatus,
|
||||
mastodonError: nil
|
||||
)
|
||||
}
|
||||
return Mastodon.Response.Content(value: false, response: response)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue