From ce3f4f5e96adbb1749214d3a62fd6e4e2ac2b65b Mon Sep 17 00:00:00 2001 From: ihugo Date: Thu, 22 Apr 2021 23:02:24 +0800 Subject: [PATCH] refactor: Use single file organization classes. --- Mastodon.xcodeproj/project.pbxproj | 12 +- Mastodon/Scene/Report/ReportFooterView.swift | 108 ++++++++++ Mastodon/Scene/Report/ReportHeaderView.swift | 115 ++++++++++ Mastodon/Scene/Report/ReportView.swift | 201 ------------------ .../Scene/Report/ReportViewController.swift | 12 +- Mastodon/Scene/Report/ReportViewModel.swift | 16 +- 6 files changed, 245 insertions(+), 219 deletions(-) create mode 100644 Mastodon/Scene/Report/ReportFooterView.swift create mode 100644 Mastodon/Scene/Report/ReportHeaderView.swift delete mode 100644 Mastodon/Scene/Report/ReportView.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index e3f553ba7..d53252220 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -137,6 +137,7 @@ 5B24BBDB262DB14800A9381B /* ReportViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B24BBD8262DB14800A9381B /* ReportViewModel+Diffable.swift */; }; 5B24BBDC262DB14800A9381B /* ReportViewModel+Provider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B24BBD9262DB14800A9381B /* ReportViewModel+Provider.swift */; }; 5B24BBE2262DB19100A9381B /* APIService+Report.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B24BBE1262DB19100A9381B /* APIService+Report.swift */; }; + 5B8E055826319E47006E3C53 /* ReportFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8E055726319E47006E3C53 /* ReportFooterView.swift */; }; 5B90C45E262599800002E742 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90C456262599800002E742 /* SettingsViewModel.swift */; }; 5B90C45F262599800002E742 /* SettingsToggleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90C459262599800002E742 /* SettingsToggleTableViewCell.swift */; }; 5B90C460262599800002E742 /* SettingsAppearanceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90C45A262599800002E742 /* SettingsAppearanceTableViewCell.swift */; }; @@ -149,7 +150,7 @@ 5B90C48526259BF10002E742 /* APIService+Subscriptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90C48426259BF10002E742 /* APIService+Subscriptions.swift */; }; 5B90C48B26259C120002E742 /* APIService+CoreData+Subscriptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90C48A26259C120002E742 /* APIService+CoreData+Subscriptions.swift */; }; 5BB04FD5262E7AFF0043BFF6 /* ReportViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FD4262E7AFF0043BFF6 /* ReportViewController.swift */; }; - 5BB04FDB262EA3070043BFF6 /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FDA262EA3070043BFF6 /* ReportView.swift */; }; + 5BB04FDB262EA3070043BFF6 /* ReportHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FDA262EA3070043BFF6 /* ReportHeaderView.swift */; }; 5BB04FE9262EFC300043BFF6 /* ReportedStatusTableviewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FE8262EFC300043BFF6 /* ReportedStatusTableviewCell.swift */; }; 5BB04FEF262F0DCB0043BFF6 /* ReportViewModel+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FEE262F0DCB0043BFF6 /* ReportViewModel+Data.swift */; }; 5BB04FF5262F0E6D0043BFF6 /* ReportSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB04FF4262F0E6D0043BFF6 /* ReportSection.swift */; }; @@ -562,6 +563,7 @@ 5B24BBD8262DB14800A9381B /* ReportViewModel+Diffable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ReportViewModel+Diffable.swift"; sourceTree = ""; }; 5B24BBD9262DB14800A9381B /* ReportViewModel+Provider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ReportViewModel+Provider.swift"; sourceTree = ""; }; 5B24BBE1262DB19100A9381B /* APIService+Report.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+Report.swift"; sourceTree = ""; }; + 5B8E055726319E47006E3C53 /* ReportFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportFooterView.swift; sourceTree = ""; }; 5B90C456262599800002E742 /* SettingsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = ""; }; 5B90C459262599800002E742 /* SettingsToggleTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsToggleTableViewCell.swift; sourceTree = ""; }; 5B90C45A262599800002E742 /* SettingsAppearanceTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsAppearanceTableViewCell.swift; sourceTree = ""; }; @@ -574,7 +576,7 @@ 5B90C48426259BF10002E742 /* APIService+Subscriptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+Subscriptions.swift"; sourceTree = ""; }; 5B90C48A26259C120002E742 /* APIService+CoreData+Subscriptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+CoreData+Subscriptions.swift"; sourceTree = ""; }; 5BB04FD4262E7AFF0043BFF6 /* ReportViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportViewController.swift; sourceTree = ""; }; - 5BB04FDA262EA3070043BFF6 /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = ""; }; + 5BB04FDA262EA3070043BFF6 /* ReportHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportHeaderView.swift; sourceTree = ""; }; 5BB04FE8262EFC300043BFF6 /* ReportedStatusTableviewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportedStatusTableviewCell.swift; sourceTree = ""; }; 5BB04FEE262F0DCB0043BFF6 /* ReportViewModel+Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReportViewModel+Data.swift"; sourceTree = ""; }; 5BB04FF4262F0E6D0043BFF6 /* ReportSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSection.swift; sourceTree = ""; }; @@ -1250,7 +1252,8 @@ 5B24BBD9262DB14800A9381B /* ReportViewModel+Provider.swift */, 5BB04FEE262F0DCB0043BFF6 /* ReportViewModel+Data.swift */, 5BB04FD4262E7AFF0043BFF6 /* ReportViewController.swift */, - 5BB04FDA262EA3070043BFF6 /* ReportView.swift */, + 5BB04FDA262EA3070043BFF6 /* ReportHeaderView.swift */, + 5B8E055726319E47006E3C53 /* ReportFooterView.swift */, 5BB04FE8262EFC300043BFF6 /* ReportedStatusTableviewCell.swift */, ); path = Report; @@ -2369,6 +2372,7 @@ 2DFAD5372617010500F9EE7C /* SearchingTableViewCell.swift in Sources */, DB447681260B3ED600B66B82 /* CustomEmojiPickerSection.swift in Sources */, 5BB04FEF262F0DCB0043BFF6 /* ReportViewModel+Data.swift in Sources */, + 5B8E055826319E47006E3C53 /* ReportFooterView.swift in Sources */, DBB525502611ED6D002F1F29 /* ProfileHeaderView.swift in Sources */, 0FB3D33225E5F50E00AAD544 /* PickServerSearchCell.swift in Sources */, DB71FD5225F8CCAA00512AE1 /* APIService+Status.swift in Sources */, @@ -2542,7 +2546,7 @@ DB02CDBF2625AE5000D0A2AF /* AdaptiveUserInterfaceStyleBarButtonItem.swift in Sources */, DB1FD44425F26CCC004CFCFC /* PickServerSection.swift in Sources */, 0FB3D30F25E525CD00AAD544 /* PickServerCategoryView.swift in Sources */, - 5BB04FDB262EA3070043BFF6 /* ReportView.swift in Sources */, + 5BB04FDB262EA3070043BFF6 /* ReportHeaderView.swift in Sources */, DB2F073525E8ECF000957B2D /* AuthenticationViewModel.swift in Sources */, DB68A04A25E9027700CFDF14 /* AdaptiveStatusBarStyleNavigationController.swift in Sources */, 0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */, diff --git a/Mastodon/Scene/Report/ReportFooterView.swift b/Mastodon/Scene/Report/ReportFooterView.swift new file mode 100644 index 000000000..16948f58e --- /dev/null +++ b/Mastodon/Scene/Report/ReportFooterView.swift @@ -0,0 +1,108 @@ +// +// ReportFooterView.swift +// Mastodon +// +// Created by ihugo on 2021/4/22. +// + +import UIKit + +final class ReportFooterView: UIView { + enum Step: Int { + case one + case two + } + + lazy var stackview: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.alignment = .fill + view.spacing = 8 + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + lazy var nextStepButton: PrimaryActionButton = { + let button = PrimaryActionButton() + button.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + lazy var skipButton: UIButton = { + let button = UIButton(type: .system) + button.tintColor = Asset.Colors.brandBlue.color + button.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) + button.translatesAutoresizingMaskIntoConstraints = false + return button + }() + + var step: Step = .one { + didSet { + switch step { + case .one: + nextStepButton.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) + skipButton.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) + case .two: + nextStepButton.setTitle(L10n.Scene.Report.send, for: .normal) + skipButton.setTitle(L10n.Scene.Report.skipToSend, for: .normal) + } + } + } + + override init(frame: CGRect) { + super.init(frame: frame) + + self.backgroundColor = Asset.Colors.Background.elevatedPrimary.color + + stackview.addArrangedSubview(nextStepButton) + stackview.addArrangedSubview(skipButton) + addSubview(stackview) + + NSLayoutConstraint.activate([ + stackview.topAnchor.constraint( + equalTo: self.topAnchor, + constant: ReportView.continuTopMargin + ), + stackview.leadingAnchor.constraint( + equalTo: self.readableContentGuide.leadingAnchor, + constant: ReportView.horizontalMargin + ), + stackview.bottomAnchor.constraint( + equalTo: self.safeAreaLayoutGuide.bottomAnchor, + constant: -1 * ReportView.skipBottomMargin + ), + stackview.trailingAnchor.constraint( + equalTo: self.readableContentGuide.trailingAnchor, + constant: -1 * ReportView.horizontalMargin + ), + nextStepButton.heightAnchor.constraint( + equalToConstant: ReportView.buttonHeight + ), + skipButton.heightAnchor.constraint( + equalTo: nextStepButton.heightAnchor + ) + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +#if canImport(SwiftUI) && DEBUG +import SwiftUI + +struct ReportFooterView_Previews: PreviewProvider { + static var previews: some View { + Group { + UIViewPreview(width: 375) { () -> UIView in + return ReportFooterView(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 164))) + } + .previewLayout(.fixed(width: 375, height: 164)) + } + } + +} + +#endif diff --git a/Mastodon/Scene/Report/ReportHeaderView.swift b/Mastodon/Scene/Report/ReportHeaderView.swift new file mode 100644 index 000000000..bace3ada5 --- /dev/null +++ b/Mastodon/Scene/Report/ReportHeaderView.swift @@ -0,0 +1,115 @@ +// +// ReportView.swift +// Mastodon +// +// Created by ihugo on 2021/4/20. +// + +import UIKit + +struct ReportView { + static var horizontalMargin: CGFloat { return 12 } + static var verticalMargin: CGFloat { return 22 } + static var buttonHeight: CGFloat { return 46 } + static var skipBottomMargin: CGFloat { return 8 } + static var continuTopMargin: CGFloat { return 22 } +} + +final class ReportHeaderView: UIView { + enum Step: Int { + case one + case two + } + + lazy var titleLabel: UILabel = { + let label = UILabel() + label.textColor = Asset.Colors.Label.secondary.color + label.font = UIFontMetrics(forTextStyle: .subheadline) + .scaledFont(for: .systemFont(ofSize: 15, weight: .regular)) + label.numberOfLines = 0 + return label + }() + + lazy var contentLabel: UILabel = { + let label = UILabel() + label.textColor = Asset.Colors.Label.primary.color + label.font = UIFontMetrics(forTextStyle: .title3) + .scaledFont(for: .systemFont(ofSize: 20, weight: .semibold)) + label.numberOfLines = 0 + return label + }() + + lazy var stackview: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.alignment = .leading + view.spacing = 2 + return view + }() + + var step: Step = .one { + didSet { + switch step { + case .one: + titleLabel.text = L10n.Scene.Report.step1 + contentLabel.text = L10n.Scene.Report.content1 + case .two: + titleLabel.text = L10n.Scene.Report.step2 + contentLabel.text = L10n.Scene.Report.content2 + } + } + } + + override init(frame: CGRect) { + super.init(frame: frame) + + self.backgroundColor = Asset.Colors.Background.elevatedPrimary.color + stackview.addArrangedSubview(titleLabel) + stackview.addArrangedSubview(contentLabel) + addSubview(stackview) + + stackview.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + stackview.safeAreaLayoutGuide.topAnchor.constraint( + equalTo: self.topAnchor, + constant: ReportView.verticalMargin + ), + stackview.leadingAnchor.constraint( + equalTo: self.readableContentGuide.leadingAnchor, + constant: ReportView.horizontalMargin + ), + stackview.bottomAnchor.constraint( + equalTo: self.bottomAnchor, + constant: -1 * ReportView.verticalMargin + ), + stackview.trailingAnchor.constraint( + equalTo: self.readableContentGuide.trailingAnchor, + constant: -1 * ReportView.horizontalMargin + ) + ]) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +#if canImport(SwiftUI) && DEBUG +import SwiftUI + +struct ReportHeaderView_Previews: PreviewProvider { + static var previews: some View { + Group { + UIViewPreview { () -> UIView in + let view = ReportHeaderView() + view.step = .one + view.contentLabel.preferredMaxLayoutWidth = 335 + return view + } + .previewLayout(.fixed(width: 375, height: 110)) + } + } + +} + +#endif diff --git a/Mastodon/Scene/Report/ReportView.swift b/Mastodon/Scene/Report/ReportView.swift deleted file mode 100644 index 9166259fe..000000000 --- a/Mastodon/Scene/Report/ReportView.swift +++ /dev/null @@ -1,201 +0,0 @@ -// -// ReportView.swift -// Mastodon -// -// Created by ihugo on 2021/4/20. -// - -import UIKit - -struct ReportView { - static var horizontalMargin: CGFloat { return 12 } - static var verticalMargin: CGFloat { return 22 } - static var buttonHeight: CGFloat { return 46 } - static var skipBottomMargin: CGFloat { return 8 } - static var continuTopMargin: CGFloat { return 22 } -} - -final class ReportViewHeader: UIView { - enum Step: Int { - case one - case two - } - - lazy var titleLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.secondary.color - label.font = UIFont.preferredFont(forTextStyle: .subheadline) - label.numberOfLines = 0 - return label - }() - - lazy var contentLabel: UILabel = { - let label = UILabel() - label.textColor = Asset.Colors.Label.primary.color - label.font = UIFont.preferredFont(forTextStyle: .title3) - label.numberOfLines = 0 - return label - }() - - lazy var stackview: UIStackView = { - let view = UIStackView() - view.axis = .vertical - view.alignment = .leading - view.spacing = 2 - return view - }() - - var step: Step = .one { - didSet { - switch step { - case .one: - titleLabel.text = L10n.Scene.Report.step1 - contentLabel.text = L10n.Scene.Report.content1 - case .two: - titleLabel.text = L10n.Scene.Report.step2 - contentLabel.text = L10n.Scene.Report.content2 - } - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - - self.backgroundColor = Asset.Colors.Background.elevatedPrimary.color - stackview.addArrangedSubview(titleLabel) - stackview.addArrangedSubview(contentLabel) - addSubview(stackview) - - stackview.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - stackview.safeAreaLayoutGuide.topAnchor.constraint( - equalTo: self.topAnchor, - constant: ReportView.verticalMargin - ), - stackview.leadingAnchor.constraint( - equalTo: self.readableContentGuide.leadingAnchor, - constant: ReportView.horizontalMargin - ), - stackview.bottomAnchor.constraint( - equalTo: self.bottomAnchor, - constant: -1 * ReportView.verticalMargin - ), - stackview.trailingAnchor.constraint( - equalTo: self.readableContentGuide.trailingAnchor, - constant: -1 * ReportView.horizontalMargin - ) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -final class ReportViewFooter: UIView { - enum Step: Int { - case one - case two - } - - lazy var stackview: UIStackView = { - let view = UIStackView() - view.axis = .vertical - view.alignment = .fill - view.spacing = 8 - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() - - lazy var nextStepButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - return button - }() - - lazy var skipButton: UIButton = { - let button = UIButton(type: .system) - button.tintColor = Asset.Colors.brandBlue.color - button.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) - button.translatesAutoresizingMaskIntoConstraints = false - return button - }() - - var step: Step = .one { - didSet { - switch step { - case .one: - nextStepButton.setTitle(L10n.Common.Controls.Actions.continue, for: .normal) - skipButton.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) - case .two: - nextStepButton.setTitle(L10n.Scene.Report.send, for: .normal) - skipButton.setTitle(L10n.Scene.Report.skiptosend, for: .normal) - } - } - } - - override init(frame: CGRect) { - super.init(frame: frame) - - self.backgroundColor = Asset.Colors.Background.elevatedPrimary.color - - stackview.addArrangedSubview(nextStepButton) - stackview.addArrangedSubview(skipButton) - addSubview(stackview) - - NSLayoutConstraint.activate([ - stackview.topAnchor.constraint( - equalTo: self.topAnchor, - constant: ReportView.continuTopMargin - ), - stackview.leadingAnchor.constraint( - equalTo: self.readableContentGuide.leadingAnchor, - constant: ReportView.horizontalMargin - ), - stackview.bottomAnchor.constraint( - equalTo: self.safeAreaLayoutGuide.bottomAnchor, - constant: -1 * ReportView.skipBottomMargin - ), - stackview.trailingAnchor.constraint( - equalTo: self.readableContentGuide.trailingAnchor, - constant: -1 * ReportView.horizontalMargin - ), - nextStepButton.heightAnchor.constraint( - equalToConstant: ReportView.buttonHeight - ), - skipButton.heightAnchor.constraint( - equalTo: nextStepButton.heightAnchor - ) - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -} - -#if canImport(SwiftUI) && DEBUG -import SwiftUI - -struct ReportView_Previews: PreviewProvider { - static var previews: some View { - Group { - UIViewPreview { () -> UIView in - let view = ReportViewHeader() - view.step = .one - view.contentLabel.preferredMaxLayoutWidth = 335 - return view - } - .previewLayout(.fixed(width: 375, height: 110)) - - UIViewPreview(width: 375) { () -> UIView in - return ReportViewFooter(frame: CGRect(origin: .zero, size: CGSize(width: 375, height: 164))) - } - .previewLayout(.fixed(width: 375, height: 164)) - } - } - -} - -#endif diff --git a/Mastodon/Scene/Report/ReportViewController.swift b/Mastodon/Scene/Report/ReportViewController.swift index 7d46ae6b9..b00e4a3ee 100644 --- a/Mastodon/Scene/Report/ReportViewController.swift +++ b/Mastodon/Scene/Report/ReportViewController.swift @@ -30,14 +30,14 @@ class ReportViewController: UIViewController, NeedsDependency { let cancel = PassthroughSubject() // MAKK: - UI - lazy var header: ReportViewHeader = { - let view = ReportViewHeader() + lazy var header: ReportHeaderView = { + let view = ReportHeaderView() view.translatesAutoresizingMaskIntoConstraints = false return view }() - lazy var footer: ReportViewFooter = { - let view = ReportViewFooter() + lazy var footer: ReportFooterView = { + let view = ReportFooterView() view.translatesAutoresizingMaskIntoConstraints = false return view }() @@ -74,7 +74,7 @@ class ReportViewController: UIViewController, NeedsDependency { let textView = UITextView() textView.font = .preferredFont(forTextStyle: .body) textView.isScrollEnabled = false - textView.placeholder = L10n.Scene.Report.textplaceholder + textView.placeholder = L10n.Scene.Report.textPlaceholder textView.backgroundColor = .clear textView.delegate = self return textView @@ -194,7 +194,7 @@ class ReportViewController: UIViewController, NeedsDependency { }() navigationItem.title = L10n.Scene.Report.title( - "\(beReportedUser?.displayName ?? "@\(beReportedUser?.acct ?? "")")" + beReportedUser?.displayNameWithFallback ?? "" ) } diff --git a/Mastodon/Scene/Report/ReportViewModel.swift b/Mastodon/Scene/Report/ReportViewModel.swift index 94404af10..6feedc0b8 100644 --- a/Mastodon/Scene/Report/ReportViewModel.swift +++ b/Mastodon/Scene/Report/ReportViewModel.swift @@ -29,14 +29,14 @@ class ReportViewModel: NSObject, NeedsDependency { var selectedItems = [Item]() var comment: String? - internal var reportQuery: FileReportQuery - internal var disposeBag = Set() - internal let currentStep = CurrentValueSubject(.one) - internal let statusFetchedResultsController: StatusFetchedResultsController - internal var diffableDataSource: UITableViewDiffableDataSource? - internal let continueEnableSubject = CurrentValueSubject(false) - internal let sendEnableSubject = CurrentValueSubject(false) - internal let reportSuccess = PassthroughSubject() + var reportQuery: FileReportQuery + var disposeBag = Set() + let currentStep = CurrentValueSubject(.one) + let statusFetchedResultsController: StatusFetchedResultsController + var diffableDataSource: UITableViewDiffableDataSource? + let continueEnableSubject = CurrentValueSubject(false) + let sendEnableSubject = CurrentValueSubject(false) + let reportSuccess = PassthroughSubject() struct Input { let didToggleSelected: AnyPublisher