forked from zelo72/mastodon-ios
375 lines
16 KiB
Swift
375 lines
16 KiB
Swift
//
|
|
// DataSourceFacade+Profile.swift
|
|
// Mastodon
|
|
//
|
|
// Created by MainasuK on 2022-1-13.
|
|
//
|
|
|
|
import UIKit
|
|
import CoreDataStack
|
|
|
|
extension DataSourceFacade {
|
|
|
|
static func coordinateToProfileScene(
|
|
provider: DataSourceProvider,
|
|
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: DataSourceProvider,
|
|
user: ManagedObjectRecord<MastodonUser>
|
|
) async {
|
|
guard let user = user.object(in: provider.context.managedObjectContext) else {
|
|
assertionFailure()
|
|
return
|
|
}
|
|
|
|
let profileViewModel = CachedProfileViewModel(
|
|
context: provider.context,
|
|
mastodonUser: user
|
|
)
|
|
|
|
provider.coordinator.present(
|
|
scene: .profile(viewModel: profileViewModel),
|
|
from: provider,
|
|
transition: .show
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
extension DataSourceFacade {
|
|
|
|
static func coordinateToProfileScene(
|
|
provider: DataSourceProvider,
|
|
status: ManagedObjectRecord<Status>,
|
|
mention: String, // username,
|
|
userInfo: [AnyHashable: Any]?
|
|
) async {
|
|
guard let authenticationBox = provider.context.authenticationService.activeMastodonAuthenticationBox.value else { return }
|
|
let domain = authenticationBox.domain
|
|
|
|
let href = userInfo?["href"] as? String
|
|
guard let url = href.flatMap({ URL(string: $0) }) 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.username == mention }) 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 != authenticationBox.userID else {
|
|
return MeProfileViewModel(context: provider.context)
|
|
}
|
|
|
|
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 CachedProfileViewModel(context: provider.context, mastodonUser: user)
|
|
} else {
|
|
return RemoteProfileViewModel(context: provider.context, 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?
|
|
}
|
|
|
|
// @MainActor
|
|
// static func createProfileActionMenu(
|
|
// dependency: NeedsDependency,
|
|
// user: ManagedObjectRecord<MastodonUser>
|
|
// ) -> UIMenu {
|
|
// var children: [UIMenuElement] = []
|
|
// let name = mastodonUser.displayNameWithFallback
|
|
//
|
|
// if let shareUser = shareUser {
|
|
// let shareAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.shareUser(name),
|
|
// image: UIImage(systemName: "square.and.arrow.up"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [],
|
|
// state: .off
|
|
// ) { [weak provider, weak sourceView, weak barButtonItem] _ in
|
|
// guard let provider = provider else { return }
|
|
// let activityViewController = createActivityViewControllerForMastodonUser(mastodonUser: shareUser, dependency: provider)
|
|
// provider.coordinator.present(
|
|
// scene: .activityViewController(
|
|
// activityViewController: activityViewController,
|
|
// sourceView: sourceView,
|
|
// barButtonItem: barButtonItem
|
|
// ),
|
|
// from: provider,
|
|
// transition: .activityViewControllerPresent(animated: true, completion: nil)
|
|
// )
|
|
// }
|
|
// children.append(shareAction)
|
|
// }
|
|
//
|
|
// if let shareStatus = shareStatus {
|
|
// let shareAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.sharePost,
|
|
// image: UIImage(systemName: "square.and.arrow.up"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [],
|
|
// state: .off
|
|
// ) { [weak provider, weak sourceView, weak barButtonItem] _ in
|
|
// guard let provider = provider else { return }
|
|
// let activityViewController = createActivityViewControllerForMastodonUser(status: shareStatus, dependency: provider)
|
|
// provider.coordinator.present(
|
|
// scene: .activityViewController(
|
|
// activityViewController: activityViewController,
|
|
// sourceView: sourceView,
|
|
// barButtonItem: barButtonItem
|
|
// ),
|
|
// from: provider,
|
|
// transition: .activityViewControllerPresent(animated: true, completion: nil)
|
|
// )
|
|
// }
|
|
// children.append(shareAction)
|
|
// }
|
|
//
|
|
// if !isMyself {
|
|
// // mute
|
|
// let muteAction = UIAction(
|
|
// title: isMuting ? L10n.Common.Controls.Friendship.unmuteUser(name) : L10n.Common.Controls.Friendship.mute,
|
|
// image: isMuting ? UIImage(systemName: "speaker") : UIImage(systemName: "speaker.slash"),
|
|
// discoverabilityTitle: isMuting ? nil : L10n.Common.Controls.Friendship.muteUser(name),
|
|
// attributes: isMuting ? [] : .destructive,
|
|
// state: .off
|
|
// ) { [weak provider, weak cell] _ in
|
|
// guard let provider = provider else { return }
|
|
//
|
|
// UserProviderFacade.toggleUserMuteRelationship(
|
|
// provider: provider,
|
|
// cell: cell
|
|
// )
|
|
// .sink { _ in
|
|
// // do nothing
|
|
// } receiveValue: { _ in
|
|
// // do nothing
|
|
// }
|
|
// .store(in: &provider.context.disposeBag)
|
|
// }
|
|
// if isMuting {
|
|
// children.append(muteAction)
|
|
// } else {
|
|
// let muteMenu = UIMenu(title: L10n.Common.Controls.Friendship.muteUser(name), image: UIImage(systemName: "speaker.slash"), options: [], children: [muteAction])
|
|
// children.append(muteMenu)
|
|
// }
|
|
// }
|
|
//
|
|
// if !isMyself {
|
|
// // block
|
|
// let blockAction = UIAction(
|
|
// title: isBlocking ? L10n.Common.Controls.Friendship.unblockUser(name) : L10n.Common.Controls.Friendship.block,
|
|
// image: isBlocking ? UIImage(systemName: "hand.raised.slash") : UIImage(systemName: "hand.raised"),
|
|
// discoverabilityTitle: isBlocking ? nil : L10n.Common.Controls.Friendship.blockUser(name),
|
|
// attributes: isBlocking ? [] : .destructive,
|
|
// state: .off
|
|
// ) { [weak provider, weak cell] _ in
|
|
// guard let provider = provider else { return }
|
|
//
|
|
// UserProviderFacade.toggleUserBlockRelationship(
|
|
// provider: provider,
|
|
// cell: cell
|
|
// )
|
|
// .sink { _ in
|
|
// // do nothing
|
|
// } receiveValue: { _ in
|
|
// // do nothing
|
|
// }
|
|
// .store(in: &provider.context.disposeBag)
|
|
// }
|
|
// if isBlocking {
|
|
// children.append(blockAction)
|
|
// } else {
|
|
// let blockMenu = UIMenu(title: L10n.Common.Controls.Friendship.blockUser(name), image: UIImage(systemName: "hand.raised"), options: [], children: [blockAction])
|
|
// children.append(blockMenu)
|
|
// }
|
|
// }
|
|
//
|
|
// if !isMyself {
|
|
// let reportAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.reportUser(name),
|
|
// image: UIImage(systemName: "flag"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [],
|
|
// state: .off
|
|
// ) { [weak provider] _ in
|
|
// guard let provider = provider else { return }
|
|
// guard let authenticationBox = provider.context.authenticationService.activeMastodonAuthenticationBox.value else {
|
|
// return
|
|
// }
|
|
// let viewModel = ReportViewModel(
|
|
// context: provider.context,
|
|
// domain: authenticationBox.domain,
|
|
// user: mastodonUser,
|
|
// status: nil
|
|
// )
|
|
// provider.coordinator.present(
|
|
// scene: .report(viewModel: viewModel),
|
|
// from: provider,
|
|
// transition: .modal(animated: true, completion: nil)
|
|
// )
|
|
// }
|
|
// children.append(reportAction)
|
|
// }
|
|
//
|
|
// if !isInSameDomain {
|
|
// if isDomainBlocking {
|
|
// let unblockDomainAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.unblockDomain(mastodonUser.domainFromAcct),
|
|
// image: UIImage(systemName: "nosign"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [],
|
|
// state: .off
|
|
// ) { [weak provider, weak cell] _ in
|
|
// guard let provider = provider else { return }
|
|
// provider.context.blockDomainService.unblockDomain(userProvider: provider, cell: cell)
|
|
// }
|
|
// children.append(unblockDomainAction)
|
|
// } else {
|
|
// let blockDomainAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.blockDomain(mastodonUser.domainFromAcct),
|
|
// image: UIImage(systemName: "nosign"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [],
|
|
// state: .off
|
|
// ) { [weak provider, weak cell] _ in
|
|
// guard let provider = provider else { return }
|
|
//
|
|
// let alertController = UIAlertController(title: L10n.Common.Alerts.BlockDomain.title(mastodonUser.domainFromAcct), message: nil, preferredStyle: .alert)
|
|
// let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .default) { _ in }
|
|
// alertController.addAction(cancelAction)
|
|
// let blockDomainAction = UIAlertAction(title: L10n.Common.Alerts.BlockDomain.blockEntireDomain, style: .destructive) { [weak provider, weak cell] _ in
|
|
// guard let provider = provider else { return }
|
|
// provider.context.blockDomainService.blockDomain(userProvider: provider, cell: cell)
|
|
// }
|
|
// alertController.addAction(blockDomainAction)
|
|
// provider.present(alertController, animated: true, completion: nil)
|
|
// }
|
|
// children.append(blockDomainAction)
|
|
// }
|
|
// }
|
|
//
|
|
// if let status = shareStatus, isMyself {
|
|
// let deleteAction = UIAction(
|
|
// title: L10n.Common.Controls.Actions.delete,
|
|
// image: UIImage(systemName: "delete.left"),
|
|
// identifier: nil,
|
|
// discoverabilityTitle: nil,
|
|
// attributes: [.destructive],
|
|
// state: .off
|
|
// ) { [weak provider] _ in
|
|
// guard let provider = provider else { return }
|
|
//
|
|
// let alertController = UIAlertController(title: L10n.Common.Alerts.DeletePost.title, message: nil, preferredStyle: .alert)
|
|
// let cancelAction = UIAlertAction(title: L10n.Common.Controls.Actions.cancel, style: .default) { _ in }
|
|
// alertController.addAction(cancelAction)
|
|
// let deleteAction = UIAlertAction(title: L10n.Common.Alerts.DeletePost.delete, style: .destructive) { [weak provider] _ in
|
|
// guard let provider = provider else { return }
|
|
// guard let activeMastodonAuthenticationBox = provider.context.authenticationService.activeMastodonAuthenticationBox.value else { return }
|
|
// provider.context.apiService.deleteStatus(
|
|
// domain: activeMastodonAuthenticationBox.domain,
|
|
// statusID: status.id,
|
|
// authorizationBox: activeMastodonAuthenticationBox
|
|
// )
|
|
// .sink { _ in
|
|
// // do nothing
|
|
// } receiveValue: { _ in
|
|
// // do nothing
|
|
// }
|
|
// .store(in: &provider.context.disposeBag)
|
|
// }
|
|
// alertController.addAction(deleteAction)
|
|
// provider.present(alertController, animated: true, completion: nil)
|
|
// }
|
|
// children.append(deleteAction)
|
|
// }
|
|
//
|
|
// return UIMenu(title: "", options: [], children: children)
|
|
// }
|
|
|
|
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
|
|
}
|
|
}
|