mastodon-ios/Mastodon/Protocol/Provider/DataSourceFacade+Profile.swift

184 lines
6.1 KiB
Swift

//
// DataSourceFacade+Profile.swift
// Mastodon
//
// Created by MainasuK on 2022-1-13.
//
import UIKit
import CoreDataStack
import MastodonCore
import MastodonSDK
extension DataSourceFacade {
static func coordinateToProfileScene(
provider: DataSourceProvider & AuthContextProvider,
target: StatusTarget,
status: ManagedObjectRecord<Status>
) async {
let _redirectRecord = await DataSourceFacade.author(
managedObjectContext: provider.context.managedObjectContext,
status: status,
target: target
)
guard let redirectRecord = _redirectRecord else {
assertionFailure()
return
}
await coordinateToProfileScene(
provider: provider,
user: redirectRecord
)
}
@MainActor
static func coordinateToProfileScene(
provider: ViewControllerWithDependencies & AuthContextProvider,
user: ManagedObjectRecord<MastodonUser>
) async {
guard let user = user.object(in: provider.context.managedObjectContext) else {
assertionFailure()
return
}
let profileViewModel = ProfileViewModel(
context: provider.context,
authContext: provider.authContext,
optionalMastodonUser: user
)
_ = provider.coordinator.present(
scene: .profile(viewModel: profileViewModel),
from: provider,
transition: .show
)
}
@MainActor
static func coordinateToProfileScene(
provider: ViewControllerWithDependencies & AuthContextProvider,
account: Mastodon.Entity.Account
) async {
provider.coordinator.showLoading()
guard let domain = account.domain else { return provider.coordinator.hideLoading() }
Task {
do {
let user = try await provider.context.apiService.fetchUser(username: account.username,
domain: domain,
authenticationBox: provider.authContext.mastodonAuthenticationBox)
provider.coordinator.hideLoading()
if let user {
await coordinateToProfileScene(provider: provider, user: user.asRecord)
}
} catch {
provider.coordinator.hideLoading()
}
}
}
}
extension DataSourceFacade {
static func coordinateToProfileScene(
provider: DataSourceProvider & AuthContextProvider,
status: ManagedObjectRecord<Status>,
mention: String, // username,
userInfo: [AnyHashable: Any]?
) async {
let domain = provider.authContext.mastodonAuthenticationBox.domain
guard
let href = userInfo?["href"] as? String,
let url = URL(string: href)
else {
return
}
let managedObjectContext = provider.context.managedObjectContext
let mentions = try? await managedObjectContext.perform {
return status.object(in: managedObjectContext)?.mentions ?? []
}
guard let mention = mentions?.first(where: { $0.url == href }) else {
_ = await provider.coordinator.present(
scene: .safari(url: url),
from: provider,
transition: .safariPresent(animated: true, completion: nil)
)
return
}
let userID = mention.id
let profileViewModel: ProfileViewModel = {
// check if self
guard userID != provider.authContext.mastodonAuthenticationBox.userID else {
return MeProfileViewModel(context: provider.context, authContext: provider.authContext)
}
let request = MastodonUser.sortedFetchRequest
request.fetchLimit = 1
request.predicate = MastodonUser.predicate(domain: domain, id: userID)
let _user = provider.context.managedObjectContext.safeFetch(request).first
if let user = _user {
return ProfileViewModel(context: provider.context, authContext: provider.authContext, optionalMastodonUser: user)
} else {
return RemoteProfileViewModel(context: provider.context, authContext: provider.authContext, userID: userID)
}
}()
_ = await provider.coordinator.present(
scene: .profile(viewModel: profileViewModel),
from: provider,
transition: .show
)
}
}
extension DataSourceFacade {
struct ProfileActionMenuContext {
let isMuting: Bool
let isBlocking: Bool
let isMyself: Bool
let cell: UITableViewCell?
let sourceView: UIView?
let barButtonItem: UIBarButtonItem?
}
static func createActivityViewController(
dependency: NeedsDependency,
user: ManagedObjectRecord<MastodonUser>
) async throws -> UIActivityViewController? {
let managedObjectContext = dependency.context.managedObjectContext
let activityItems: [Any] = try await managedObjectContext.perform {
guard let user = user.object(in: managedObjectContext) else { return [] }
return user.activityItems
}
guard !activityItems.isEmpty else {
assertionFailure()
return nil
}
let activityViewController = await UIActivityViewController(
activityItems: activityItems,
applicationActivities: [SafariActivity(sceneCoordinator: dependency.coordinator)]
)
return activityViewController
}
static func createActivityViewControllerForMastodonUser(status: Status, dependency: NeedsDependency) -> UIActivityViewController {
let activityViewController = UIActivityViewController(
activityItems: status.activityItems,
applicationActivities: [SafariActivity(sceneCoordinator: dependency.coordinator)]
)
return activityViewController
}
}