From 4378c1e97109d1fd2f1021affb06db35bc4549e6 Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Sun, 17 Sep 2023 16:57:15 +0200 Subject: [PATCH] Go to link (IOS-141) It's either a profile (then show the profile) or a status (than show the status) or a link (then open the link in safari) --- ...chResultsOverviewTableViewController.swift | 54 +++++++++++++++++-- .../Sources/MastodonSDK/Extension/URL.swift | 11 ++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/Mastodon/Scene/Search/SearchDetail/Search Results Overview/SearchResultsOverviewTableViewController.swift b/Mastodon/Scene/Search/SearchDetail/Search Results Overview/SearchResultsOverviewTableViewController.swift index a90fb747a..173be218e 100644 --- a/Mastodon/Scene/Search/SearchDetail/Search Results Overview/SearchResultsOverviewTableViewController.swift +++ b/Mastodon/Scene/Search/SearchDetail/Search Results Overview/SearchResultsOverviewTableViewController.swift @@ -118,7 +118,6 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc } func showStandardSearch(for searchText: String) { - guard let dataSource else { return } var snapshot = dataSource.snapshot() @@ -127,8 +126,7 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc .default(.people(searchText)), .default(.profile(searchText, authContext.mastodonAuthenticationBox.domain))], toSection: .default) - if URL(string: searchText) != nil { - //TODO: Check if Mastodon-URL + if URL(string: searchText)?.isValidURL() ?? false { snapshot.appendItems([.default(.openLink(searchText))], toSection: .default) } @@ -188,6 +186,8 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc activeTask = searchTask } + //MARK: - Actions + func showPosts(tag: Mastodon.Entity.Tag) { Task { await DataSourceFacade.coordinateToHashtagScene( @@ -268,6 +268,50 @@ class SearchResultsOverviewTableViewController: UIViewController, NeedsDependenc } } } + + func goTo(link: String) { + + let query = Mastodon.API.V2.Search.Query( + q: link, + 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(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.authenticationRecord.object(in: managedObjectContext)?.user, + statusCache: nil, + userCache: nil, + networkDate: Date())) + } + + guard let status else { return } + + await DataSourceFacade.coordinateToStatusThreadScene( + provider: self, + target: .status, // remove reblog wrapper + status: status.asRecord + ) + } else if let url = URL(string: link) { + coordinator.present(scene: .safari(url: url), transition: .safariPresent(animated: true)) + } + } + } } //MARK: UITableViewDelegate @@ -288,8 +332,8 @@ extension SearchResultsOverviewTableViewController: UITableViewDelegate { searchForPeople(withName: searchText) case .profile(let username, let domain): searchForPerson(username: username, domain: domain) - case .openLink(let string): - delegate?.openLink(self) + case .openLink(let urlString): + goTo(link: urlString) } case .suggestion(let suggestionSectionEntry): switch suggestionSectionEntry { diff --git a/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift b/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift index a9345c7b3..5675fc8c5 100644 --- a/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift +++ b/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift @@ -11,4 +11,15 @@ extension URL { public static func httpScheme(domain: String) -> String { return domain.hasSuffix(".onion") ? "http" : "https" } + + // inspired by https://stackoverflow.com/a/49072718 + public func isValidURL() -> Bool { + if let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue), + let match = detector.firstMatch(in: absoluteString, options: [], range: NSRange(location: 0, length: absoluteString.utf16.count)) { + // it is a link, if the match covers the whole string + return match.range.length == absoluteString.utf16.count + } else { + return false + } + } }