diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index 50f5dfb0f..1b9e99521 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -107,11 +107,14 @@ final public class SceneCoordinator { notificationID: notificationID, authenticationBox: authContext.mastodonAuthenticationBox ).value.account - + + let relationship = try await appContext.apiService.relationship(forAccounts: [account], authenticationBox: authContext.mastodonAuthenticationBox).value.first + let profileViewModel = ProfileViewModel( context: appContext, authContext: authContext, - account: account + account: account, + relationship: relationship ) _ = self.present( scene: .profile(viewModel: profileViewModel), diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift index 30f556a2c..24e059f1c 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift @@ -102,17 +102,23 @@ extension DataSourceFacade { account: Mastodon.Entity.Account ) { - let profileViewModel = ProfileViewModel( - context: provider.context, - authContext: provider.authContext, - account: account - ) - - _ = provider.coordinator.present( - scene: .profile(viewModel: profileViewModel), - from: provider, - transition: .show - ) + Task { @MainActor in + + guard let relationship = try? await provider.context.apiService.relationship(forAccounts: [account], authenticationBox: provider.authContext.mastodonAuthenticationBox).value.first else { return } + + let profileViewModel = ProfileViewModel( + context: provider.context, + authContext: provider.authContext, + account: account, + relationship: relationship + ) + + _ = provider.coordinator.present( + scene: .profile(viewModel: profileViewModel), + from: provider, + transition: .show + ) + } } } diff --git a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift index 0ebd0511b..05d290742 100644 --- a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift +++ b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift @@ -296,16 +296,7 @@ extension NotificationTimelineViewController: TableViewControllerNavigateable { ) } else { - let profileViewModel = ProfileViewModel( - context: self.context, - authContext: self.viewModel.authContext, - account: notification.account - ) - _ = self.coordinator.present( - scene: .profile(viewModel: profileViewModel), - from: self, - transition: .show - ) + DataSourceFacade.coordinateToProfileScene(provider: self, account: notification.account) } default: break diff --git a/Mastodon/Scene/Profile/ProfileViewModel.swift b/Mastodon/Scene/Profile/ProfileViewModel.swift index 01b29a46f..7c705ecc8 100644 --- a/Mastodon/Scene/Profile/ProfileViewModel.swift +++ b/Mastodon/Scene/Profile/ProfileViewModel.swift @@ -56,10 +56,12 @@ class ProfileViewModel: NSObject { // let needsPagePinToTop = CurrentValueSubject(false) @MainActor - init(context: AppContext, authContext: AuthContext, account: Mastodon.Entity.Account) { + init(context: AppContext, authContext: AuthContext, account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?) { self.context = context self.authContext = authContext self.account = account + self.relationship = relationship + self.postsUserTimelineViewModel = UserTimelineViewModel( context: context, authContext: authContext, diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index 258585c1d..f247b83cc 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -119,7 +119,7 @@ class MainTabBarController: UITabBarController { let _viewController = ProfileViewController() _viewController.context = context _viewController.coordinator = coordinator - _viewController.viewModel = ProfileViewModel(context: context, authContext: authContext, account: me) + _viewController.viewModel = ProfileViewModel(context: context, authContext: authContext, account: me, relationship: nil) viewController = _viewController } viewController.title = self.title diff --git a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift index 59c1d5b01..e41dde9d0 100644 --- a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift @@ -2,13 +2,18 @@ import UIKit import MastodonSDK +import MastodonCore protocol AboutInstanceViewControllerDelegate: AnyObject { func showAdminAccount(_ viewController: AboutInstanceViewController, account: Mastodon.Entity.Account) func sendEmailToAdmin(_ viewController: AboutInstanceViewController, emailAddress: String) } -class AboutInstanceViewController: UIViewController { +class AboutInstanceViewController: UIViewController, NeedsDependency, AuthContextProvider { + + var authContext: AuthContext + var context: AppContext! + var coordinator: SceneCoordinator! weak var delegate: AboutInstanceViewControllerDelegate? var dataSource: AboutInstanceTableViewDataSource? @@ -19,7 +24,12 @@ class AboutInstanceViewController: UIViewController { var instance: Mastodon.Entity.V2.Instance? - init() { + init(context: AppContext, authContext: AuthContext, coordinator: SceneCoordinator) { + + self.context = context + self.authContext = authContext + self.coordinator = coordinator + tableView = UITableView(frame: .zero, style: .insetGrouped) tableView.translatesAutoresizingMaskIntoConstraints = false tableView.register(ContactAdminTableViewCell.self, forCellReuseIdentifier: ContactAdminTableViewCell.reuseIdentifier) diff --git a/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift b/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift index fb724f8f9..4dd19b7c0 100644 --- a/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift @@ -4,6 +4,7 @@ import UIKit import MastodonSDK import MastodonLocalization import MetaTextKit +import MastodonCore enum ServerDetailsTab: Int, CaseIterable { case about = 0 @@ -36,7 +37,7 @@ class ServerDetailsViewController: UIViewController { let instanceRulesViewController: InstanceRulesViewController let containerView: UIView - init(domain: String) { + init(domain: String, appContext: AppContext, authContext: AuthContext, sceneCoordinator: SceneCoordinator) { segmentedControl = UISegmentedControl() segmentedControl.translatesAutoresizingMaskIntoConstraints = false @@ -47,7 +48,7 @@ class ServerDetailsViewController: UIViewController { containerView = UIView() containerView.translatesAutoresizingMaskIntoConstraints = false - aboutInstanceViewController = AboutInstanceViewController() + aboutInstanceViewController = AboutInstanceViewController(context: appContext, authContext: authContext, coordinator: sceneCoordinator) instanceRulesViewController = InstanceRulesViewController() pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) diff --git a/Mastodon/Scene/Settings/SettingsCoordinator.swift b/Mastodon/Scene/Settings/SettingsCoordinator.swift index b1150e3f7..8d9e40695 100644 --- a/Mastodon/Scene/Settings/SettingsCoordinator.swift +++ b/Mastodon/Scene/Settings/SettingsCoordinator.swift @@ -70,7 +70,7 @@ extension SettingsCoordinator: SettingsViewControllerDelegate { navigationController.pushViewController(notificationViewController, animated: true) case .serverDetails(let domain): - let serverDetailsViewController = ServerDetailsViewController(domain: domain) + let serverDetailsViewController = ServerDetailsViewController(domain: domain, appContext: appContext, authContext: authContext, sceneCoordinator: sceneCoordinator) serverDetailsViewController.delegate = self appContext.apiService.instanceV2(domain: domain) @@ -217,8 +217,7 @@ extension SettingsCoordinator: ServerDetailsViewControllerDelegate { extension SettingsCoordinator: AboutInstanceViewControllerDelegate { @MainActor func showAdminAccount(_ viewController: AboutInstanceViewController, account: Mastodon.Entity.Account) { - let profileViewModel = ProfileViewModel(context: appContext, authContext: authContext, account: account) - sceneCoordinator.present(scene: .profile(viewModel: profileViewModel), transition: .show) + DataSourceFacade.coordinateToProfileScene(provider: viewController, account: account) } func sendEmailToAdmin(_ viewController: AboutInstanceViewController, emailAddress: String) { diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 9ecbfe58a..3bff14995 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -146,10 +146,16 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { authenticationBox: authenticationBox ).value.accounts.first else { return } + guard let relationship = try await AppContext.shared.apiService.relationship( + forAccounts: [account], + authenticationBox: authenticationBox + ).value.first else { return } + let profileViewModel = ProfileViewModel( context: AppContext.shared, authContext: authContext, - account: account + account: account, + relationship: relationship ) _ = self.coordinator?.present( scene: .profile(viewModel: profileViewModel), @@ -284,11 +290,18 @@ extension SceneDelegate { authenticationBox: authenticationBox ).value.accounts.first else { return } + guard let relationship = try await AppContext.shared.apiService.relationship( + forAccounts: [account], + authenticationBox: authenticationBox + ).value.first else { return } + let profileViewModel = ProfileViewModel( context: AppContext.shared, authContext: authContext, - account: account + account: account, + relationship: relationship ) + self.coordinator?.present( scene: .profile(viewModel: profileViewModel), from: nil, diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Relationship.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Relationship.swift index b6c5ebcd4..ce366ad7e 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Relationship.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Relationship.swift @@ -12,60 +12,6 @@ import CoreDataStack import MastodonSDK extension APIService { - - public func relationship( - records: [ManagedObjectRecord], - authenticationBox: MastodonAuthenticationBox - ) async throws -> Mastodon.Response.Content<[Mastodon.Entity.Relationship]> { - let managedObjectContext = backgroundManagedObjectContext - - let _query: Mastodon.API.Account.RelationshipQuery? = try? await managedObjectContext.perform { - var ids: [String] = [] - for record in records { - guard let user = record.object(in: managedObjectContext) else { continue } - guard user.id != authenticationBox.userID else { continue } - ids.append(user.id) - } - guard !ids.isEmpty else { return nil } - return Mastodon.API.Account.RelationshipQuery(ids: ids) - } - guard let query = _query else { - throw APIError.implicit(.badRequest) - } - - let response = try await Mastodon.API.Account.relationships( - session: session, - domain: authenticationBox.domain, - query: query, - authorization: authenticationBox.userAuthorization - ).singleOutput() - - try await managedObjectContext.performChanges { - guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { - // assertionFailure() - return - } - - let relationships = response.value - for record in records { - guard let user = record.object(in: managedObjectContext) else { continue } - guard let relationship = relationships.first(where: { $0.id == user.id }) else { continue } - - Persistence.MastodonUser.update( - mastodonUser: user, - context: Persistence.MastodonUser.RelationshipContext( - entity: relationship, - me: me, - networkDate: response.networkDate - ) - ) - } // end for in - } - - return response - } - - public func relationship( forAccounts accounts: [Mastodon.Entity.Account], authenticationBox: MastodonAuthenticationBox diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Search.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Search.swift index 123c01d17..3b3624344 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Search.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Search.swift @@ -24,25 +24,6 @@ extension APIService { query: query, authorization: authorization ).singleOutput() - - let managedObjectContext = self.backgroundManagedObjectContext - try await managedObjectContext.performChanges { - let me = authenticationBox.authentication.user(in: managedObjectContext) - - // user - for entity in response.value.accounts { - _ = Persistence.MastodonUser.createOrMerge( - in: managedObjectContext, - context: Persistence.MastodonUser.PersistContext( - domain: domain, - entity: entity, - cache: nil, - networkDate: response.networkDate - ) - ) - } - - } // ent try await managedObjectContext.performChanges { … } return response }