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