Refactor: Remove NeedsDependency
The AppContext is already a singleton. SceneCoordinators are unique to UIWindowScenes, so fetch them that way. Fixes iOS-324
This commit is contained in:
parent
fc7ebd65f8
commit
65bf555d98
@ -397,7 +397,6 @@
|
||||
DB87D4452609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB87D4442609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift */; };
|
||||
DB87D4512609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB87D4502609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift */; };
|
||||
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */; };
|
||||
DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54325C13647002E6C99 /* NeedsDependency.swift */; };
|
||||
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */; };
|
||||
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55C25C138B7002E6C99 /* UIViewController.swift */; };
|
||||
DB8F7076279E954700E1225B /* DataSourceFacade+Follow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8F7075279E954700E1225B /* DataSourceFacade+Follow.swift */; };
|
||||
@ -1100,7 +1099,6 @@
|
||||
DB87D4502609CF1E00D12C0D /* ComposeStatusPollOptionAppendEntryCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeStatusPollOptionAppendEntryCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
DB89BA1025C10FF5008580ED /* Mastodon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mastodon.entitlements; sourceTree = "<group>"; };
|
||||
DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = "<group>"; };
|
||||
DB8AF54325C13647002E6C99 /* NeedsDependency.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeedsDependency.swift; sourceTree = "<group>"; };
|
||||
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = "<group>"; };
|
||||
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
||||
DB8D8E3128196FA0009FD90F /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Intents.strings; sourceTree = "<group>"; };
|
||||
@ -2588,7 +2586,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DB8AF54225C13647002E6C99 /* SceneCoordinator.swift */,
|
||||
DB8AF54325C13647002E6C99 /* NeedsDependency.swift */,
|
||||
D8F9170E2A4B47EF008A5370 /* Coordinator.swift */,
|
||||
);
|
||||
path = Coordinator;
|
||||
@ -3812,7 +3809,6 @@
|
||||
2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */,
|
||||
DBEFCD7B282A162400C0ABEA /* ReportReasonView.swift in Sources */,
|
||||
D8E5C346296DAB84007E76A7 /* DataSourceFacade+Status+History.swift in Sources */,
|
||||
DB8AF54525C13647002E6C99 /* NeedsDependency.swift in Sources */,
|
||||
DB63F77B279ACAE500455B82 /* DataSourceFacade+Favorite.swift in Sources */,
|
||||
DB9D6BF825E4F5690051B173 /* NotificationViewController.swift in Sources */,
|
||||
2DAC9E46262FC9FD0062E1A6 /* SuggestionAccountTableViewCell.swift in Sources */,
|
||||
|
@ -15,7 +15,7 @@ final class SafariActivity: UIActivity {
|
||||
weak var sceneCoordinator: SceneCoordinator?
|
||||
var url: NSURL?
|
||||
|
||||
init(sceneCoordinator: SceneCoordinator) {
|
||||
init(sceneCoordinator: SceneCoordinator?) {
|
||||
self.sceneCoordinator = sceneCoordinator
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// NeedsDependency.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by Cirno MainasuK on 2021-1-27.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import MastodonCore
|
||||
|
||||
protocol NeedsDependency: AnyObject {
|
||||
//FIXME: Get rid of ! ~@zeitschlag
|
||||
var context: AppContext! { get set }
|
||||
var coordinator: SceneCoordinator! { get set }
|
||||
}
|
||||
|
||||
typealias ViewControllerWithDependencies = NeedsDependency & UIViewController
|
||||
|
||||
|
@ -17,11 +17,14 @@ import MBProgressHUD
|
||||
@MainActor
|
||||
final public class SceneCoordinator {
|
||||
|
||||
fileprivate static func coordinator(for view: UIView) -> SceneCoordinator? {
|
||||
return SceneDelegate.delegate(for: view)?.coordinator
|
||||
}
|
||||
|
||||
private var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
private weak var scene: UIScene!
|
||||
private weak var sceneDelegate: SceneDelegate!
|
||||
private(set) weak var appContext: AppContext!
|
||||
|
||||
var authenticationBox: MastodonAuthenticationBox? {
|
||||
AuthenticationServiceProvider.shared.currentActiveUser.value
|
||||
@ -45,7 +48,6 @@ final public class SceneCoordinator {
|
||||
) {
|
||||
self.scene = scene
|
||||
self.sceneDelegate = sceneDelegate
|
||||
self.appContext = appContext
|
||||
|
||||
NotificationService.shared.requestRevealNotificationPublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
@ -118,7 +120,6 @@ final public class SceneCoordinator {
|
||||
break
|
||||
case .mention, .reblog, .favourite, .poll, .status:
|
||||
let threadViewModel = RemoteThreadViewModel(
|
||||
context: appContext,
|
||||
authenticationBox: authenticationBox,
|
||||
notificationID: notificationID
|
||||
)
|
||||
@ -250,17 +251,18 @@ extension SceneCoordinator {
|
||||
|
||||
switch UIDevice.current.userInterfaceIdiom {
|
||||
case .phone:
|
||||
let viewController = MainTabBarController(context: appContext, coordinator: self, authenticationBox: authenticationBox)
|
||||
let viewController = MainTabBarController(authenticationBox: authenticationBox)
|
||||
self.splitViewController = nil
|
||||
self.tabBarController = viewController
|
||||
rootViewController = viewController
|
||||
default:
|
||||
let splitViewController = RootSplitViewController(context: appContext, coordinator: self, authenticationBox: authenticationBox)
|
||||
let splitViewController = RootSplitViewController(authenticationBox: authenticationBox)
|
||||
self.splitViewController = splitViewController
|
||||
self.tabBarController = splitViewController.contentSplitViewController.mainTabBarController
|
||||
rootViewController = splitViewController
|
||||
}
|
||||
|
||||
// this feels wrong
|
||||
sceneDelegate.window?.rootViewController = rootViewController // base: main
|
||||
self.rootViewController = rootViewController
|
||||
|
||||
@ -268,7 +270,7 @@ extension SceneCoordinator {
|
||||
DispatchQueue.main.async {
|
||||
_ = self.present(
|
||||
scene: .welcome,
|
||||
from: self.sceneDelegate.window?.rootViewController,
|
||||
from: rootViewController, // self.sceneDelegate.window?.rootViewController,
|
||||
transition: .modal(animated: true, completion: nil)
|
||||
)
|
||||
}
|
||||
@ -422,13 +424,11 @@ private extension SceneCoordinator {
|
||||
let _viewController = WebViewController(viewModel)
|
||||
viewController = _viewController
|
||||
case .searchDetail(let viewModel):
|
||||
let _viewController = SearchDetailViewController(appContext: appContext, sceneCoordinator: self, authenticationBox: viewModel.authenticationBox)
|
||||
let _viewController = SearchDetailViewController(authenticationBox: viewModel.authenticationBox)
|
||||
_viewController.viewModel = viewModel
|
||||
viewController = _viewController
|
||||
case .searchResult(let viewModel):
|
||||
let searchResultViewController = SearchResultViewController()
|
||||
searchResultViewController.context = appContext
|
||||
searchResultViewController.coordinator = self
|
||||
searchResultViewController.viewModel = viewModel
|
||||
viewController = searchResultViewController
|
||||
case .compose(let viewModel):
|
||||
@ -460,19 +460,19 @@ private extension SceneCoordinator {
|
||||
case .followedTags(let viewModel):
|
||||
guard let authenticationBox else { return nil }
|
||||
|
||||
viewController = FollowedTagsViewController(appContext: appContext, sceneCoordinator: self, authenticationBox: authenticationBox, viewModel: viewModel)
|
||||
viewController = FollowedTagsViewController(authenticationBox: authenticationBox, viewModel: viewModel)
|
||||
case .favorite(let viewModel):
|
||||
let _viewController = FavoriteViewController()
|
||||
_viewController.viewModel = viewModel
|
||||
viewController = _viewController
|
||||
case .follower(let viewModel):
|
||||
let followerListViewController = FollowerListViewController(viewModel: viewModel, coordinator: self, context: appContext)
|
||||
let followerListViewController = FollowerListViewController(viewModel: viewModel)
|
||||
viewController = followerListViewController
|
||||
case .following(let viewModel):
|
||||
let followingListViewController = FollowingListViewController(viewModel: viewModel, coordinator: self, context: appContext)
|
||||
let followingListViewController = FollowingListViewController(viewModel: viewModel)
|
||||
viewController = followingListViewController
|
||||
case .familiarFollowers(let viewModel):
|
||||
viewController = FamiliarFollowersViewController(viewModel: viewModel, context: appContext, coordinator: self)
|
||||
viewController = FamiliarFollowersViewController(viewModel: viewModel)
|
||||
case .rebloggedBy(let viewModel):
|
||||
let _viewController = RebloggedByViewController()
|
||||
_viewController.viewModel = viewModel
|
||||
@ -539,7 +539,7 @@ private extension SceneCoordinator {
|
||||
let settingsCoordinator = SettingsCoordinator(presentedOn: presentedOn,
|
||||
accountName: accountName,
|
||||
setting: setting,
|
||||
appContext: appContext,
|
||||
appContext: AppContext.shared,
|
||||
authenticationBox: authenticationBox,
|
||||
sceneCoordinator: self
|
||||
)
|
||||
@ -557,18 +557,11 @@ private extension SceneCoordinator {
|
||||
case .notificationPolicy(let viewModel):
|
||||
viewController = NotificationPolicyViewController(viewModel: viewModel)
|
||||
case .accountNotificationTimeline(let viewModel, let request):
|
||||
viewController = AccountNotificationTimelineViewController(viewModel: viewModel, context: appContext, coordinator: self, notificationRequest: request)
|
||||
viewController = AccountNotificationTimelineViewController(viewModel: viewModel, notificationRequest: request)
|
||||
}
|
||||
|
||||
setupDependency(for: viewController as? NeedsDependency)
|
||||
|
||||
return viewController
|
||||
}
|
||||
|
||||
private func setupDependency(for needs: NeedsDependency?) {
|
||||
needs?.context = appContext
|
||||
needs?.coordinator = self
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - Loading
|
||||
@ -692,3 +685,10 @@ extension SceneCoordinator: SettingsCoordinatorDelegate {
|
||||
self.mastodonAuthenticationController = authenticationController
|
||||
}
|
||||
}
|
||||
|
||||
public extension UIViewController {
|
||||
var sceneCoordinator: SceneCoordinator? {
|
||||
guard let view = viewIfLoaded else { assert(false); return nil }
|
||||
return SceneCoordinator.coordinator(for: view)
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ extension ReportSection {
|
||||
case .status(let status):
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportStatusTableViewCell.self), for: indexPath) as! ReportStatusTableViewCell
|
||||
configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: .init(value: status),
|
||||
@ -83,19 +82,16 @@ extension ReportSection {
|
||||
extension ReportSection {
|
||||
|
||||
static func configure(
|
||||
context: AppContext,
|
||||
tableView: UITableView,
|
||||
cell: ReportStatusTableViewCell,
|
||||
viewModel: ReportStatusTableViewCell.ViewModel,
|
||||
configuration: Configuration
|
||||
) {
|
||||
StatusSection.setupStatusPollDataSource(
|
||||
context: context,
|
||||
authenticationBox: configuration.authenticationBox,
|
||||
statusView: cell.statusView
|
||||
)
|
||||
|
||||
cell.statusView.viewModel.context = context
|
||||
cell.statusView.viewModel.authenticationBox = configuration.authenticationBox
|
||||
|
||||
cell.configure(
|
||||
|
@ -24,7 +24,6 @@ enum StatusSection: Equatable, Hashable {
|
||||
extension StatusSection {
|
||||
|
||||
struct Configuration {
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
weak var statusTableViewCellDelegate: StatusTableViewCellDelegate?
|
||||
weak var timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?
|
||||
@ -33,7 +32,6 @@ extension StatusSection {
|
||||
|
||||
static func diffableDataSource(
|
||||
tableView: UITableView,
|
||||
context: AppContext,
|
||||
configuration: Configuration
|
||||
) -> UITableViewDiffableDataSource<StatusSection, StatusItem> {
|
||||
tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self))
|
||||
@ -48,7 +46,6 @@ extension StatusSection {
|
||||
let displayItem = StatusTableViewCell.StatusTableViewCellViewModel.DisplayItem.feed(feed)
|
||||
let contentConcealModel = StatusView.ContentConcealViewModel(status: feed.status, filterBox: StatusFilterService.shared.activeFilterBox, filterContext: configuration.filterContext)
|
||||
configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel(displayItem: displayItem, contentConcealModel: contentConcealModel),
|
||||
@ -68,7 +65,6 @@ extension StatusSection {
|
||||
let displayItem = StatusTableViewCell.StatusTableViewCellViewModel.DisplayItem.status(status)
|
||||
let contentConcealModel = StatusView.ContentConcealViewModel(status: status, filterBox: StatusFilterService.shared.activeFilterBox, filterContext: configuration.filterContext)
|
||||
configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel(displayItem: displayItem, contentConcealModel: contentConcealModel),
|
||||
@ -77,7 +73,6 @@ extension StatusSection {
|
||||
return cell
|
||||
case .thread(let thread):
|
||||
let cell = dequeueConfiguredReusableCell(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
indexPath: indexPath,
|
||||
configuration: ThreadCellRegistrationConfiguration(
|
||||
@ -108,7 +103,6 @@ extension StatusSection {
|
||||
}
|
||||
|
||||
static func dequeueConfiguredReusableCell(
|
||||
context: AppContext,
|
||||
tableView: UITableView,
|
||||
indexPath: IndexPath,
|
||||
configuration: ThreadCellRegistrationConfiguration
|
||||
@ -118,7 +112,6 @@ extension StatusSection {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusThreadRootTableViewCell.self), for: indexPath) as! StatusThreadRootTableViewCell
|
||||
let contentConcealModel = StatusView.ContentConcealViewModel(status: threadContext.status, filterBox: StatusFilterService.shared.activeFilterBox, filterContext: .thread)
|
||||
StatusSection.configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel(displayItem: .status(threadContext.status), contentConcealModel: contentConcealModel),
|
||||
@ -132,9 +125,7 @@ extension StatusSection {
|
||||
let contentConcealModel = StatusView.ContentConcealViewModel(status: threadContext.status, filterBox: StatusFilterService.shared.activeFilterBox, filterContext: configuration.configuration.filterContext)
|
||||
assert(configuration.configuration.filterContext == .thread)
|
||||
StatusSection.configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
tableView: tableView, cell: cell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel(displayItem: displayItem, contentConcealModel: contentConcealModel),
|
||||
configuration: configuration.configuration
|
||||
)
|
||||
@ -147,7 +138,6 @@ extension StatusSection {
|
||||
extension StatusSection {
|
||||
|
||||
public static func setupStatusPollDataSource(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
statusView: StatusView
|
||||
) {
|
||||
@ -206,19 +196,16 @@ extension StatusSection {
|
||||
extension StatusSection {
|
||||
|
||||
static func configure(
|
||||
context: AppContext,
|
||||
tableView: UITableView,
|
||||
cell: StatusTableViewCell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel,
|
||||
configuration: Configuration
|
||||
) {
|
||||
setupStatusPollDataSource(
|
||||
context: context,
|
||||
authenticationBox: configuration.authenticationBox,
|
||||
statusView: cell.statusView
|
||||
)
|
||||
|
||||
cell.statusView.viewModel.context = configuration.context
|
||||
cell.statusView.viewModel.authenticationBox = configuration.authenticationBox
|
||||
|
||||
cell.configure(
|
||||
@ -229,19 +216,16 @@ extension StatusSection {
|
||||
}
|
||||
|
||||
static func configure(
|
||||
context: AppContext,
|
||||
tableView: UITableView,
|
||||
cell: StatusThreadRootTableViewCell,
|
||||
viewModel: StatusTableViewCell.StatusTableViewCellViewModel,
|
||||
configuration: Configuration
|
||||
) {
|
||||
setupStatusPollDataSource(
|
||||
context: context,
|
||||
authenticationBox: configuration.authenticationBox,
|
||||
statusView: cell.statusView
|
||||
)
|
||||
|
||||
cell.statusView.viewModel.context = configuration.context
|
||||
cell.statusView.viewModel.authenticationBox = configuration.authenticationBox
|
||||
|
||||
cell.configure(
|
||||
|
@ -21,7 +21,6 @@ enum UserSection: Hashable {
|
||||
extension UserSection {
|
||||
static func diffableDataSource(
|
||||
tableView: UITableView,
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
userTableViewCellDelegate: UserTableViewCellDelegate?
|
||||
) -> UITableViewDiffableDataSource<UserSection, UserItem> {
|
||||
|
@ -12,7 +12,7 @@ import MastodonSDK
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToUserBlockAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
dependency: AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws -> Mastodon.Entity.Relationship {
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
@ -35,7 +35,7 @@ extension DataSourceFacade {
|
||||
}
|
||||
|
||||
static func responseToDomainBlockAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
dependency: AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws -> Mastodon.Entity.Empty {
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
@ -14,7 +14,7 @@ import MastodonSDK
|
||||
extension DataSourceFacade {
|
||||
@MainActor
|
||||
public static func responseToStatusBookmarkAction(
|
||||
provider: NeedsDependency & AuthContextProvider & DataSourceProvider,
|
||||
provider: AuthContextProvider & DataSourceProvider,
|
||||
status: MastodonStatus
|
||||
) async throws {
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
@ -14,7 +14,7 @@ import MastodonLocalization
|
||||
extension DataSourceFacade {
|
||||
@MainActor
|
||||
static func responseToUserFollowAction(
|
||||
dependency: ViewControllerWithDependencies & AuthContextProvider,
|
||||
dependency: UIViewController & AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws -> Mastodon.Entity.Relationship {
|
||||
let authBox = dependency.authenticationBox
|
||||
@ -78,7 +78,7 @@ extension DataSourceFacade {
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToUserFollowRequestAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
dependency: UIViewController & AuthContextProvider,
|
||||
notification: MastodonNotification,
|
||||
notificationView: NotificationView,
|
||||
query: Mastodon.API.Account.FollowRequestQuery
|
||||
@ -129,10 +129,11 @@ extension DataSourceFacade {
|
||||
case .notFound:
|
||||
break
|
||||
default:
|
||||
guard let coordinator = await dependency.sceneCoordinator else { return }
|
||||
let alertController = await UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = await UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||
await alertController.addAction(okAction)
|
||||
_ = await dependency.coordinator.present(
|
||||
_ = await coordinator.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
@ -146,7 +147,7 @@ extension DataSourceFacade {
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToShowHideReblogAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
dependency: AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws {
|
||||
let newRelationship = try await APIService.shared.toggleShowReblogs(
|
||||
|
@ -13,16 +13,16 @@ import MastodonSDK
|
||||
extension DataSourceFacade {
|
||||
@MainActor
|
||||
static func coordinateToHashtagScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController,
|
||||
tag: Mastodon.Entity.Tag
|
||||
) async {
|
||||
guard let authBox = AuthenticationServiceProvider.shared.currentActiveUser.value else { return }
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(
|
||||
context: provider.context,
|
||||
authenticationBox: provider.authenticationBox,
|
||||
authenticationBox: authBox,
|
||||
hashtag: tag.name
|
||||
)
|
||||
|
||||
_ = provider.coordinator.present(
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel),
|
||||
from: provider,
|
||||
transition: .show
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
@ -15,16 +16,17 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func coordinateToMediaPreviewScene(
|
||||
dependency: NeedsDependency & MediaPreviewableViewController,
|
||||
dependency: UIViewController & MediaPreviewableViewController,
|
||||
mediaPreviewItem: MediaPreviewViewModel.PreviewItem,
|
||||
mediaPreviewTransitionItem: MediaPreviewTransitionItem
|
||||
) {
|
||||
let mediaPreviewViewModel = MediaPreviewViewModel(
|
||||
context: dependency.context,
|
||||
context: AppContext.shared,
|
||||
item: mediaPreviewItem,
|
||||
transitionItem: mediaPreviewTransitionItem
|
||||
)
|
||||
_ = dependency.coordinator.present(
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .mediaPreview(viewModel: mediaPreviewViewModel),
|
||||
from: dependency,
|
||||
transition: .custom(transitioningDelegate: dependency.mediaPreviewTransitionController)
|
||||
@ -61,7 +63,7 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func coordinateToMediaPreviewScene(
|
||||
dependency: NeedsDependency & MediaPreviewableViewController,
|
||||
dependency: UIViewController & MediaPreviewableViewController,
|
||||
status: MastodonStatus,
|
||||
previewContext: AttachmentPreviewContext
|
||||
) async throws {
|
||||
@ -146,7 +148,7 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func coordinateToMediaPreviewScene(
|
||||
dependency: NeedsDependency & MediaPreviewableViewController,
|
||||
dependency: MediaPreviewableViewController,
|
||||
account: Mastodon.Entity.Account,
|
||||
previewContext: ImagePreviewContext
|
||||
) async throws {
|
||||
|
@ -53,8 +53,9 @@ extension DataSourceFacade {
|
||||
url: url
|
||||
)
|
||||
case .hashtag(_, let hashtag, _):
|
||||
let hashtagTimelineViewModel = await HashtagTimelineViewModel(context: provider.context, authenticationBox: provider.authenticationBox, hashtag: hashtag)
|
||||
_ = await provider.coordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: provider, transition: .show)
|
||||
let hashtagTimelineViewModel = await HashtagTimelineViewModel(authenticationBox: provider.authenticationBox, hashtag: hashtag)
|
||||
guard let coordinator = await provider.sceneCoordinator else { return }
|
||||
_ = await coordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: provider, transition: .show)
|
||||
case .mention(_, let mention, let userInfo):
|
||||
await coordinateToProfileScene(
|
||||
provider: provider,
|
||||
|
@ -11,7 +11,7 @@ import MastodonCore
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToUserMuteAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
dependency: AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async throws -> Mastodon.Entity.Relationship {
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
@ -3,19 +3,21 @@
|
||||
import Foundation
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
import UIKit
|
||||
|
||||
extension DataSourceFacade {
|
||||
@MainActor
|
||||
static func coordinateToNotificationRequests(
|
||||
provider: DataSourceProvider & AuthContextProvider
|
||||
) async {
|
||||
provider.coordinator.showLoading()
|
||||
guard let sceneCoordinator = provider.sceneCoordinator else { return }
|
||||
sceneCoordinator.showLoading()
|
||||
|
||||
do {
|
||||
let notificationRequests = try await APIService.shared.notificationRequests(authenticationBox: provider.authenticationBox).value
|
||||
let viewModel = NotificationRequestsViewModel(appContext: provider.context, authenticationBox: provider.authenticationBox, coordinator: provider.coordinator, requests: notificationRequests)
|
||||
let viewModel = NotificationRequestsViewModel(authenticationBox: provider.authenticationBox, requests: notificationRequests)
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
sceneCoordinator.hideLoading()
|
||||
|
||||
let transition: SceneCoordinator.Transition
|
||||
|
||||
@ -25,25 +27,26 @@ extension DataSourceFacade {
|
||||
transition = .modal(animated: true)
|
||||
}
|
||||
|
||||
provider.coordinator.present(scene: .notificationRequests(viewModel: viewModel), transition: transition)
|
||||
sceneCoordinator.present(scene: .notificationRequests(viewModel: viewModel), transition: transition)
|
||||
} catch {
|
||||
//TODO: Error Handling
|
||||
provider.coordinator.hideLoading()
|
||||
sceneCoordinator.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
static func coordinateToNotificationRequest(
|
||||
request: Mastodon.Entity.NotificationRequest,
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider
|
||||
provider: UIViewController & AuthContextProvider
|
||||
) async -> AccountNotificationTimelineViewController? {
|
||||
provider.coordinator.showLoading()
|
||||
guard let sceneCoordinator = provider.sceneCoordinator else { return nil }
|
||||
sceneCoordinator.showLoading()
|
||||
|
||||
let notificationTimelineViewModel = NotificationTimelineViewModel(context: provider.context, authenticationBox: provider.authenticationBox, scope: .fromAccount(request.account))
|
||||
let notificationTimelineViewModel = NotificationTimelineViewModel(authenticationBox: provider.authenticationBox, scope: .fromAccount(request.account))
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
sceneCoordinator.hideLoading()
|
||||
|
||||
guard let viewController = provider.coordinator.present(scene: .accountNotificationTimeline(viewModel: notificationTimelineViewModel, request: request), transition: .show) as? AccountNotificationTimelineViewController else { return nil }
|
||||
guard let viewController = sceneCoordinator.present(scene: .accountNotificationTimeline(viewModel: notificationTimelineViewModel, request: request), transition: .show) as? AccountNotificationTimelineViewController else { return nil }
|
||||
|
||||
return viewController
|
||||
|
||||
|
@ -26,7 +26,9 @@ extension DataSourceFacade {
|
||||
acct = status.entity.account.acct
|
||||
}
|
||||
|
||||
provider.coordinator.showLoading()
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
|
||||
let _redirectRecord = try? await Mastodon.API.Account.lookupAccount(
|
||||
session: .shared,
|
||||
@ -35,7 +37,7 @@ extension DataSourceFacade {
|
||||
authorization: provider.authenticationBox.userAuthorization
|
||||
).singleOutput().value
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
|
||||
guard let redirectRecord = _redirectRecord else {
|
||||
assertionFailure()
|
||||
@ -50,11 +52,13 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func coordinateToProfileScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController & AuthContextProvider,
|
||||
username: String,
|
||||
domain: String
|
||||
) async {
|
||||
provider.coordinator.showLoading()
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
|
||||
do {
|
||||
guard let account = try await APIService.shared.fetchUser(
|
||||
@ -62,24 +66,26 @@ extension DataSourceFacade {
|
||||
domain: domain,
|
||||
authenticationBox: provider.authenticationBox
|
||||
) else {
|
||||
return provider.coordinator.hideLoading()
|
||||
return coordinator.hideLoading()
|
||||
}
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
|
||||
await coordinateToProfileScene(provider: provider, account: account)
|
||||
} catch {
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
static func coordinateToProfileScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController & AuthContextProvider,
|
||||
domain: String,
|
||||
accountID: String
|
||||
) async {
|
||||
provider.coordinator.showLoading()
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
|
||||
do {
|
||||
let account = try await APIService.shared.accountInfo(
|
||||
@ -89,37 +95,40 @@ extension DataSourceFacade {
|
||||
authorization: provider.authenticationBox.userAuthorization
|
||||
)
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
|
||||
await coordinateToProfileScene(provider: provider, account: account)
|
||||
} catch {
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public static func coordinateToProfileScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController & AuthContextProvider,
|
||||
account: Mastodon.Entity.Account
|
||||
) async {
|
||||
provider.coordinator.showLoading()
|
||||
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
|
||||
guard let me = provider.authenticationBox.cachedAccount,
|
||||
let relationship = try? await APIService.shared.relationship(forAccounts: [account], authenticationBox: provider.authenticationBox).value.first else {
|
||||
return provider.coordinator.hideLoading()
|
||||
return coordinator.hideLoading()
|
||||
}
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
coordinator.hideLoading()
|
||||
|
||||
let profileViewModel = ProfileViewModel(
|
||||
context: provider.context,
|
||||
context: AppContext.shared,
|
||||
authenticationBox: provider.authenticationBox,
|
||||
account: account,
|
||||
relationship: relationship,
|
||||
me: me
|
||||
)
|
||||
|
||||
_ = provider.coordinator.present(
|
||||
_ = coordinator.present(
|
||||
scene: .profile(viewModel: profileViewModel),
|
||||
from: provider,
|
||||
transition: .show
|
||||
@ -146,13 +155,13 @@ extension DataSourceFacade {
|
||||
}
|
||||
let mentions = status.entity.mentions
|
||||
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
guard let mention = mentions.first(where: { $0.url == href }) else {
|
||||
_ = provider.coordinator.present(
|
||||
_ = coordinator.present(
|
||||
scene: .safari(url: url),
|
||||
from: provider,
|
||||
transition: .safariPresent(animated: true, completion: nil)
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,21 +172,21 @@ extension DataSourceFacade {
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func createActivityViewController(
|
||||
dependency: NeedsDependency,
|
||||
dependency: UIViewController,
|
||||
account: Mastodon.Entity.Account
|
||||
) -> UIActivityViewController {
|
||||
|
||||
let activityViewController = UIActivityViewController(
|
||||
activityItems: [account.url],
|
||||
applicationActivities: [SafariActivity(sceneCoordinator: dependency.coordinator)]
|
||||
applicationActivities: [SafariActivity(sceneCoordinator: dependency.sceneCoordinator)]
|
||||
)
|
||||
return activityViewController
|
||||
}
|
||||
|
||||
static func createActivityViewControllerForMastodonUser(status: Status, dependency: NeedsDependency) -> UIActivityViewController {
|
||||
static func createActivityViewControllerForMastodonUser(status: Status, dependency: UIViewController) -> UIActivityViewController {
|
||||
let activityViewController = UIActivityViewController(
|
||||
activityItems: status.activityItems,
|
||||
applicationActivities: [SafariActivity(sceneCoordinator: dependency.coordinator)]
|
||||
applicationActivities: [SafariActivity(sceneCoordinator: dependency.sceneCoordinator)]
|
||||
)
|
||||
return activityViewController
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import UIKit
|
||||
extension DataSourceFacade {
|
||||
|
||||
static func responseToCreateSearchHistory(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController & AuthContextProvider,
|
||||
item: DataSourceItem
|
||||
) async {
|
||||
switch item {
|
||||
|
@ -8,7 +8,7 @@ import CoreDataStack
|
||||
extension DataSourceFacade {
|
||||
public static func getEditHistory(
|
||||
forStatus status: Status,
|
||||
provider: NeedsDependency & AuthContextProvider
|
||||
provider: AuthContextProvider
|
||||
) async throws -> [Mastodon.Entity.StatusEdit] {
|
||||
let reponse = try await APIService.shared.getHistory(forStatusID: status.id, authenticationBox: provider.authenticationBox)
|
||||
|
||||
|
@ -20,7 +20,7 @@ import MastodonSDK
|
||||
extension DataSourceFacade {
|
||||
|
||||
static func responseToDeleteStatus(
|
||||
dependency: NeedsDependency & AuthContextProvider & DataSourceProvider,
|
||||
dependency: AuthContextProvider & DataSourceProvider,
|
||||
status: MastodonStatus
|
||||
) async throws {
|
||||
let deletedStatus = try await APIService.shared.deleteStatus(
|
||||
@ -46,7 +46,8 @@ extension DataSourceFacade {
|
||||
dependency: provider,
|
||||
status: status
|
||||
)
|
||||
_ = provider.coordinator.present(
|
||||
guard let coordinator = provider.sceneCoordinator else { /* TODO: throw? */ return }
|
||||
_ = coordinator.present(
|
||||
scene: .activityViewController(
|
||||
activityViewController: activityViewController,
|
||||
sourceView: button,
|
||||
@ -58,7 +59,7 @@ extension DataSourceFacade {
|
||||
}
|
||||
|
||||
private static func createActivityViewController(
|
||||
dependency: NeedsDependency,
|
||||
dependency: UIViewController,
|
||||
status: MastodonStatus
|
||||
) async throws -> UIActivityViewController {
|
||||
var activityItems: [Any] = {
|
||||
@ -68,8 +69,8 @@ extension DataSourceFacade {
|
||||
]
|
||||
}()
|
||||
|
||||
var applicationActivities: [UIActivity] = [
|
||||
SafariActivity(sceneCoordinator: dependency.coordinator), // open URL
|
||||
var applicationActivities: [UIActivity] = await [
|
||||
SafariActivity(sceneCoordinator: dependency.sceneCoordinator), // open URL
|
||||
]
|
||||
|
||||
if let provider = dependency as? ShareActivityProvider {
|
||||
@ -95,18 +96,19 @@ extension DataSourceFacade {
|
||||
sender: UIButton
|
||||
) async throws {
|
||||
let _status = status.reblog ?? status
|
||||
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
|
||||
switch action {
|
||||
case .reply:
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: provider.context,
|
||||
authenticationBox: provider.authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .reply(parent: _status)
|
||||
)
|
||||
_ = provider.coordinator.present(
|
||||
_ = coordinator.present(
|
||||
scene: .compose(viewModel: composeViewModel),
|
||||
from: provider,
|
||||
transition: .modal(animated: true, completion: nil)
|
||||
@ -144,7 +146,7 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func responseToMenuAction<T>(
|
||||
dependency: UIViewController & NeedsDependency & AuthContextProvider & DataSourceProvider,
|
||||
dependency: AuthContextProvider & DataSourceProvider,
|
||||
action: MastodonMenu.Action,
|
||||
menuContext: MenuContext,
|
||||
completion: ((T) -> Void)? = { (param: Void) in }
|
||||
@ -237,7 +239,7 @@ extension DataSourceFacade {
|
||||
guard let relationship = try? await APIService.shared.relationship(forAccounts: [menuContext.author], authenticationBox: dependency.authenticationBox).value.first else { return }
|
||||
|
||||
let reportViewModel = ReportViewModel(
|
||||
context: dependency.context,
|
||||
context: AppContext.shared,
|
||||
authenticationBox: dependency.authenticationBox,
|
||||
account: menuContext.author,
|
||||
relationship: relationship,
|
||||
@ -245,7 +247,8 @@ extension DataSourceFacade {
|
||||
contentDisplayMode: .neverConceal
|
||||
)
|
||||
|
||||
_ = dependency.coordinator.present(
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .report(viewModel: reportViewModel),
|
||||
from: dependency,
|
||||
transition: .modal(animated: true, completion: nil)
|
||||
@ -256,7 +259,8 @@ extension DataSourceFacade {
|
||||
account: menuContext.author
|
||||
)
|
||||
|
||||
_ = dependency.coordinator.present(
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .activityViewController(
|
||||
activityViewController: activityViewController,
|
||||
sourceView: menuContext.button,
|
||||
@ -284,8 +288,8 @@ extension DataSourceFacade {
|
||||
dependency: dependency,
|
||||
status: status
|
||||
)
|
||||
|
||||
_ = dependency.coordinator.present(
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .activityViewController(
|
||||
activityViewController: activityViewController,
|
||||
sourceView: menuContext.button,
|
||||
@ -321,7 +325,7 @@ extension DataSourceFacade {
|
||||
guard let status = menuContext.statusViewModel?.originalStatus?.reblog ?? menuContext.statusViewModel?.originalStatus else { return }
|
||||
|
||||
do {
|
||||
let translation = try await DataSourceFacade.translateStatus(provider: dependency,status: status)
|
||||
let translation = try await DataSourceFacade.translateStatus(provider: dependency, status: status)
|
||||
|
||||
menuContext.statusViewModel?.translation = translation
|
||||
} catch TranslationFailure.emptyOrInvalidResponse {
|
||||
@ -340,11 +344,11 @@ extension DataSourceFacade {
|
||||
).value
|
||||
|
||||
let editStatusViewModel = ComposeViewModel(
|
||||
context: dependency.coordinator.appContext,
|
||||
authenticationBox: dependency.authenticationBox,
|
||||
composeContext: .editStatus(status: status, statusSource: statusSource),
|
||||
destination: .topLevel)
|
||||
_ = dependency.coordinator.present(scene: .editStatus(viewModel: editStatusViewModel), transition: .modal(animated: true))
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
_ = coordinator.present(scene: .editStatus(viewModel: editStatusViewModel), transition: .modal(animated: true))
|
||||
|
||||
case .showOriginal:
|
||||
// do nothing, as the translation is reverted in `StatusTableViewCellDelegate` in `DataSourceProvider+StatusTableViewCellDelegate.swift`.
|
||||
@ -416,14 +420,13 @@ extension DataSourceFacade {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
|
||||
dependency.coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true))
|
||||
guard let coordinator = dependency.sceneCoordinator else { return }
|
||||
coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true))
|
||||
case .copyProfileLink(let url):
|
||||
UIPasteboard.general.string = url?.absoluteString
|
||||
case .openUserInBrowser(let url):
|
||||
guard let url else { return }
|
||||
|
||||
dependency.coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true))
|
||||
guard let url, let coordinator = dependency.sceneCoordinator else { return }
|
||||
coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -431,7 +434,7 @@ extension DataSourceFacade {
|
||||
extension DataSourceFacade {
|
||||
@MainActor
|
||||
static func responseToToggleSensitiveAction(
|
||||
dependency: NeedsDependency & DataSourceProvider,
|
||||
dependency: DataSourceProvider,
|
||||
status: MastodonStatus
|
||||
) async throws {
|
||||
let _status = status.reblog ?? status
|
||||
@ -443,7 +446,7 @@ extension DataSourceFacade {
|
||||
}
|
||||
|
||||
private extension DataSourceFacade {
|
||||
static func performDeletion(of status: MastodonStatus, with dependency: NeedsDependency & AuthContextProvider & DataSourceProvider) {
|
||||
static func performDeletion(of status: MastodonStatus, with dependency: AuthContextProvider & DataSourceProvider) {
|
||||
Task {
|
||||
try await DataSourceFacade.responseToDeleteStatus(
|
||||
dependency: dependency,
|
||||
|
@ -13,7 +13,7 @@ import MastodonSDK
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func coordinateToStatusThreadScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController,
|
||||
target: StatusTarget,
|
||||
status: MastodonStatus
|
||||
) async {
|
||||
@ -39,15 +39,16 @@ extension DataSourceFacade {
|
||||
|
||||
@MainActor
|
||||
static func coordinateToStatusThreadScene(
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider,
|
||||
provider: UIViewController,
|
||||
root: StatusItem.Thread
|
||||
) async {
|
||||
guard let authBox = AuthenticationServiceProvider.shared.currentActiveUser.value else { return }
|
||||
let threadViewModel = ThreadViewModel(
|
||||
context: provider.context,
|
||||
authenticationBox: provider.authenticationBox,
|
||||
authenticationBox: authBox,
|
||||
optionalRoot: root
|
||||
)
|
||||
_ = provider.coordinator.present(
|
||||
guard let coordinator = provider.sceneCoordinator else { return }
|
||||
_ = coordinator.present(
|
||||
scene: .thread(viewModel: threadViewModel),
|
||||
from: provider,
|
||||
transition: .show
|
||||
|
@ -11,15 +11,13 @@ import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
typealias Provider = UIViewController & NeedsDependency & AuthContextProvider
|
||||
|
||||
extension DataSourceFacade {
|
||||
enum TranslationFailure: Error {
|
||||
case emptyOrInvalidResponse
|
||||
}
|
||||
|
||||
public static func translateStatus(
|
||||
provider: Provider,
|
||||
provider: AuthContextProvider,
|
||||
status: MastodonStatus
|
||||
) async throws -> Mastodon.Entity.Translation {
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
@ -16,6 +16,7 @@ extension DataSourceFacade {
|
||||
provider: DataSourceProvider & AuthContextProvider,
|
||||
url: URL
|
||||
) async {
|
||||
guard let coordinator = await provider.sceneCoordinator else { return }
|
||||
let domain = provider.authenticationBox.domain
|
||||
if url.host == domain,
|
||||
url.pathComponents.count >= 4,
|
||||
@ -23,10 +24,10 @@ extension DataSourceFacade {
|
||||
url.pathComponents[1] == "web",
|
||||
url.pathComponents[2] == "statuses" {
|
||||
let statusID = url.pathComponents[3]
|
||||
let threadViewModel = await RemoteThreadViewModel(context: provider.context, authenticationBox: provider.authenticationBox, statusID: statusID)
|
||||
_ = await provider.coordinator.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show)
|
||||
let threadViewModel = await RemoteThreadViewModel(authenticationBox: provider.authenticationBox, statusID: statusID)
|
||||
_ = await coordinator.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show)
|
||||
} else {
|
||||
_ = await provider.coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
_ = await coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,11 @@ import MastodonUI
|
||||
import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
import UIKit
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToUserViewButtonAction(
|
||||
dependency: ViewControllerWithDependencies & AuthContextProvider,
|
||||
dependency: UIViewController & AuthContextProvider,
|
||||
account: Mastodon.Entity.Account,
|
||||
buttonState: UserView.ButtonState
|
||||
) async throws {
|
||||
|
@ -184,7 +184,7 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
],
|
||||
applicationActivities: []
|
||||
)
|
||||
self.coordinator.present(
|
||||
self.sceneCoordinator?.present(
|
||||
scene: .activityViewController(
|
||||
activityViewController: activityViewController,
|
||||
sourceView: statusCardControl, barButtonItem: nil
|
||||
@ -200,9 +200,8 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
image: UIImage(systemName: "square.and.pencil")
|
||||
) {
|
||||
DispatchQueue.main.async {
|
||||
self.coordinator.present(
|
||||
self.sceneCoordinator?.present(
|
||||
scene: .compose(viewModel: ComposeViewModel(
|
||||
context: self.context,
|
||||
authenticationBox: self.authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .topLevel,
|
||||
@ -534,12 +533,12 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
assertionFailure("only works for status data provider")
|
||||
return
|
||||
}
|
||||
let userListViewModel = UserListViewModel(
|
||||
context: context,
|
||||
let userListViewModel = await UserListViewModel(
|
||||
context: AppContext.shared,
|
||||
authenticationBox: authenticationBox,
|
||||
kind: .rebloggedBy(status: status)
|
||||
)
|
||||
_ = await coordinator.present(
|
||||
_ = await self.sceneCoordinator?.present(
|
||||
scene: .rebloggedBy(viewModel: userListViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -558,12 +557,12 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
assertionFailure("only works for status data provider")
|
||||
return
|
||||
}
|
||||
let userListViewModel = UserListViewModel(
|
||||
context: context,
|
||||
let userListViewModel = await UserListViewModel(
|
||||
context: AppContext.shared,
|
||||
authenticationBox: authenticationBox,
|
||||
kind: .favoritedBy(status: status)
|
||||
)
|
||||
_ = await coordinator.present(
|
||||
_ = await self.sceneCoordinator?.present(
|
||||
scene: .favoritedBy(viewModel: userListViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -574,7 +573,7 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
func tableViewCell(_ cell: UITableViewCell, statusView: StatusView, statusMetricView: StatusMetricView, showEditHistory button: UIButton) {
|
||||
Task {
|
||||
|
||||
await coordinator.showLoading()
|
||||
await self.sceneCoordinator?.showLoading()
|
||||
|
||||
let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil)
|
||||
guard let item = await self.item(from: source),
|
||||
@ -586,12 +585,12 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider & AuthConte
|
||||
do {
|
||||
let edits = try await APIService.shared.getHistory(forStatusID: status.id, authenticationBox: authenticationBox).value
|
||||
|
||||
await coordinator.hideLoading()
|
||||
await self.sceneCoordinator?.hideLoading()
|
||||
|
||||
let viewModel = StatusEditHistoryViewModel(status: status, edits: edits, appContext: context, authenticationBox: authenticationBox)
|
||||
_ = await coordinator.present(scene: .editHistory(viewModel: viewModel), from: self, transition: .show)
|
||||
let viewModel = await StatusEditHistoryViewModel(status: status, edits: edits, appContext: AppContext.shared, authenticationBox: authenticationBox)
|
||||
_ = await self.sceneCoordinator?.present(scene: .editHistory(viewModel: viewModel), from: self, transition: .show)
|
||||
} catch {
|
||||
await coordinator.hideLoading()
|
||||
await self.sceneCoordinator?.hideLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,12 +88,11 @@ extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvid
|
||||
FeedbackGenerator.shared.generate(.selectionChanged)
|
||||
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: self.context,
|
||||
authenticationBox: authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .reply(parent: status)
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .compose(viewModel: composeViewModel),
|
||||
from: self,
|
||||
transition: .modal(animated: true, completion: nil)
|
||||
|
@ -45,12 +45,11 @@ extension UITableViewDelegate where Self: DataSourceProvider & AuthContextProvid
|
||||
)
|
||||
} else if let accountWarning = notification.entity.accountWarning {
|
||||
let url = Mastodon.API.disputesEndpoint(domain: authenticationBox.domain, strikeId: accountWarning.id)
|
||||
_ = coordinator.present(
|
||||
self.sceneCoordinator?.present(
|
||||
scene: .safari(url: url),
|
||||
from: self,
|
||||
transition: .safariPresent(animated: true, completion: nil)
|
||||
)
|
||||
|
||||
} else {
|
||||
await DataSourceFacade.coordinateToProfileScene(
|
||||
provider: self,
|
||||
@ -135,7 +134,7 @@ extension UITableViewDelegate where Self: DataSourceProvider & MediaPreviewableV
|
||||
title: L10n.Common.Alerts.SavePhotoFailure.title,
|
||||
message: L10n.Common.Alerts.SavePhotoFailure.message
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: self,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
@ -166,10 +165,10 @@ extension UITableViewDelegate where Self: DataSourceProvider & MediaPreviewableV
|
||||
attributes: [],
|
||||
state: .off
|
||||
) { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
guard let self = self, let coordinator = self.sceneCoordinator else { return }
|
||||
Task {
|
||||
let applicationActivities: [UIActivity] = [
|
||||
SafariActivity(sceneCoordinator: self.coordinator)
|
||||
SafariActivity(sceneCoordinator: coordinator)
|
||||
]
|
||||
let activityViewController = UIActivityViewController(
|
||||
activityItems: [assetURL],
|
||||
|
@ -36,7 +36,7 @@ extension DataSourceItem {
|
||||
}
|
||||
}
|
||||
|
||||
protocol DataSourceProvider: ViewControllerWithDependencies {
|
||||
protocol DataSourceProvider: UIViewController {
|
||||
func item(from source: DataSourceItem.Source) async -> DataSourceItem?
|
||||
func update(status: MastodonStatus, intent: MastodonStatus.UpdateIntent)
|
||||
|
||||
|
@ -20,7 +20,6 @@ final class AccountListViewModel: NSObject {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
// output
|
||||
@ -28,8 +27,7 @@ final class AccountListViewModel: NSObject {
|
||||
|
||||
var diffableDataSource: UITableViewDiffableDataSource<Section, Item>!
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
|
||||
super.init()
|
||||
|
@ -12,10 +12,7 @@ import MastodonAsset
|
||||
import MastodonLocalization
|
||||
import MastodonCore
|
||||
|
||||
final class AccountListViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class AccountListViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: AccountListViewModel!
|
||||
@ -83,7 +80,7 @@ extension AccountListViewController {
|
||||
extension AccountListViewController {
|
||||
|
||||
@objc private func addBarButtonItem(_ sender: UIBarButtonItem) {
|
||||
_ = coordinator.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
||||
override func accessibilityPerformEscape() -> Bool {
|
||||
@ -115,7 +112,7 @@ extension AccountListViewController: UITableViewDelegate {
|
||||
FileManager.default.invalidateHomeTimelineCache(for: userIdentifier)
|
||||
FileManager.default.invalidateNotificationsAll(for: userIdentifier)
|
||||
FileManager.default.invalidateNotificationsMentions(for: userIdentifier)
|
||||
self.coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
|
||||
} catch {
|
||||
assertionFailure("Failed to delete Authentication: \(error)")
|
||||
@ -146,23 +143,23 @@ extension AccountListViewController: UITableViewDelegate {
|
||||
Task { @MainActor in
|
||||
let isActive = AuthenticationServiceProvider.shared.activateExistingUser(record.userID, inDomain: record.domain)
|
||||
guard isActive else { return }
|
||||
self.coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
} // end Task
|
||||
case .addAccount:
|
||||
// TODO: add dismiss entry for welcome scene
|
||||
_ = coordinator.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil))
|
||||
case .logoutOfAllAccounts:
|
||||
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
|
||||
let logoutAction = UIAlertAction(title: L10n.Scene.AccountList.logoutAllAccounts, style: .destructive) { _ in
|
||||
Task { @MainActor in
|
||||
self.coordinator.showLoading()
|
||||
self.sceneCoordinator?.showLoading()
|
||||
for authenticationBox in AuthenticationServiceProvider.shared.mastodonAuthenticationBoxes {
|
||||
try? await AuthenticationServiceProvider.shared.signOutMastodonUser(authentication: authenticationBox.authentication)
|
||||
}
|
||||
self.coordinator.hideLoading()
|
||||
self.sceneCoordinator?.hideLoading()
|
||||
|
||||
self.coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,8 @@ import MastodonUI
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
|
||||
final class ComposeViewController: UIViewController, NeedsDependency {
|
||||
final class ComposeViewController: UIViewController {
|
||||
static let minAutoCompleteVisibleHeight: CGFloat = 100
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: ComposeViewModel
|
||||
@ -48,7 +45,6 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
||||
}
|
||||
|
||||
return ComposeContentViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
composeContext: composeContext,
|
||||
destination: viewModel.destination,
|
||||
@ -217,7 +213,7 @@ extension ComposeViewController {
|
||||
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
_ = coordinator.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@ -235,7 +231,7 @@ extension ComposeViewController {
|
||||
self?.enqueuePublishStatus()
|
||||
}
|
||||
alertController.addAction(confirmAction)
|
||||
_ = coordinator.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@ -266,7 +262,7 @@ extension ComposeViewController {
|
||||
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
_ = coordinator.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@ -284,7 +280,7 @@ extension ComposeViewController {
|
||||
self?.enqueuePublishStatusEdit()
|
||||
}
|
||||
alertController.addAction(confirmAction)
|
||||
_ = coordinator.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), from: nil, transition: .alertController(animated: true, completion: nil))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ final class ComposeViewModel {
|
||||
let id = UUID()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let composeContext: Context
|
||||
let destination: ComposeContentViewModel.Destination
|
||||
@ -43,13 +42,11 @@ final class ComposeViewModel {
|
||||
@Published var title: String
|
||||
|
||||
init(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
composeContext: ComposeViewModel.Context,
|
||||
destination: ComposeContentViewModel.Destination,
|
||||
initialContent: String = ""
|
||||
) {
|
||||
self.context = context
|
||||
self.authenticationBox = authenticationBox
|
||||
self.destination = destination
|
||||
self.initialContent = initialContent
|
||||
|
@ -37,7 +37,6 @@ extension DiscoverySection {
|
||||
|
||||
static func diffableDataSource(
|
||||
tableView: UITableView,
|
||||
context: AppContext,
|
||||
configuration: Configuration
|
||||
) -> UITableViewDiffableDataSource<DiscoverySection, DiscoveryItem> {
|
||||
|
||||
|
@ -12,15 +12,12 @@ import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonUI
|
||||
|
||||
public class DiscoveryViewController: PageboyViewController, NeedsDependency {
|
||||
public class DiscoveryViewController: PageboyViewController {
|
||||
|
||||
public static let containerViewMarginForRegularHorizontalSizeClass: CGFloat = 64
|
||||
public static let containerViewMarginForCompactHorizontalSizeClass: CGFloat = 16
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var viewModel: DiscoveryViewModel!
|
||||
|
||||
|
@ -16,7 +16,6 @@ final class DiscoveryViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let discoveryPostsViewController: DiscoveryPostsViewController
|
||||
let discoveryHashtagsViewController: DiscoveryHashtagsViewController
|
||||
@ -26,37 +25,27 @@ final class DiscoveryViewModel {
|
||||
@Published var viewControllers: [ScrollViewContainer]
|
||||
|
||||
@MainActor
|
||||
init(context: AppContext, coordinator: SceneCoordinator, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
|
||||
func setupDependency(_ needsDependency: NeedsDependency) {
|
||||
needsDependency.context = context
|
||||
needsDependency.coordinator = coordinator
|
||||
}
|
||||
|
||||
discoveryPostsViewController = {
|
||||
let viewController = DiscoveryPostsViewController()
|
||||
setupDependency(viewController)
|
||||
viewController.viewModel = DiscoveryPostsViewModel(context: context, authenticationBox: authenticationBox)
|
||||
viewController.viewModel = DiscoveryPostsViewModel(authenticationBox: authenticationBox)
|
||||
return viewController
|
||||
}()
|
||||
discoveryHashtagsViewController = {
|
||||
let viewController = DiscoveryHashtagsViewController()
|
||||
setupDependency(viewController)
|
||||
viewController.viewModel = DiscoveryHashtagsViewModel(context: context, authenticationBox: authenticationBox)
|
||||
viewController.viewModel = DiscoveryHashtagsViewModel(authenticationBox: authenticationBox)
|
||||
return viewController
|
||||
}()
|
||||
discoveryNewsViewController = {
|
||||
let viewController = DiscoveryNewsViewController()
|
||||
setupDependency(viewController)
|
||||
viewController.viewModel = DiscoveryNewsViewModel(context: context, authenticationBox: authenticationBox)
|
||||
viewController.viewModel = DiscoveryNewsViewModel(authenticationBox: authenticationBox)
|
||||
return viewController
|
||||
}()
|
||||
discoveryForYouViewController = {
|
||||
let viewController = DiscoveryForYouViewController()
|
||||
setupDependency(viewController)
|
||||
viewController.viewModel = DiscoveryForYouViewModel(context: context, authenticationBox: authenticationBox)
|
||||
viewController.viewModel = DiscoveryForYouViewModel(authenticationBox: authenticationBox)
|
||||
return viewController
|
||||
}()
|
||||
self.viewControllers = [
|
||||
|
@ -11,10 +11,7 @@ import MastodonUI
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
final class DiscoveryForYouViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class DiscoveryForYouViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: DiscoveryForYouViewModel!
|
||||
@ -137,7 +134,7 @@ extension DiscoveryForYouViewController: ProfileCardTableViewCellDelegate {
|
||||
guard let indexPath = tableView.indexPath(for: cell) else { return }
|
||||
guard case let .account(account, _) = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
self.sceneCoordinator?.showLoading()
|
||||
|
||||
Task { [weak self] in
|
||||
|
||||
@ -147,16 +144,15 @@ extension DiscoveryForYouViewController: ProfileCardTableViewCellDelegate {
|
||||
let familiarFollowers = viewModel.familiarFollowers.first(where: { $0.id == userID })?.accounts ?? []
|
||||
let relationships = try await APIService.shared.relationship(forAccounts: familiarFollowers, authenticationBox: authenticationBox).value
|
||||
|
||||
coordinator.hideLoading()
|
||||
self.sceneCoordinator?.hideLoading()
|
||||
|
||||
let familiarFollowersViewModel = FamiliarFollowersViewModel(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
accounts: familiarFollowers,
|
||||
relationships: relationships
|
||||
)
|
||||
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .familiarFollowers(viewModel: familiarFollowersViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
|
@ -17,7 +17,6 @@ extension DiscoveryForYouViewModel {
|
||||
) {
|
||||
diffableDataSource = DiscoverySection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: DiscoverySection.Configuration(
|
||||
authenticationBox: authenticationBox,
|
||||
profileCardTableViewCellDelegate: profileCardTableViewCellDelegate,
|
||||
|
@ -16,7 +16,6 @@ final class DiscoveryForYouViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
@MainActor
|
||||
@ -29,8 +28,7 @@ final class DiscoveryForYouViewModel {
|
||||
var diffableDataSource: UITableViewDiffableDataSource<DiscoverySection, DiscoveryItem>?
|
||||
let didLoadLatest = PassthroughSubject<Void, Never>()
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.accounts = []
|
||||
self.relationships = []
|
||||
|
@ -10,10 +10,7 @@ import Combine
|
||||
import MastodonCore
|
||||
import MastodonUI
|
||||
|
||||
final class DiscoveryHashtagsViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class DiscoveryHashtagsViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: DiscoveryHashtagsViewModel!
|
||||
@ -88,8 +85,8 @@ extension DiscoveryHashtagsViewController: UITableViewDelegate {
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
guard case let .hashtag(tag) = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(context: context, authenticationBox: viewModel.authenticationBox, hashtag: tag.name)
|
||||
_ = coordinator.present(
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(authenticationBox: viewModel.authenticationBox, hashtag: tag.name)
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -198,8 +195,8 @@ extension DiscoveryHashtagsViewController: TableViewControllerNavigateable {
|
||||
guard let item = diffableDataSource.itemIdentifier(for: indexPathForSelectedRow) else { return }
|
||||
|
||||
guard case let .hashtag(tag) = item else { return }
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(context: context, authenticationBox: viewModel.authenticationBox, hashtag: tag.name)
|
||||
_ = coordinator.present(
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(authenticationBox: viewModel.authenticationBox, hashtag: tag.name)
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
|
@ -14,7 +14,6 @@ extension DiscoveryHashtagsViewModel {
|
||||
) {
|
||||
diffableDataSource = DiscoverySection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: DiscoverySection.Configuration(authenticationBox: authenticationBox)
|
||||
)
|
||||
|
||||
|
@ -18,7 +18,6 @@ final class DiscoveryHashtagsViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let viewDidAppeared = PassthroughSubject<Void, Never>()
|
||||
|
||||
@ -26,8 +25,7 @@ final class DiscoveryHashtagsViewModel {
|
||||
var diffableDataSource: UITableViewDiffableDataSource<DiscoverySection, DiscoveryItem>?
|
||||
@Published var hashtags: [Mastodon.Entity.Tag] = []
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
// end init
|
||||
|
||||
|
@ -10,10 +10,7 @@ import Combine
|
||||
import MastodonCore
|
||||
import MastodonUI
|
||||
|
||||
final class DiscoveryNewsViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class DiscoveryNewsViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: DiscoveryNewsViewModel!
|
||||
@ -85,7 +82,7 @@ extension DiscoveryNewsViewController: UITableViewDelegate {
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
guard case let .link(link) = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
|
||||
guard let url = URL(string: link.url) else { return }
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .safari(url: url),
|
||||
from: self,
|
||||
transition: .safariPresent(animated: true, completion: nil)
|
||||
@ -182,7 +179,7 @@ extension DiscoveryNewsViewController: TableViewControllerNavigateable {
|
||||
|
||||
guard case let .link(link) = item else { return }
|
||||
guard let url = URL(string: link.url) else { return }
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .safari(url: url),
|
||||
from: self,
|
||||
transition: .safariPresent(animated: true, completion: nil)
|
||||
|
@ -15,7 +15,6 @@ extension DiscoveryNewsViewModel {
|
||||
) {
|
||||
diffableDataSource = DiscoverySection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: DiscoverySection.Configuration(authenticationBox: authenticationBox)
|
||||
)
|
||||
|
||||
|
@ -18,7 +18,6 @@ final class DiscoveryNewsViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
// output
|
||||
@ -40,8 +39,7 @@ final class DiscoveryNewsViewModel {
|
||||
let didLoadLatest = PassthroughSubject<Void, Never>()
|
||||
@Published var isServerSupportEndpoint = true
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
// end init
|
||||
|
||||
|
@ -10,9 +10,7 @@ import Combine
|
||||
import MastodonCore
|
||||
import MastodonUI
|
||||
|
||||
final class DiscoveryPostsViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class DiscoveryPostsViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: DiscoveryPostsViewModel!
|
||||
|
@ -16,9 +16,7 @@ extension DiscoveryPostsViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: nil,
|
||||
|
@ -18,7 +18,6 @@ final class DiscoveryPostsViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let dataController: StatusDataController
|
||||
|
||||
@ -41,8 +40,7 @@ final class DiscoveryPostsViewModel {
|
||||
@Published var isServerSupportEndpoint = true
|
||||
|
||||
@MainActor
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.dataController = StatusDataController()
|
||||
|
||||
|
@ -10,17 +10,15 @@ import UIKit
|
||||
class NewDonationNavigationFlow: NavigationFlow {
|
||||
|
||||
private let campaign: DonationCampaignViewModel
|
||||
private let appContext: AppContext
|
||||
private let authenticationBox: MastodonAuthenticationBox
|
||||
private let sceneCoordinator: SceneCoordinator
|
||||
|
||||
init(
|
||||
flowPresenter: NavigationFlowPresenter,
|
||||
campaign: DonationCampaignViewModel, appContext: AppContext,
|
||||
campaign: DonationCampaignViewModel,
|
||||
authenticationBox: MastodonAuthenticationBox, sceneCoordinator: SceneCoordinator
|
||||
) {
|
||||
self.campaign = campaign
|
||||
self.appContext = appContext
|
||||
self.authenticationBox = authenticationBox
|
||||
self.sceneCoordinator = sceneCoordinator
|
||||
super.init(flowPresenter: flowPresenter)
|
||||
@ -106,7 +104,6 @@ class NewDonationNavigationFlow: NavigationFlow {
|
||||
|
||||
private func composeDonationSuccessPost(_ suggestedText: String) {
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: appContext,
|
||||
authenticationBox: authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .topLevel,
|
||||
|
@ -16,10 +16,7 @@ import MastodonUI
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
|
||||
final class HashtagTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class HashtagTimelineViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
let mediaPreviewTransitionController = MediaPreviewTransitionController()
|
||||
|
||||
@ -184,13 +181,12 @@ extension HashtagTimelineViewController {
|
||||
let hashtag = "#" + viewModel.hashtag
|
||||
UITextChecker.learnWord(hashtag)
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .topLevel,
|
||||
initialContent: hashtag
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,9 +17,7 @@ extension HashtagTimelineViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: nil,
|
||||
|
@ -22,7 +22,6 @@ final class HashtagTimelineViewModel {
|
||||
var needLoadMiddleIndex: Int? = nil
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let dataController: StatusDataController
|
||||
let isFetchingLatestTimeline = CurrentValueSubject<Bool, Never>(false)
|
||||
@ -50,8 +49,7 @@ final class HashtagTimelineViewModel {
|
||||
}()
|
||||
|
||||
@MainActor
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox, hashtag: String) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox, hashtag: String) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.hashtag = hashtag
|
||||
self.dataController = StatusDataController()
|
||||
|
@ -19,10 +19,7 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class HomeTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class HomeTimelineViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: HomeTimelineViewModel?
|
||||
@ -616,9 +613,9 @@ extension HomeTimelineViewController {
|
||||
@objc private func findPeopleButtonPressed(_ sender: Any?) {
|
||||
guard let authenticationBox = viewModel?.authenticationBox else { return }
|
||||
|
||||
let suggestionAccountViewModel = SuggestionAccountViewModel(context: context, authenticationBox: authenticationBox)
|
||||
let suggestionAccountViewModel = SuggestionAccountViewModel(authenticationBox: authenticationBox)
|
||||
suggestionAccountViewModel.delegate = viewModel
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .suggestionAccount(viewModel: suggestionAccountViewModel),
|
||||
from: self,
|
||||
transition: .modal(animated: true, completion: nil)
|
||||
@ -626,13 +623,13 @@ extension HomeTimelineViewController {
|
||||
}
|
||||
|
||||
@objc private func manuallySearchButtonPressed(_ sender: UIButton) {
|
||||
coordinator.switchToTabBar(tab: .search)
|
||||
self.sceneCoordinator?.switchToTabBar(tab: .search)
|
||||
}
|
||||
|
||||
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
guard let setting = SettingService.shared.currentSetting.value else { return }
|
||||
|
||||
_ = coordinator.present(scene: .settings(setting: setting), from: self, transition: .none)
|
||||
_ = self.sceneCoordinator?.present(scene: .settings(setting: setting), from: self, transition: .none)
|
||||
}
|
||||
|
||||
@objc private func refreshControlValueChanged(_ sender: RefreshControl) {
|
||||
@ -650,7 +647,7 @@ extension HomeTimelineViewController {
|
||||
FileManager.default.invalidateHomeTimelineCache(for: userIdentifier)
|
||||
FileManager.default.invalidateNotificationsAll(for: userIdentifier)
|
||||
FileManager.default.invalidateNotificationsMentions(for: userIdentifier)
|
||||
self.coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
}
|
||||
}
|
||||
|
||||
@ -741,7 +738,8 @@ extension HomeTimelineViewController {
|
||||
|
||||
private func showDonationCampaign(_ campaign: Mastodon.Entity.DonationCampaign) {
|
||||
hideDonationCampaignBanner()
|
||||
navigationFlow = NewDonationNavigationFlow(flowPresenter: self, campaign: campaign, appContext: context, authenticationBox: authenticationBox, sceneCoordinator: coordinator)
|
||||
guard let coordinator = self.sceneCoordinator else { return }
|
||||
navigationFlow = NewDonationNavigationFlow(flowPresenter: self, campaign: campaign, authenticationBox: authenticationBox, sceneCoordinator: coordinator)
|
||||
navigationFlow?.presentFlow { [weak self] in
|
||||
self?.navigationFlow = nil
|
||||
}
|
||||
|
@ -20,9 +20,7 @@ extension HomeTimelineViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: timelineMiddleLoaderTableViewCellDelegate,
|
||||
|
@ -23,7 +23,6 @@ final class HomeTimelineViewModel: NSObject {
|
||||
var observations = Set<NSKeyValueObservation>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let dataController: FeedDataController
|
||||
|
||||
@ -91,10 +90,9 @@ final class HomeTimelineViewModel: NSObject {
|
||||
|
||||
var cellFrameCache = NSCache<NSNumber, NSValue>()
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.dataController = FeedDataController(context: context, authenticationBox: authenticationBox, kind: .home(timeline: timelineContext))
|
||||
self.dataController = FeedDataController(authenticationBox: authenticationBox, kind: .home(timeline: timelineContext))
|
||||
super.init()
|
||||
self.dataController.records = (try? PersistenceManager.shared.cachedTimeline(.homeTimeline(authenticationBox)).map {
|
||||
MastodonFeed.fromStatus($0, kind: .home)
|
||||
|
@ -13,10 +13,7 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class MediaPreviewViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class MediaPreviewViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: MediaPreviewViewModel!
|
||||
@ -285,7 +282,7 @@ extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate {
|
||||
title: L10n.Common.Alerts.SavePhotoFailure.title,
|
||||
message: L10n.Common.Alerts.SavePhotoFailure.message
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: self,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
@ -296,7 +293,7 @@ extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate {
|
||||
} receiveValue: { _ in
|
||||
// do nothing
|
||||
}
|
||||
.store(in: &context.disposeBag)
|
||||
.store(in: &AppContext.shared.disposeBag)
|
||||
case .copyPhoto:
|
||||
guard let assetURL = viewController.viewModel.item.assetURL else { return }
|
||||
|
||||
@ -311,10 +308,10 @@ extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate {
|
||||
} receiveValue: { _ in
|
||||
// do nothing
|
||||
}
|
||||
.store(in: &context.disposeBag)
|
||||
.store(in: &AppContext.shared.disposeBag)
|
||||
case .share:
|
||||
let applicationActivities: [UIActivity] = [
|
||||
SafariActivity(sceneCoordinator: self.coordinator)
|
||||
SafariActivity(sceneCoordinator: self.sceneCoordinator)
|
||||
]
|
||||
let activityViewController = UIActivityViewController(
|
||||
activityItems: {
|
||||
|
@ -15,10 +15,10 @@ class AccountNotificationTimelineViewController: NotificationTimelineViewControl
|
||||
let request: Mastodon.Entity.NotificationRequest
|
||||
weak var delegate: AccountNotificationTimelineViewControllerDelegate?
|
||||
|
||||
init(viewModel: NotificationTimelineViewModel, context: AppContext, coordinator: SceneCoordinator, notificationRequest: Mastodon.Entity.NotificationRequest) {
|
||||
init(viewModel: NotificationTimelineViewModel, notificationRequest: Mastodon.Entity.NotificationRequest) {
|
||||
self.request = notificationRequest
|
||||
|
||||
super.init(viewModel: viewModel, context: context, coordinator: coordinator)
|
||||
super.init(viewModel: viewModel)
|
||||
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis.circle"), target: nil, action: nil, menu: menu())
|
||||
}
|
||||
@ -32,18 +32,18 @@ class AccountNotificationTimelineViewController: NotificationTimelineViewControl
|
||||
UIAction(title: L10n.Scene.Notification.FilteredNotification.accept, image: UIImage(systemName: "checkmark")) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
self.sceneCoordinator?.showLoading()
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
self.delegate?.acceptRequest(self, request: request)
|
||||
coordinator.hideLoading()
|
||||
self.sceneCoordinator?.hideLoading()
|
||||
},
|
||||
UIAction(title: L10n.Scene.Notification.FilteredNotification.dismiss, image: NotificationRequestConstants.dismissIcon) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
self.sceneCoordinator?.showLoading()
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
self.delegate?.dismissRequest(self, request: request)
|
||||
coordinator.hideLoading()
|
||||
self.sceneCoordinator?.hideLoading()
|
||||
}
|
||||
])
|
||||
|
||||
|
@ -18,9 +18,8 @@ protocol NotificationRequestsTableViewControllerDelegate: AnyObject {
|
||||
func notificationRequestsUpdated(_ viewController: NotificationRequestsTableViewController)
|
||||
}
|
||||
|
||||
class NotificationRequestsTableViewController: UIViewController, NeedsDependency {
|
||||
var context: AppContext!
|
||||
var coordinator: SceneCoordinator!
|
||||
class NotificationRequestsTableViewController: UIViewController {
|
||||
|
||||
weak var delegate: NotificationRequestsTableViewControllerDelegate?
|
||||
|
||||
let tableView: UITableView
|
||||
@ -30,8 +29,6 @@ class NotificationRequestsTableViewController: UIViewController, NeedsDependency
|
||||
init(viewModel: NotificationRequestsViewModel) {
|
||||
|
||||
self.viewModel = viewModel
|
||||
self.context = viewModel.appContext
|
||||
self.coordinator = viewModel.coordinator
|
||||
|
||||
tableView = UITableView(frame: .zero)
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
@ -5,16 +5,12 @@ import MastodonSDK
|
||||
import MastodonCore
|
||||
|
||||
struct NotificationRequestsViewModel {
|
||||
let appContext: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let coordinator: SceneCoordinator
|
||||
|
||||
var requests: [Mastodon.Entity.NotificationRequest]
|
||||
|
||||
init(appContext: AppContext, authenticationBox: MastodonAuthenticationBox, coordinator: SceneCoordinator, requests: [Mastodon.Entity.NotificationRequest]) {
|
||||
self.appContext = appContext
|
||||
init(authenticationBox: MastodonAuthenticationBox, requests: [Mastodon.Entity.NotificationRequest]) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.coordinator = coordinator
|
||||
self.requests = requests
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ extension NotificationSection {
|
||||
|
||||
static func diffableDataSource(
|
||||
tableView: UITableView,
|
||||
context: AppContext,
|
||||
configuration: Configuration
|
||||
) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> {
|
||||
tableView.register(NotificationTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationTableViewCell.self))
|
||||
@ -50,7 +49,6 @@ extension NotificationSection {
|
||||
} else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationTableViewCell.self), for: indexPath) as! NotificationTableViewCell
|
||||
configure(
|
||||
context: context,
|
||||
tableView: tableView,
|
||||
cell: cell,
|
||||
viewModel: NotificationTableViewCell.ViewModel(value: .feed(feed)),
|
||||
@ -81,20 +79,17 @@ extension NotificationSection {
|
||||
extension NotificationSection {
|
||||
|
||||
static func configure(
|
||||
context: AppContext,
|
||||
tableView: UITableView,
|
||||
cell: NotificationTableViewCell,
|
||||
viewModel: NotificationTableViewCell.ViewModel,
|
||||
configuration: Configuration
|
||||
) {
|
||||
StatusSection.setupStatusPollDataSource(
|
||||
context: context,
|
||||
authenticationBox: configuration.authenticationBox,
|
||||
statusView: cell.notificationView.statusView
|
||||
)
|
||||
|
||||
StatusSection.setupStatusPollDataSource(
|
||||
context: context,
|
||||
authenticationBox: configuration.authenticationBox,
|
||||
statusView: cell.notificationView.quoteStatusView
|
||||
)
|
||||
|
@ -11,10 +11,7 @@ import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
|
||||
class NotificationTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator!
|
||||
class NotificationTimelineViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
let mediaPreviewTransitionController = MediaPreviewTransitionController()
|
||||
|
||||
@ -39,10 +36,8 @@ class NotificationTimelineViewController: UIViewController, NeedsDependency, Med
|
||||
|
||||
let cellFrameCache = NSCache<NSNumber, NSValue>()
|
||||
|
||||
init(viewModel: NotificationTimelineViewModel, context: AppContext, coordinator: SceneCoordinator) {
|
||||
init(viewModel: NotificationTimelineViewModel) {
|
||||
self.viewModel = viewModel
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
@ -288,11 +283,10 @@ extension NotificationTimelineViewController: TableViewControllerNavigateable {
|
||||
|
||||
if let status = notification.status {
|
||||
let threadViewModel = ThreadViewModel(
|
||||
context: self.context,
|
||||
authenticationBox: self.viewModel.authenticationBox,
|
||||
optionalRoot: .root(context: .init(status: .fromEntity(status)))
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .thread(viewModel: threadViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
|
@ -18,7 +18,6 @@ extension NotificationTimelineViewModel {
|
||||
) {
|
||||
diffableDataSource = NotificationSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: NotificationSection.Configuration(
|
||||
authenticationBox: authenticationBox,
|
||||
notificationTableViewCellDelegate: notificationTableViewCellDelegate,
|
||||
|
@ -19,7 +19,6 @@ final class NotificationTimelineViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let scope: Scope
|
||||
var notificationPolicy: Mastodon.Entity.NotificationPolicy?
|
||||
@ -47,15 +46,13 @@ final class NotificationTimelineViewModel {
|
||||
|
||||
@MainActor
|
||||
init(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
scope: Scope,
|
||||
notificationPolicy: Mastodon.Entity.NotificationPolicy? = nil
|
||||
) {
|
||||
self.context = context
|
||||
self.authenticationBox = authenticationBox
|
||||
self.scope = scope
|
||||
self.dataController = FeedDataController(context: context, authenticationBox: authenticationBox, kind: scope.feedKind)
|
||||
self.dataController = FeedDataController(authenticationBox: authenticationBox, kind: scope.feedKind)
|
||||
self.notificationPolicy = notificationPolicy
|
||||
|
||||
switch scope {
|
||||
|
@ -14,10 +14,7 @@ import Pageboy
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
final class NotificationViewController: TabmanViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class NotificationViewController: TabmanViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var observations = Set<NSKeyValueObservation>()
|
||||
@ -129,7 +126,7 @@ extension NotificationViewController {
|
||||
privateMentions: policy.filterPrivateMentions
|
||||
)
|
||||
|
||||
guard let policyViewController = coordinator.present(scene: .notificationPolicy(viewModel: policyViewModel), transition: .formSheet) as? NotificationPolicyViewController else { return }
|
||||
guard let policyViewController = self.sceneCoordinator?.present(scene: .notificationPolicy(viewModel: policyViewModel), transition: .formSheet) as? NotificationPolicyViewController else { return }
|
||||
|
||||
policyViewController.delegate = self
|
||||
}
|
||||
@ -156,12 +153,9 @@ extension NotificationViewController {
|
||||
|
||||
let viewController = NotificationTimelineViewController(
|
||||
viewModel: NotificationTimelineViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
scope: scope, notificationPolicy: viewModel.notificationPolicy
|
||||
),
|
||||
context: context,
|
||||
coordinator: coordinator
|
||||
)
|
||||
)
|
||||
|
||||
return viewController
|
||||
|
@ -13,13 +13,10 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class MastodonConfirmEmailViewController: UIViewController, NeedsDependency {
|
||||
final class MastodonConfirmEmailViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var viewModel: MastodonConfirmEmailViewModel!
|
||||
|
||||
let stackView = UIStackView()
|
||||
@ -126,10 +123,10 @@ extension MastodonConfirmEmailViewController {
|
||||
} receiveValue: { _ in
|
||||
// do nothing
|
||||
}
|
||||
.store(in: &self.context.disposeBag) // execute in the background
|
||||
.store(in: &AppContext.shared.disposeBag) // execute in the background
|
||||
} // end switch
|
||||
} receiveValue: { _ in
|
||||
self.coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
// self.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
.store(in: &self.disposeBag)
|
||||
@ -208,13 +205,13 @@ extension MastodonConfirmEmailViewController {
|
||||
let resendAction = UIAlertAction(title: L10n.Scene.ConfirmEmail.DontReceiveEmail.resendEmail, style: .default) { _ in
|
||||
let url = Mastodon.API.resendEmailURL(domain: self.viewModel.authenticateInfo.domain)
|
||||
let viewModel = MastodonResendEmailViewModel(resendEmailURL: url, email: self.viewModel.email)
|
||||
_ = self.coordinator.present(scene: .mastodonResendEmail(viewModel: viewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonResendEmail(viewModel: viewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default) { _ in
|
||||
}
|
||||
alertController.addAction(resendAction)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), from: self, transition: .alertController(animated: true, completion: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ enum CategoryPickerSection: Equatable, Hashable {
|
||||
extension CategoryPickerSection {
|
||||
static func collectionViewDiffableDataSource(
|
||||
for collectionView: UICollectionView,
|
||||
dependency: NeedsDependency,
|
||||
dependency: UIViewController,
|
||||
viewModel: MastodonPickServerViewModel
|
||||
) -> UICollectionViewDiffableDataSource<CategoryPickerSection, CategoryPickerItem> {
|
||||
UICollectionViewDiffableDataSource(collectionView: collectionView) { [weak dependency] collectionView, indexPath, item -> UICollectionViewCell? in
|
||||
|
@ -14,11 +14,7 @@ import MastodonLocalization
|
||||
import MastodonUI
|
||||
import MastodonSDK
|
||||
|
||||
final class MastodonPickServerViewController: UIViewController, NeedsDependency {
|
||||
var context: AppContext! {
|
||||
get { return AppContext.shared }
|
||||
set { }
|
||||
}
|
||||
final class MastodonPickServerViewController: UIViewController {
|
||||
|
||||
var coordinator: SceneCoordinator!
|
||||
|
||||
|
@ -13,7 +13,7 @@ extension MastodonPickServerViewModel {
|
||||
|
||||
func setupDiffableDataSource(
|
||||
for tableView: UITableView,
|
||||
dependency: NeedsDependency,
|
||||
dependency: UIViewController,
|
||||
pickServerServerSectionTableHeaderViewDelegate: PickServerServerSectionTableHeaderViewDelegate
|
||||
) {
|
||||
// set section header
|
||||
|
@ -18,7 +18,7 @@ enum PickServerSection: Equatable, Hashable {
|
||||
extension PickServerSection {
|
||||
static func tableViewDiffableDataSource(
|
||||
for tableView: UITableView,
|
||||
dependency: NeedsDependency
|
||||
dependency: UIViewController
|
||||
) -> UITableViewDiffableDataSource<PickServerSection, PickServerItem> {
|
||||
tableView.register(PickServerCell.self, forCellReuseIdentifier: String(describing: PickServerCell.self))
|
||||
tableView.register(PickServerLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerLoaderTableViewCell.self))
|
||||
|
@ -16,15 +16,12 @@ import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
|
||||
final class MastodonRegisterViewController: UIViewController, NeedsDependency, OnboardingViewControllerAppearance {
|
||||
final class MastodonRegisterViewController: UIViewController, OnboardingViewControllerAppearance {
|
||||
|
||||
static let avatarImageMaxSizeInPixel = CGSize(width: 400, height: 400)
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
private var observations = Set<NSKeyValueObservation>()
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var viewModel: MastodonRegisterViewModel!
|
||||
private(set) lazy var mastodonRegisterView = MastodonRegisterView(viewModel: viewModel)
|
||||
@ -92,7 +89,7 @@ extension MastodonRegisterViewController {
|
||||
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.SignUpFailure.title, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
|
@ -10,10 +10,7 @@ import UIKit
|
||||
import WebKit
|
||||
import MastodonCore
|
||||
|
||||
final class MastodonResendEmailViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class MastodonResendEmailViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: MastodonResendEmailViewModel!
|
||||
|
@ -12,7 +12,7 @@ import MastodonCore
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
|
||||
final class WelcomeViewController: UIViewController, NeedsDependency {
|
||||
final class WelcomeViewController: UIViewController {
|
||||
|
||||
private enum Constants {
|
||||
static let topAnchorInset: CGFloat = 20
|
||||
@ -28,16 +28,13 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
|
||||
}
|
||||
}
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
private let authenticationViewModel = AuthenticationViewModel()
|
||||
private var authenticationStateTask: Task<(), Never>?
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var observations = Set<NSKeyValueObservation>()
|
||||
private(set) lazy var viewModel = WelcomeViewModel(context: context)
|
||||
private(set) lazy var viewModel = WelcomeViewModel()
|
||||
|
||||
let welcomeIllustrationView = WelcomeIllustrationView()
|
||||
let separatorView = WelcomeSeparatorView(frame: .zero)
|
||||
@ -137,7 +134,7 @@ extension WelcomeViewController {
|
||||
let alertController = UIAlertController(for: error, title: "Error", preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
@ -151,25 +148,25 @@ extension WelcomeViewController {
|
||||
case .error(let error):
|
||||
displayError(error)
|
||||
case .logInToExistingAccountRequested:
|
||||
_ = coordinator.present(scene: .mastodonLogin(authenticationViewModel: authenticationViewModel, suggestedDomain: viewModel.randomDefaultServer?.domain), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonLogin(authenticationViewModel: authenticationViewModel, suggestedDomain: viewModel.randomDefaultServer?.domain), from: self, transition: .show)
|
||||
case .joiningServer:
|
||||
break
|
||||
case .showingRules(let viewModel):
|
||||
if let viewModel {
|
||||
_ = coordinator.present(scene: .mastodonServerRules(viewModel: viewModel), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonServerRules(viewModel: viewModel), from: self, transition: .show)
|
||||
} else {
|
||||
popBack()
|
||||
}
|
||||
case .registering(let viewModel):
|
||||
_ = coordinator.present(scene: .mastodonRegister(viewModel: viewModel), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonRegister(viewModel: viewModel), from: self, transition: .show)
|
||||
case .showingPrivacyPolicy(let viewModel):
|
||||
_ = coordinator.present(scene: .mastodonPrivacyPolicies(viewModel: viewModel), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonPrivacyPolicies(viewModel: viewModel), from: self, transition: .show)
|
||||
case .pickingServer:
|
||||
_ = coordinator.present(scene: .mastodonPickServer(viewMode: MastodonPickServerViewModel(joinServer: { [weak self] server in try await self?.authenticationViewModel.joinServer(server) }, displayError: { [weak self] error in self?.displayError(error) })), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonPickServer(viewMode: MastodonPickServerViewModel(joinServer: { [weak self] server in try await self?.authenticationViewModel.joinServer(server) }, displayError: { [weak self] error in self?.displayError(error) })), from: self, transition: .show)
|
||||
case .confirmingEmail(let viewModel):
|
||||
_ = coordinator.present(scene: .mastodonConfirmEmail(viewModel: viewModel), from: self, transition: .show)
|
||||
_ = self.sceneCoordinator?.present(scene: .mastodonConfirmEmail(viewModel: viewModel), from: self, transition: .show)
|
||||
case .authenticatedUser(let authBox):
|
||||
coordinator.setup()
|
||||
self.sceneCoordinator?.setup()
|
||||
break
|
||||
case .authenticatingUser:
|
||||
break
|
||||
|
@ -16,16 +16,11 @@ final class WelcomeViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
private(set) var defaultServers: [Mastodon.Entity.DefaultServer]?
|
||||
var randomDefaultServer: Mastodon.Entity.Server?
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
|
||||
// output
|
||||
@Published var needsShowDismissEntry = false
|
||||
|
||||
init(context: AppContext) {
|
||||
self.context = context
|
||||
|
||||
init() {
|
||||
AuthenticationServiceProvider.shared.$mastodonAuthenticationBoxes
|
||||
.map { !$0.isEmpty }
|
||||
.assign(to: &$needsShowDismissEntry)
|
||||
|
@ -19,9 +19,6 @@ protocol ProfileAboutViewControllerDelegate: AnyObject {
|
||||
|
||||
final class ProfileAboutViewController: UIViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
weak var delegate: ProfileAboutViewControllerDelegate?
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
@ -14,10 +14,7 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class BookmarkViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class BookmarkViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: BookmarkViewModel!
|
||||
|
@ -15,9 +15,7 @@ extension BookmarkViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: nil,
|
||||
|
@ -17,7 +17,6 @@ final class BookmarkViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
let dataController: StatusDataController
|
||||
@ -38,8 +37,7 @@ final class BookmarkViewModel {
|
||||
}()
|
||||
|
||||
@MainActor
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.dataController = StatusDataController()
|
||||
}
|
||||
|
@ -12,19 +12,14 @@ import MastodonLocalization
|
||||
import MastodonUI
|
||||
import MastodonSDK
|
||||
|
||||
final class FamiliarFollowersViewController: UIViewController, NeedsDependency {
|
||||
final class FamiliarFollowersViewController: UIViewController {
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator!
|
||||
let viewModel: FamiliarFollowersViewModel
|
||||
|
||||
let tableView: UITableView
|
||||
|
||||
init(viewModel: FamiliarFollowersViewModel, context: AppContext, coordinator: SceneCoordinator) {
|
||||
init(viewModel: FamiliarFollowersViewModel) {
|
||||
self.viewModel = viewModel
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
|
||||
tableView = UITableView()
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.separatorStyle = .none
|
||||
|
@ -10,7 +10,6 @@ import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
final class FamiliarFollowersViewModel {
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
var accounts: [Mastodon.Entity.Account]
|
||||
@ -19,8 +18,7 @@ final class FamiliarFollowersViewModel {
|
||||
// output
|
||||
var diffableDataSource: UITableViewDiffableDataSource<UserSection, UserItem>?
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox, accounts: [Mastodon.Entity.Account], relationships: [Mastodon.Entity.Relationship]) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox, accounts: [Mastodon.Entity.Account], relationships: [Mastodon.Entity.Relationship]) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.accounts = accounts
|
||||
self.relationships = relationships
|
||||
@ -32,7 +30,6 @@ final class FamiliarFollowersViewModel {
|
||||
) {
|
||||
diffableDataSource = UserSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
userTableViewCellDelegate: userTableViewCellDelegate
|
||||
)
|
||||
|
@ -17,10 +17,7 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class FavoriteViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class FavoriteViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: FavoriteViewModel!
|
||||
|
@ -15,9 +15,7 @@ extension FavoriteViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: nil,
|
||||
|
@ -17,7 +17,6 @@ final class FavoriteViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let dataController: StatusDataController
|
||||
|
||||
@ -37,8 +36,7 @@ final class FavoriteViewModel {
|
||||
}()
|
||||
|
||||
@MainActor
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.dataController = StatusDataController()
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ import MastodonCore
|
||||
import MastodonUI
|
||||
import MastodonLocalization
|
||||
|
||||
final class FollowedTagsViewController: UIViewController, NeedsDependency {
|
||||
var context: AppContext!
|
||||
var coordinator: SceneCoordinator!
|
||||
final class FollowedTagsViewController: UIViewController {
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
var viewModel: FollowedTagsViewModel
|
||||
@ -22,9 +20,7 @@ final class FollowedTagsViewController: UIViewController, NeedsDependency {
|
||||
let tableView: UITableView
|
||||
let refreshControl: UIRefreshControl
|
||||
|
||||
init(appContext: AppContext, sceneCoordinator: SceneCoordinator, authenticationBox: MastodonAuthenticationBox, viewModel: FollowedTagsViewModel) {
|
||||
self.context = appContext
|
||||
self.coordinator = sceneCoordinator
|
||||
init(authenticationBox: MastodonAuthenticationBox, viewModel: FollowedTagsViewModel) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.viewModel = viewModel
|
||||
|
||||
@ -76,12 +72,11 @@ extension FollowedTagsViewController: UITableViewDelegate {
|
||||
let object = viewModel.followedTags[indexPath.row]
|
||||
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(
|
||||
context: self.context,
|
||||
authenticationBox: self.authenticationBox,
|
||||
hashtag: object.name
|
||||
)
|
||||
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
|
@ -16,11 +16,9 @@ final class FollowedTagsViewModel: NSObject {
|
||||
var diffableDataSource: UITableViewDiffableDataSource<Section, Item>?
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.followedTags = []
|
||||
|
||||
|
@ -13,10 +13,7 @@ import MastodonUI
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
|
||||
final class FollowerListViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator!
|
||||
final class FollowerListViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: FollowerListViewModel
|
||||
@ -24,10 +21,8 @@ final class FollowerListViewController: UIViewController, NeedsDependency {
|
||||
let tableView: UITableView
|
||||
let refreshControl: UIRefreshControl
|
||||
|
||||
init(viewModel: FollowerListViewModel, coordinator: SceneCoordinator, context: AppContext) {
|
||||
init(viewModel: FollowerListViewModel) {
|
||||
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
self.viewModel = viewModel
|
||||
|
||||
tableView = UITableView()
|
||||
|
@ -17,7 +17,6 @@ extension FollowerListViewModel {
|
||||
) {
|
||||
diffableDataSource = UserSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
userTableViewCellDelegate: userTableViewCellDelegate
|
||||
)
|
||||
|
@ -15,7 +15,6 @@ final class FollowerListViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
@Published var accounts: [Mastodon.Entity.Account]
|
||||
@Published var relationships: [Mastodon.Entity.Relationship]
|
||||
@ -43,12 +42,10 @@ final class FollowerListViewModel {
|
||||
}()
|
||||
|
||||
init(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
domain: String?,
|
||||
userID: String?
|
||||
) {
|
||||
self.context = context
|
||||
self.authenticationBox = authenticationBox
|
||||
self.domain = domain
|
||||
self.userID = userID
|
||||
|
@ -14,10 +14,7 @@ import MastodonUI
|
||||
import CoreDataStack
|
||||
import MastodonSDK
|
||||
|
||||
final class FollowingListViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator!
|
||||
final class FollowingListViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: FollowingListViewModel
|
||||
@ -25,10 +22,8 @@ final class FollowingListViewController: UIViewController, NeedsDependency {
|
||||
let refreshControl: UIRefreshControl
|
||||
let tableView: UITableView
|
||||
|
||||
init(viewModel: FollowingListViewModel, coordinator: SceneCoordinator, context: AppContext) {
|
||||
init(viewModel: FollowingListViewModel) {
|
||||
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
self.viewModel = viewModel
|
||||
|
||||
tableView = UITableView()
|
||||
|
@ -18,7 +18,6 @@ extension FollowingListViewModel {
|
||||
) {
|
||||
diffableDataSource = UserSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
userTableViewCellDelegate: userTableViewCellDelegate
|
||||
)
|
||||
|
@ -16,7 +16,6 @@ final class FollowingListViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
@Published var accounts: [Mastodon.Entity.Account]
|
||||
@Published var relationships: [Mastodon.Entity.Relationship]
|
||||
@ -44,12 +43,10 @@ final class FollowingListViewModel {
|
||||
}()
|
||||
|
||||
init(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
domain: String?,
|
||||
userID: String?
|
||||
) {
|
||||
self.context = context
|
||||
self.authenticationBox = authenticationBox
|
||||
self.domain = domain
|
||||
self.userID = userID
|
||||
|
@ -25,14 +25,11 @@ protocol ProfileHeaderViewControllerDelegate: AnyObject {
|
||||
func profileHeaderViewController(_ profileHeaderViewController: ProfileHeaderViewController, profileHeaderView: ProfileHeaderView, metaTextView: MetaTextView, metaDidPressed meta: Meta)
|
||||
}
|
||||
|
||||
final class ProfileHeaderViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
final class ProfileHeaderViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
static let segmentedControlHeight: CGFloat = 50
|
||||
static let headerMinHeight: CGFloat = segmentedControlHeight
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
let viewModel: ProfileHeaderViewModel
|
||||
|
||||
@ -82,10 +79,8 @@ final class ProfileHeaderViewController: UIViewController, NeedsDependency, Medi
|
||||
return documentPickerController
|
||||
}()
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox, coordinator: SceneCoordinator, profileViewModel: ProfileViewModel) {
|
||||
self.context = context
|
||||
self.coordinator = coordinator
|
||||
self.viewModel = ProfileHeaderViewModel(context: context, authenticationBox: authenticationBox, account: profileViewModel.account, me: profileViewModel.me, relationship: profileViewModel.relationship)
|
||||
init(authenticationBox: MastodonAuthenticationBox, profileViewModel: ProfileViewModel) {
|
||||
self.viewModel = ProfileHeaderViewModel(authenticationBox: authenticationBox, account: profileViewModel.account, me: profileViewModel.me, relationship: profileViewModel.relationship)
|
||||
self.profileHeaderView = ProfileHeaderView(account: profileViewModel.account, me: profileViewModel.me, relationship: profileViewModel.relationship)
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
@ -341,12 +336,11 @@ extension ProfileHeaderViewController: ProfileHeaderViewDelegate {
|
||||
guard let domain = viewModel.account.domain else { return }
|
||||
let userID = viewModel.account.id
|
||||
let followerListViewModel = FollowerListViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
domain: domain,
|
||||
userID: userID
|
||||
)
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .follower(viewModel: followerListViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -357,12 +351,11 @@ extension ProfileHeaderViewController: ProfileHeaderViewDelegate {
|
||||
|
||||
let userID = viewModel.account.id
|
||||
let followingListViewModel = FollowingListViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
domain: domain,
|
||||
userID: userID
|
||||
)
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .following(viewModel: followingListViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
|
@ -23,7 +23,6 @@ final class ProfileHeaderViewModel {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
|
||||
@Published var me: Mastodon.Entity.Account
|
||||
@ -45,8 +44,7 @@ final class ProfileHeaderViewModel {
|
||||
@Published var isTitleViewDisplaying = false
|
||||
@Published var isTitleViewContentOffsetSet = false
|
||||
|
||||
init(context: AppContext, authenticationBox: MastodonAuthenticationBox, account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) {
|
||||
self.context = context
|
||||
init(authenticationBox: MastodonAuthenticationBox, account: Mastodon.Entity.Account, me: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) {
|
||||
self.authenticationBox = authenticationBox
|
||||
self.account = account
|
||||
self.me = me
|
||||
|
@ -22,14 +22,11 @@ protocol ProfileViewModelEditable {
|
||||
var isEdited: Bool { get }
|
||||
}
|
||||
|
||||
final class ProfileViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
final class ProfileViewController: UIViewController, MediaPreviewableViewController {
|
||||
|
||||
public static let containerViewMarginForRegularHorizontalSizeClass: CGFloat = 64
|
||||
public static let containerViewMarginForCompactHorizontalSizeClass: CGFloat = 16
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
var viewModel: ProfileViewModel? {
|
||||
@ -144,7 +141,7 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi
|
||||
}
|
||||
|
||||
private func createProfileHeaderViewController(viewModel: ProfileViewModel) -> ProfileHeaderViewController {
|
||||
let viewController = ProfileHeaderViewController(context: context, authenticationBox: viewModel.authenticationBox, coordinator: coordinator, profileViewModel: viewModel)
|
||||
let viewController = ProfileHeaderViewController(authenticationBox: viewModel.authenticationBox, profileViewModel: viewModel)
|
||||
return viewController
|
||||
}
|
||||
|
||||
@ -159,12 +156,6 @@ final class ProfileViewController: UIViewController, NeedsDependency, MediaPrevi
|
||||
mediaUserTimelineViewModel: viewModel.mediaUserTimelineViewModel,
|
||||
profileAboutViewModel: viewModel.profileAboutViewModel
|
||||
)
|
||||
profilePagingViewModel.viewControllers.forEach { viewController in
|
||||
if let viewController = viewController as? NeedsDependency {
|
||||
viewController.context = context
|
||||
viewController.coordinator = coordinator
|
||||
}
|
||||
}
|
||||
return profilePagingViewModel
|
||||
}()
|
||||
return profilePagingViewController
|
||||
@ -553,15 +544,15 @@ extension ProfileViewController {
|
||||
switch meta {
|
||||
case .url(_, _, let url, _):
|
||||
guard let url = URL(string: url) else { return }
|
||||
_ = coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .mention(_, _, let userInfo):
|
||||
guard let href = userInfo?["href"] as? String,
|
||||
let url = URL(string: href) else { return }
|
||||
_ = coordinator.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .safari(url: url), from: nil, transition: .safariPresent(animated: true, completion: nil))
|
||||
case .hashtag(_, let hashtag, _):
|
||||
guard let viewModel = viewModel else { break }
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(context: context, authenticationBox: viewModel.authenticationBox, hashtag: hashtag)
|
||||
_ = coordinator.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: nil, transition: .show)
|
||||
let hashtagTimelineViewModel = HashtagTimelineViewModel(authenticationBox: viewModel.authenticationBox, hashtag: hashtag)
|
||||
_ = self.sceneCoordinator?.present(scene: .hashtagTimeline(viewModel: hashtagTimelineViewModel), from: nil, transition: .show)
|
||||
case .email, .emoji:
|
||||
break
|
||||
}
|
||||
@ -578,7 +569,7 @@ extension ProfileViewController {
|
||||
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
guard let setting = SettingService.shared.currentSetting.value else { return }
|
||||
|
||||
_ = coordinator.present(scene: .settings(setting: setting), from: self, transition: .none)
|
||||
_ = self.sceneCoordinator?.present(scene: .settings(setting: setting), from: self, transition: .none)
|
||||
}
|
||||
|
||||
@objc private func shareBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
@ -588,7 +579,7 @@ extension ProfileViewController {
|
||||
dependency: self,
|
||||
account: viewModel.account
|
||||
)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .activityViewController(
|
||||
activityViewController: activityViewController,
|
||||
sourceView: nil,
|
||||
@ -602,15 +593,15 @@ extension ProfileViewController {
|
||||
@objc private func favoriteBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
guard let viewModel = viewModel else { return }
|
||||
|
||||
let favoriteViewModel = FavoriteViewModel(context: context, authenticationBox: viewModel.authenticationBox)
|
||||
_ = coordinator.present(scene: .favorite(viewModel: favoriteViewModel), from: self, transition: .show)
|
||||
let favoriteViewModel = FavoriteViewModel(authenticationBox: viewModel.authenticationBox)
|
||||
_ = self.sceneCoordinator?.present(scene: .favorite(viewModel: favoriteViewModel), from: self, transition: .show)
|
||||
}
|
||||
|
||||
@objc private func bookmarkBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
guard let viewModel = viewModel else { return }
|
||||
|
||||
let bookmarkViewModel = BookmarkViewModel(context: context, authenticationBox: viewModel.authenticationBox)
|
||||
_ = coordinator.present(scene: .bookmark(viewModel: bookmarkViewModel), from: self, transition: .show)
|
||||
let bookmarkViewModel = BookmarkViewModel(authenticationBox: viewModel.authenticationBox)
|
||||
_ = self.sceneCoordinator?.present(scene: .bookmark(viewModel: bookmarkViewModel), from: self, transition: .show)
|
||||
}
|
||||
|
||||
@objc private func replyBarButtonItemPressed(_ sender: UIBarButtonItem) {
|
||||
@ -619,20 +610,19 @@ extension ProfileViewController {
|
||||
let mention = "@" + viewModel.account.acct
|
||||
UITextChecker.learnWord(mention)
|
||||
let composeViewModel = ComposeViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
composeContext: .composeStatus,
|
||||
destination: .topLevel,
|
||||
initialContent: mention
|
||||
)
|
||||
_ = coordinator.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
_ = self.sceneCoordinator?.present(scene: .compose(viewModel: composeViewModel), from: self, transition: .modal(animated: true, completion: nil))
|
||||
}
|
||||
|
||||
@objc private func followedTagsItemPressed(_ sender: UIBarButtonItem) {
|
||||
guard let viewModel = viewModel else { return }
|
||||
|
||||
let followedTagsViewModel = FollowedTagsViewModel(context: context, authenticationBox: viewModel.authenticationBox)
|
||||
_ = coordinator.present(scene: .followedTags(viewModel: followedTagsViewModel), from: self, transition: .show)
|
||||
let followedTagsViewModel = FollowedTagsViewModel(authenticationBox: viewModel.authenticationBox)
|
||||
_ = self.sceneCoordinator?.present(scene: .followedTags(viewModel: followedTagsViewModel), from: self, transition: .show)
|
||||
}
|
||||
|
||||
@objc private func refreshControlValueChanged(_ sender: RefreshControl) {
|
||||
@ -840,7 +830,7 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||
let alertController = UIAlertController(for: error, title: L10n.Common.Alerts.EditProfileFailure.title, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
@ -900,7 +890,7 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||
alertController.addAction(unblockAction)
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
coordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
} else if relationship.domainBlocking {
|
||||
guard let domain = account.domain else { return }
|
||||
|
||||
@ -930,7 +920,7 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||
alertController.addAction(unblockAction)
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
coordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
|
||||
} else if relationship.muting {
|
||||
let name = account.displayNameWithFallback
|
||||
@ -950,7 +940,7 @@ extension ProfileViewController: ProfileHeaderViewControllerDelegate {
|
||||
alertController.addAction(unmuteAction)
|
||||
let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .cancel)
|
||||
alertController.addAction(cancelAction)
|
||||
coordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
self.sceneCoordinator?.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
||||
} else {
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
|
@ -14,10 +14,7 @@ import TabBarPager
|
||||
import XLPagerTabStrip
|
||||
import MastodonCore
|
||||
|
||||
final class UserTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController, StatusReloadable {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class UserTimelineViewController: UIViewController, MediaPreviewableViewController, StatusReloadable {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: UserTimelineViewModel!
|
||||
|
@ -16,9 +16,7 @@ extension UserTimelineViewModel {
|
||||
) {
|
||||
diffableDataSource = StatusSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
configuration: StatusSection.Configuration(
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
statusTableViewCellDelegate: statusTableViewCellDelegate,
|
||||
timelineMiddleLoaderTableViewCellDelegate: nil,
|
||||
|
@ -13,9 +13,7 @@ import MastodonLocalization
|
||||
import MastodonUI
|
||||
import CoreDataStack
|
||||
|
||||
final class FavoritedByViewController: UIViewController, NeedsDependency {
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class FavoritedByViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: UserListViewModel!
|
||||
|
@ -13,10 +13,7 @@ import MastodonLocalization
|
||||
import MastodonUI
|
||||
import CoreDataStack
|
||||
|
||||
final class RebloggedByViewController: UIViewController, NeedsDependency {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class RebloggedByViewController: UIViewController {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
var viewModel: UserListViewModel!
|
||||
|
@ -19,7 +19,6 @@ extension UserListViewModel {
|
||||
) {
|
||||
diffableDataSource = UserSection.diffableDataSource(
|
||||
tableView: tableView,
|
||||
context: context,
|
||||
authenticationBox: authenticationBox,
|
||||
userTableViewCellDelegate: userTableViewCellDelegate
|
||||
)
|
||||
|
@ -12,13 +12,10 @@ import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
|
||||
class ReportViewController: UIViewController, NeedsDependency, ReportViewControllerAppearance {
|
||||
class ReportViewController: UIViewController, ReportViewControllerAppearance {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
private var observations = Set<NSKeyValueObservation>()
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
let viewModel: ReportViewModel
|
||||
|
||||
@ -50,8 +47,6 @@ class ReportViewController: UIViewController, NeedsDependency, ReportViewControl
|
||||
viewModel.reportSupplementaryViewModel.delegate = self
|
||||
|
||||
let reportReasonViewController = ReportReasonViewController(viewModel: viewModel.reportReasonViewModel)
|
||||
reportReasonViewController.context = context
|
||||
reportReasonViewController.coordinator = coordinator
|
||||
|
||||
addChild(reportReasonViewController)
|
||||
reportReasonViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
@ -80,25 +75,24 @@ extension ReportViewController: ReportReasonViewControllerDelegate {
|
||||
switch reason {
|
||||
case .dislike:
|
||||
let reportResultViewModel = ReportResultViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
account: viewModel.account,
|
||||
relationship: viewModel.relationship,
|
||||
isReported: false
|
||||
)
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportResult(viewModel: reportResultViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
)
|
||||
case .violateRule:
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportServerRules(viewModel: viewModel.reportServerRulesViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
)
|
||||
case .spam, .other:
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportStatus(viewModel: viewModel.reportStatusViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -114,7 +108,7 @@ extension ReportViewController: ReportServerRulesViewControllerDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportStatus(viewModel: viewModel.reportStatusViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -133,7 +127,7 @@ extension ReportViewController: ReportStatusViewControllerDelegate {
|
||||
}
|
||||
|
||||
private func coordinateToReportSupplementary() {
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportSupplementary(viewModel: viewModel.reportSupplementaryViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -157,14 +151,13 @@ extension ReportViewController: ReportSupplementaryViewControllerDelegate {
|
||||
let _ = try await viewModel.report()
|
||||
|
||||
let reportResultViewModel = ReportResultViewModel(
|
||||
context: context,
|
||||
authenticationBox: viewModel.authenticationBox,
|
||||
account: viewModel.account,
|
||||
relationship: viewModel.relationship,
|
||||
isReported: true
|
||||
)
|
||||
|
||||
_ = coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .reportResult(viewModel: reportResultViewModel),
|
||||
from: self,
|
||||
transition: .show
|
||||
@ -174,7 +167,7 @@ extension ReportViewController: ReportSupplementaryViewControllerDelegate {
|
||||
let alertController = UIAlertController(for: error, title: nil, preferredStyle: .alert)
|
||||
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default, handler: nil)
|
||||
alertController.addAction(okAction)
|
||||
_ = self.coordinator.present(
|
||||
_ = self.sceneCoordinator?.present(
|
||||
scene: .alertController(alertController: alertController),
|
||||
from: nil,
|
||||
transition: .alertController(animated: true, completion: nil)
|
||||
|
@ -17,10 +17,7 @@ protocol ReportReasonViewControllerDelegate: AnyObject {
|
||||
func reportReasonViewController(_ viewController: ReportReasonViewController, nextButtonPressed button: UIButton)
|
||||
}
|
||||
|
||||
final class ReportReasonViewController: UIViewController, NeedsDependency, ReportViewControllerAppearance {
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
final class ReportReasonViewController: UIViewController, ReportViewControllerAppearance {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
private var observations = Set<NSKeyValueObservation>()
|
||||
|
@ -12,13 +12,10 @@ import MastodonAsset
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
|
||||
final class ReportResultViewController: UIViewController, NeedsDependency, ReportViewControllerAppearance {
|
||||
final class ReportResultViewController: UIViewController, ReportViewControllerAppearance {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
private var observations = Set<NSKeyValueObservation>()
|
||||
|
||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||
|
||||
var viewModel: ReportResultViewModel!
|
||||
private(set) lazy var reportResultView = ReportResultView(viewModel: viewModel)
|
||||
|
@ -21,7 +21,6 @@ class ReportResultViewModel: ObservableObject {
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
// input
|
||||
let context: AppContext
|
||||
let authenticationBox: MastodonAuthenticationBox
|
||||
let account: Mastodon.Entity.Account
|
||||
var relationship: Mastodon.Entity.Relationship
|
||||
@ -46,13 +45,11 @@ class ReportResultViewModel: ObservableObject {
|
||||
let blockActionPublisher = PassthroughSubject<Void, Never>()
|
||||
|
||||
init(
|
||||
context: AppContext,
|
||||
authenticationBox: MastodonAuthenticationBox,
|
||||
account: Mastodon.Entity.Account,
|
||||
relationship: Mastodon.Entity.Relationship,
|
||||
isReported: Bool
|
||||
) {
|
||||
self.context = context
|
||||
self.authenticationBox = authenticationBox
|
||||
self.account = account
|
||||
self.relationship = relationship
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user