168 lines
7.1 KiB
Swift
168 lines
7.1 KiB
Swift
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
|
|
|
import UIKit
|
|
import MastodonCore
|
|
import MastodonSDK
|
|
import MastodonLocalization
|
|
|
|
class SearchResultOverviewCoordinator: Coordinator {
|
|
|
|
let overviewViewController: SearchResultsOverviewTableViewController
|
|
let sceneCoordinator: SceneCoordinator
|
|
let context: AppContext
|
|
let authContext: AuthContext
|
|
|
|
var activeTask: Task<Void, Never>?
|
|
|
|
init(appContext: AppContext, authContext: AuthContext, sceneCoordinator: SceneCoordinator) {
|
|
self.sceneCoordinator = sceneCoordinator
|
|
self.context = appContext
|
|
self.authContext = authContext
|
|
|
|
overviewViewController = SearchResultsOverviewTableViewController(appContext: appContext, authContext: authContext, sceneCoordinator: sceneCoordinator)
|
|
}
|
|
|
|
func start() {
|
|
overviewViewController.delegate = self
|
|
}
|
|
}
|
|
|
|
extension SearchResultOverviewCoordinator: SearchResultsOverviewTableViewControllerDelegate {
|
|
@MainActor
|
|
func searchForPosts(_ viewController: SearchResultsOverviewTableViewController, withSearchText searchText: String) {
|
|
let searchResultViewModel = SearchResultViewModel(context: context, authContext: authContext, searchScope: .posts, searchText: searchText)
|
|
|
|
sceneCoordinator.present(scene: .searchResult(viewModel: searchResultViewModel), transition: .show)
|
|
}
|
|
|
|
func showPosts(_ viewController: SearchResultsOverviewTableViewController, tag: Mastodon.Entity.Tag) {
|
|
Task {
|
|
await DataSourceFacade.coordinateToHashtagScene(
|
|
provider: viewController,
|
|
tag: tag
|
|
)
|
|
|
|
await DataSourceFacade.responseToCreateSearchHistory(provider: viewController,
|
|
item: .hashtag(tag: .entity(tag)))
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
func searchForPeople(_ viewController: SearchResultsOverviewTableViewController, withName searchText: String) {
|
|
let searchResultViewModel = SearchResultViewModel(context: context, authContext: authContext, searchScope: .people, searchText: searchText)
|
|
|
|
sceneCoordinator.present(scene: .searchResult(viewModel: searchResultViewModel), transition: .show)
|
|
}
|
|
|
|
func goTo(_ viewController: SearchResultsOverviewTableViewController, urlString: String) {
|
|
|
|
let query = Mastodon.API.V2.Search.Query(
|
|
q: urlString,
|
|
type: .default,
|
|
resolve: true
|
|
)
|
|
|
|
let authContext = self.authContext
|
|
let managedObjectContext = context.managedObjectContext
|
|
|
|
Task {
|
|
let searchResult = try await context.apiService.search(
|
|
query: query,
|
|
authenticationBox: authContext.mastodonAuthenticationBox
|
|
).value
|
|
|
|
if let account = searchResult.accounts.first {
|
|
showProfile(viewController, for: account)
|
|
} else if let status = searchResult.statuses.first {
|
|
|
|
let status = try await managedObjectContext.perform {
|
|
return Persistence.Status.fetch(in: managedObjectContext, context: Persistence.Status.PersistContext(
|
|
domain: authContext.mastodonAuthenticationBox.domain,
|
|
entity: status,
|
|
me: authContext.mastodonAuthenticationBox.authentication.user(in: managedObjectContext),
|
|
statusCache: nil,
|
|
userCache: nil,
|
|
networkDate: Date()))
|
|
}
|
|
|
|
guard let status else { return }
|
|
|
|
await DataSourceFacade.coordinateToStatusThreadScene(
|
|
provider: viewController,
|
|
target: .status, // remove reblog wrapper
|
|
status: status.asRecord
|
|
)
|
|
} else if let url = URL(string: urlString) {
|
|
let prefixedURL: URL?
|
|
if var components = URLComponents(url: url, resolvingAgainstBaseURL: false) {
|
|
if components.scheme == nil {
|
|
components.scheme = "https"
|
|
}
|
|
prefixedURL = components.url
|
|
} else {
|
|
prefixedURL = url
|
|
}
|
|
|
|
guard let prefixedURL else { return }
|
|
|
|
await sceneCoordinator.present(scene: .safari(url: prefixedURL), transition: .safariPresent(animated: true))
|
|
}
|
|
}
|
|
}
|
|
|
|
func showProfile(_ viewController: SearchResultsOverviewTableViewController, for account: Mastodon.Entity.Account) {
|
|
let managedObjectContext = context.managedObjectContext
|
|
let domain = authContext.mastodonAuthenticationBox.domain
|
|
|
|
Task {
|
|
let user = try await managedObjectContext.perform {
|
|
return Persistence.MastodonUser.fetch(in: managedObjectContext,
|
|
context: Persistence.MastodonUser.PersistContext(
|
|
domain: domain,
|
|
entity: account,
|
|
cache: nil,
|
|
networkDate: Date()
|
|
))
|
|
}
|
|
|
|
if let user {
|
|
await DataSourceFacade.coordinateToProfileScene(provider: viewController,
|
|
user: user.asRecord)
|
|
|
|
await DataSourceFacade.responseToCreateSearchHistory(provider: viewController,
|
|
item: .user(record: user.asRecord))
|
|
}
|
|
}
|
|
}
|
|
|
|
func searchForPerson(_ viewController: SearchResultsOverviewTableViewController, username: String, domain: String) {
|
|
let acct = "\(username)@\(domain)"
|
|
let query = Mastodon.API.V2.Search.Query(
|
|
q: acct,
|
|
type: .accounts,
|
|
resolve: true
|
|
)
|
|
|
|
Task {
|
|
let searchResult = try await context.apiService.search(
|
|
query: query,
|
|
authenticationBox: authContext.mastodonAuthenticationBox
|
|
).value
|
|
|
|
if let account = searchResult.accounts.first(where: { $0.acctWithDomainIfMissing(domain).lowercased() == acct.lowercased() }) {
|
|
showProfile(viewController, for: account)
|
|
} else {
|
|
await MainActor.run {
|
|
let alertTitle = L10n.Scene.Search.Searching.NoUser.title
|
|
let alertMessage = L10n.Scene.Search.Searching.NoUser.message(username, domain)
|
|
|
|
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
|
|
let okAction = UIAlertAction(title: L10n.Common.Controls.Actions.ok, style: .default)
|
|
alertController.addAction(okAction)
|
|
sceneCoordinator.present(scene: .alertController(alertController: alertController), transition: .alertController(animated: true))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|