feat: add spam and other reason report flow path

This commit is contained in:
CMK 2022-05-10 18:53:02 +08:00
parent 2ef6345d83
commit a88bb763fb
5 changed files with 57 additions and 26 deletions

View File

@ -24,6 +24,12 @@ class ReportViewController: UIViewController, NeedsDependency, ReportViewControl
var viewModel: ReportViewModel! var viewModel: ReportViewModel!
lazy var cancelBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .cancel,
target: self,
action: #selector(ReportViewController.cancelBarButtonItemDidPressed(_:))
)
deinit { deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
} }
@ -38,6 +44,8 @@ extension ReportViewController {
setupAppearance() setupAppearance()
defer { setupNavigationBarBackgroundView() } defer { setupNavigationBarBackgroundView() }
navigationItem.rightBarButtonItem = cancelBarButtonItem
viewModel.reportReasonViewModel.delegate = self viewModel.reportReasonViewModel.delegate = self
viewModel.reportServerRulesViewModel.delegate = self viewModel.reportServerRulesViewModel.delegate = self
viewModel.reportStatusViewModel.delegate = self viewModel.reportStatusViewModel.delegate = self
@ -62,6 +70,14 @@ extension ReportViewController {
} }
extension ReportViewController {
@objc private func cancelBarButtonItemDidPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
}
// MARK: - UIAdaptivePresentationControllerDelegate // MARK: - UIAdaptivePresentationControllerDelegate
extension ReportViewController: UIAdaptivePresentationControllerDelegate { extension ReportViewController: UIAdaptivePresentationControllerDelegate {
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
@ -74,14 +90,21 @@ extension ReportViewController: ReportReasonViewControllerDelegate {
func reportReasonViewController(_ viewController: ReportReasonViewController, nextButtonPressed button: UIButton) { func reportReasonViewController(_ viewController: ReportReasonViewController, nextButtonPressed button: UIButton) {
guard let reason = viewController.viewModel.selectReason else { return } guard let reason = viewController.viewModel.selectReason else { return }
switch reason { switch reason {
case .dislike:
// TODO:
break
case .violateRule: case .violateRule:
coordinator.present( coordinator.present(
scene: .reportServerRules(viewModel: viewModel.reportServerRulesViewModel), scene: .reportServerRules(viewModel: viewModel.reportServerRulesViewModel),
from: self, from: self,
transition: .show transition: .show
) )
default: case .spam, .other:
break coordinator.present(
scene: .reportStatus(viewModel: viewModel.reportStatusViewModel),
from: self,
transition: .show
)
} }
} }
} }
@ -90,7 +113,7 @@ extension ReportViewController: ReportReasonViewControllerDelegate {
extension ReportViewController: ReportServerRulesViewControllerDelegate { extension ReportViewController: ReportServerRulesViewControllerDelegate {
func reportServerRulesViewController(_ viewController: ReportServerRulesViewController, nextButtonPressed button: UIButton) { func reportServerRulesViewController(_ viewController: ReportServerRulesViewController, nextButtonPressed button: UIButton) {
if viewController.viewModel.isDislike { if viewController.viewModel.isDislike {
// TODO:
} else if viewController.viewModel.selectRule != nil { } else if viewController.viewModel.selectRule != nil {
coordinator.present( coordinator.present(
scene: .reportStatus(viewModel: viewModel.reportStatusViewModel), scene: .reportStatus(viewModel: viewModel.reportStatusViewModel),

View File

@ -104,6 +104,9 @@ extension ReportViewModel {
let managedObjectContext = context.managedObjectContext let managedObjectContext = context.managedObjectContext
let _query: Mastodon.API.Reports.FileReportQuery? = try await managedObjectContext.perform { let _query: Mastodon.API.Reports.FileReportQuery? = try await managedObjectContext.perform {
guard let user = self.user.object(in: managedObjectContext) else { return nil } guard let user = self.user.object(in: managedObjectContext) else { return nil }
// the status picker is essential step in report flow
// only check isSkip or not
let statusIDs: [Status.ID]? = { let statusIDs: [Status.ID]? = {
if self.reportStatusViewModel.isSkip { if self.reportStatusViewModel.isSkip {
let _id: Status.ID? = self.reportStatusViewModel.status.flatMap { record -> Status.ID? in let _id: Status.ID? = self.reportStatusViewModel.status.flatMap { record -> Status.ID? in
@ -118,10 +121,15 @@ extension ReportViewModel {
} }
} }
}() }()
// the user comment is essential step in report flow
// only check isSkip or not
let comment: String? = { let comment: String? = {
var suffixes: [String] = [] var suffixes: [String] = []
let content: String? let content: String?
// the server rules is NOT essential step in report flow
// append suffix depends which reason
if let reason = self.reportReasonViewModel.selectReason { if let reason = self.reportReasonViewModel.selectReason {
switch reason { switch reason {
case .spam: case .spam:
@ -130,9 +138,12 @@ extension ReportViewModel {
suffixes.append(reason.rawValue) suffixes.append(reason.rawValue)
if let rule = self.reportServerRulesViewModel.selectRule { if let rule = self.reportServerRulesViewModel.selectRule {
suffixes.append(rule.text) suffixes.append(rule.text)
} else {
assertionFailure("should select valid rule")
} }
case .dislike:
case .dislike, .other: assertionFailure("should not enter the report flow")
case .other:
break break
} }
} }
@ -162,11 +173,14 @@ extension ReportViewModel {
do { do {
isReporting = true isReporting = true
#if DEBUG
try await Task.sleep(nanoseconds: .second * 3) try await Task.sleep(nanoseconds: .second * 3)
// let _ = try await context.apiService.report( #else
// query: query, let _ = try await context.apiService.report(
// authenticationBox: authenticationBox query: query,
// ) authenticationBox: authenticationBox
)
#endif
isReportSuccess = true isReportSuccess = true
} catch { } catch {
isReporting = false isReporting = false

View File

@ -30,12 +30,6 @@ final class ReportReasonViewController: UIViewController, NeedsDependency, Repor
var viewModel: ReportReasonViewModel! var viewModel: ReportReasonViewModel!
private(set) lazy var reportReasonView = ReportReasonView(viewModel: viewModel) private(set) lazy var reportReasonView = ReportReasonView(viewModel: viewModel)
lazy var cancelBarButtonItem = UIBarButtonItem(
barButtonSystemItem: .cancel,
target: self,
action: #selector(ReportReasonViewController.cancelBarButtonItemDidPressed(_:))
)
let navigationActionView: NavigationActionView = { let navigationActionView: NavigationActionView = {
let navigationActionView = NavigationActionView() let navigationActionView = NavigationActionView()
navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color
@ -57,8 +51,6 @@ extension ReportReasonViewController {
setupAppearance() setupAppearance()
defer { setupNavigationBarBackgroundView() } defer { setupNavigationBarBackgroundView() }
navigationItem.rightBarButtonItem = cancelBarButtonItem
let hostingViewController = UIHostingController(rootView: reportReasonView) let hostingViewController = UIHostingController(rootView: reportReasonView)
hostingViewController.view.preservesSuperviewLayoutMargins = true hostingViewController.view.preservesSuperviewLayoutMargins = true
addChild(hostingViewController) addChild(hostingViewController)
@ -102,10 +94,6 @@ extension ReportReasonViewController {
extension ReportReasonViewController { extension ReportReasonViewController {
@objc private func cancelBarButtonItemDidPressed(_ sender: UIBarButtonItem) {
dismiss(animated: true, completion: nil)
}
@objc private func nextButtonPressed(_ sender: UIButton) { @objc private func nextButtonPressed(_ sender: UIButton) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")

View File

@ -84,6 +84,8 @@ extension ReportSupplementaryViewController {
.sink { [weak self] isBusy in .sink { [weak self] isBusy in
guard let self = self else { return } guard let self = self else { return }
self.navigationItem.rightBarButtonItem = isBusy ? self.activityIndicatorBarButtonItem : self.cancelBarButtonItem self.navigationItem.rightBarButtonItem = isBusy ? self.activityIndicatorBarButtonItem : self.cancelBarButtonItem
self.navigationItem.hidesBackButton = isBusy
self.navigationActionView.backButton.isUserInteractionEnabled = !isBusy
} }
.store(in: &disposeBag) .store(in: &disposeBag)

View File

@ -34,11 +34,15 @@ class ReportSupplementaryViewModel {
self.user = user self.user = user
// end init // end init
commentContext.$comment Publishers.CombineLatest(
.map { comment -> Bool in commentContext.$comment,
return !comment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty $isBusy
} )
.assign(to: &$isNextButtonEnabled) .map { comment, isBusy -> Bool in
guard !isBusy else { return false }
return !comment.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}
.assign(to: &$isNextButtonEnabled)
} }
} }