feat(ActionExtension): Implement Open in Search as Fallback
This commit is contained in:
parent
89c808ea11
commit
68fe3cb8f2
|
@ -242,41 +242,56 @@ extension SceneDelegate {
|
|||
|
||||
if !UIApplication.shared.canOpenURL(url) { return }
|
||||
|
||||
#if DEBUG
|
||||
print("source application = \(sendingAppID ?? "Unknown")")
|
||||
print("url = \(url)")
|
||||
#endif
|
||||
|
||||
switch url.host {
|
||||
case "post":
|
||||
showComposeViewController()
|
||||
case "profile":
|
||||
let components = url.pathComponents
|
||||
if components.count == 2 && components[0] == "/" {
|
||||
let addr = components[1]
|
||||
if let authContext = coordinator?.authContext {
|
||||
let profileViewModel = RemoteProfileViewModel(
|
||||
context: AppContext.shared,
|
||||
authContext: authContext,
|
||||
acct: components[1]
|
||||
)
|
||||
self.coordinator?.present(
|
||||
scene: .profile(viewModel: profileViewModel),
|
||||
from: nil,
|
||||
transition: .show
|
||||
)
|
||||
}
|
||||
}
|
||||
guard
|
||||
components.count == 2,
|
||||
components[0] == "/",
|
||||
let authContext = coordinator?.authContext
|
||||
else { return }
|
||||
|
||||
let profileViewModel = RemoteProfileViewModel(
|
||||
context: AppContext.shared,
|
||||
authContext: authContext,
|
||||
acct: components[1]
|
||||
)
|
||||
self.coordinator?.present(
|
||||
scene: .profile(viewModel: profileViewModel),
|
||||
from: nil,
|
||||
transition: .show
|
||||
)
|
||||
case "status":
|
||||
let components = url.pathComponents
|
||||
if components.count == 2 && components[0] == "/" {
|
||||
let statusId = components[1]
|
||||
// View post from user
|
||||
if let authContext = coordinator?.authContext {
|
||||
let threadViewModel = RemoteThreadViewModel(context: AppContext.shared,
|
||||
authContext: authContext,
|
||||
statusID: statusId)
|
||||
coordinator?.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show)
|
||||
}
|
||||
}
|
||||
guard
|
||||
components.count == 2,
|
||||
components[0] == "/",
|
||||
let authContext = coordinator?.authContext
|
||||
else { return }
|
||||
let statusId = components[1]
|
||||
// View post from user
|
||||
let threadViewModel = RemoteThreadViewModel(
|
||||
context: AppContext.shared,
|
||||
authContext: authContext,
|
||||
statusID: statusId
|
||||
)
|
||||
coordinator?.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show)
|
||||
case "search":
|
||||
let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems
|
||||
guard
|
||||
let authContext = coordinator?.authContext,
|
||||
let searchQuery = queryItems?.first(where: { $0.name == "query" })?.value
|
||||
else { return }
|
||||
|
||||
let viewModel = SearchDetailViewModel(authContext: authContext, initialSearchText: searchQuery)
|
||||
coordinator?.present(scene: .searchDetail(viewModel: viewModel), from: nil, transition: .show)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
|
|
@ -10,25 +10,16 @@ var Action = function() {};
|
|||
Action.prototype = {
|
||||
|
||||
run: function(arguments) {
|
||||
|
||||
var username = detectUsername()
|
||||
|
||||
if (username) {
|
||||
arguments.completionFunction({ "username" : username })
|
||||
var payload = {
|
||||
"username": detectUsername(),
|
||||
"url": document.documentURI
|
||||
}
|
||||
|
||||
|
||||
arguments.completionFunction(payload)
|
||||
},
|
||||
|
||||
finalize: function(arguments) {
|
||||
|
||||
var openURL = arguments["openURL"]
|
||||
var error = arguments["error"]
|
||||
|
||||
if (error) {
|
||||
alert(error)
|
||||
} else if (openURL) {
|
||||
window.location = openURL
|
||||
}
|
||||
window.location = arguments["openURL"]
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -39,12 +30,13 @@ function detectUsername() {
|
|||
if (typeof uriUsername === "Array") {
|
||||
return uriUsername[0]
|
||||
}
|
||||
|
||||
var querySelector = document.head.querySelector('[property="profile:username"]')
|
||||
if (typeof querySelector === "Object") {
|
||||
return querySelector.content
|
||||
}
|
||||
|
||||
return document.head.querySelector('[property="profile:username"]').content
|
||||
return undefined
|
||||
}
|
||||
|
||||
function detectPost() {
|
||||
|
||||
}
|
||||
|
||||
var ExtensionPreprocessingJS = new Action
|
||||
|
|
|
@ -16,47 +16,56 @@ class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
|
|||
func beginRequest(with context: NSExtensionContext) {
|
||||
// Do not call super in an Action extension with no user interface
|
||||
self.extensionContext = context
|
||||
|
||||
guard
|
||||
let itemProvider = context.inputItems
|
||||
.compactMap({ $0 as? NSExtensionItem })
|
||||
.reduce([NSItemProvider](), { partialResult, acc in
|
||||
var nextResult = partialResult
|
||||
nextResult += acc.attachments ?? []
|
||||
return nextResult
|
||||
})
|
||||
.filter({ $0.hasItemConformingToTypeIdentifier(UTType.propertyList.identifier) })
|
||||
.first
|
||||
else {
|
||||
return self.completeWithNotFoundError()
|
||||
|
||||
let itemProvider = context.inputItems
|
||||
.compactMap({ $0 as? NSExtensionItem })
|
||||
.reduce([NSItemProvider](), { partialResult, acc in
|
||||
var nextResult = partialResult
|
||||
nextResult += acc.attachments ?? []
|
||||
return nextResult
|
||||
})
|
||||
.filter({ $0.hasItemConformingToTypeIdentifier(UTType.propertyList.identifier) })
|
||||
.first
|
||||
|
||||
guard let itemProvider = itemProvider else {
|
||||
return doneWithResults(nil)
|
||||
}
|
||||
|
||||
itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier, options: nil, completionHandler: { (item, error) in
|
||||
guard
|
||||
let dictionary = item as? [String: Any],
|
||||
let results = dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as? [String: Any]? ?? [:]
|
||||
else {
|
||||
return self.completeWithNotFoundError()
|
||||
}
|
||||
|
||||
itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier, options: nil, completionHandler: { [weak self] item, error in
|
||||
DispatchQueue.main.async {
|
||||
self.completeWithOpenUserProfile(results)
|
||||
guard
|
||||
let dictionary = item as? NSDictionary,
|
||||
let results = dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as? NSDictionary
|
||||
else {
|
||||
self?.doneWithResults(nil)
|
||||
return
|
||||
}
|
||||
|
||||
if let username = results["username"] as? String {
|
||||
self?.completeWithOpenUserProfile(username)
|
||||
} else if let url = results["url"] as? String {
|
||||
self?.completeWithSearch(url)
|
||||
} else {
|
||||
self?.doneWithResults(nil)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private extension ActionRequestHandler {
|
||||
func completeWithOpenUserProfile(_ results: [String: Any]) {
|
||||
guard let username = results["username"] as? String else { return }
|
||||
func completeWithOpenUserProfile(_ username: String) {
|
||||
doneWithResults([
|
||||
"openURL": "mastodon://profile/\(username)"
|
||||
])
|
||||
}
|
||||
|
||||
func completeWithNotFoundError() {
|
||||
func completeWithSearch(_ query: String) {
|
||||
guard let query = query.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
|
||||
return doneWithResults(nil)
|
||||
}
|
||||
doneWithResults(
|
||||
["error": "Failed to find username. Are you sure this is a Mastodon Profile page?"]
|
||||
["openURL": "mastodon://search?query=\(query)"]
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue