mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2024-12-23 23:46:56 +01:00
Improve "Open in Mastodon" by using Search API (#888)
* feat(ActionExtension): Improve "Open in Mastodon" by using Search aPI * Add code comment
This commit is contained in:
parent
8e7d115944
commit
3ec9e603df
@ -573,6 +573,7 @@
|
||||
27D701F4292FC2D60031BCBB /* DataSourceFacade+URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+URL.swift"; sourceTree = "<group>"; };
|
||||
2A1FE47B2938BB2600784BF1 /* FollowedTagsViewModel+DiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FollowedTagsViewModel+DiffableDataSource.swift"; sourceTree = "<group>"; };
|
||||
2A1FE47D2938C11200784BF1 /* Collection+IsNotEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+IsNotEmpty.swift"; sourceTree = "<group>"; };
|
||||
2A33625329759B4200481A90 /* OpenInActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OpenInActionExtension.entitlements; sourceTree = "<group>"; };
|
||||
2A3F6FE2292ECB5E002E6DA7 /* FollowedTagsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowedTagsViewModel.swift; sourceTree = "<group>"; };
|
||||
2A3F6FE4292F6E44002E6DA7 /* FollowedTagsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowedTagsTableViewCell.swift; sourceTree = "<group>"; };
|
||||
2A506CF3292CD85800059C37 /* FollowedTagsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FollowedTagsViewController.swift; sourceTree = "<group>"; };
|
||||
@ -1333,6 +1334,7 @@
|
||||
2A71F53C296DBDA80049F54A /* OpenInActionExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2A33625329759B4200481A90 /* OpenInActionExtension.entitlements */,
|
||||
2A71F53D296DBDA80049F54A /* Media.xcassets */,
|
||||
2A71F53E296DBDA80049F54A /* Action.js */,
|
||||
2A71F53F296DBDA80049F54A /* ActionRequestHandler.swift */,
|
||||
@ -3939,6 +3941,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = Icon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@ -3969,6 +3972,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = Icon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@ -3998,6 +4002,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = Icon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@ -4027,6 +4032,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = Icon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
|
@ -8,40 +8,23 @@
|
||||
var Action = function() {};
|
||||
|
||||
Action.prototype = {
|
||||
|
||||
run: function(arguments) {
|
||||
var payload = {
|
||||
"username": detectUsername(),
|
||||
"url": document.documentURI
|
||||
}
|
||||
|
||||
arguments.completionFunction(payload)
|
||||
},
|
||||
|
||||
finalize: function(arguments) {
|
||||
let alertMessage = arguments["alert"]
|
||||
const alertMessage = arguments["alert"]
|
||||
const openURL = arguments["openURL"]
|
||||
|
||||
if (alertMessage) {
|
||||
alert(alertMessage)
|
||||
} else {
|
||||
window.location = arguments["openURL"]
|
||||
} else if (openURL) {
|
||||
window.location = openURL
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function detectUsername() {
|
||||
var uriUsername = document.documentURI.match("(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))")
|
||||
|
||||
if (Array.isArray(uriUsername)) {
|
||||
return uriUsername[0]
|
||||
}
|
||||
|
||||
var querySelector = document.head.querySelector('[property="profile:username"]')
|
||||
if (querySelector !== null && typeof querySelector === "object") {
|
||||
return querySelector.content
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
var ExtensionPreprocessingJS = new Action
|
||||
|
@ -9,6 +9,7 @@ import Combine
|
||||
import UIKit
|
||||
import MobileCoreServices
|
||||
import UniformTypeIdentifiers
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
import MastodonLocalization
|
||||
|
||||
@ -16,6 +17,11 @@ class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
|
||||
var extensionContext: NSExtensionContext?
|
||||
var cancellables = [AnyCancellable]()
|
||||
|
||||
/// Capturing a static shared instance of AppContext here as otherwise there
|
||||
/// will be lifecycle issues and we don't want to keep multiple AppContexts around
|
||||
/// in case there another Action Extension process is spawned
|
||||
private static let appContext = AppContext()
|
||||
|
||||
func beginRequest(with context: NSExtensionContext) {
|
||||
// Do not call super in an Action extension with no user interface
|
||||
self.extensionContext = context
|
||||
@ -44,10 +50,8 @@ class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
|
||||
return
|
||||
}
|
||||
|
||||
if let username = results["username"] as? String {
|
||||
self?.completeWithOpenUserProfile(username)
|
||||
} else if let url = results["url"] as? String {
|
||||
self?.continueWithSearch(url)
|
||||
if let url = results["url"] as? String {
|
||||
self?.performSearch(for: url)
|
||||
} else {
|
||||
self?.doneWithInvalidLink()
|
||||
}
|
||||
@ -56,13 +60,53 @@ class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
|
||||
}
|
||||
}
|
||||
|
||||
// Search API
|
||||
private extension ActionRequestHandler {
|
||||
func completeWithOpenUserProfile(_ username: String) {
|
||||
doneWithResults([
|
||||
"openURL": "mastodon://profile/\(username)"
|
||||
])
|
||||
func performSearch(for url: String) {
|
||||
guard
|
||||
let activeAuthenticationBox = Self.appContext
|
||||
.authenticationService
|
||||
.mastodonAuthenticationBoxes
|
||||
.first
|
||||
else {
|
||||
return doneWithResults(nil)
|
||||
}
|
||||
|
||||
Mastodon.API
|
||||
.V2
|
||||
.Search
|
||||
.search(
|
||||
session: .shared,
|
||||
domain: activeAuthenticationBox.domain,
|
||||
query: .init(q: url, resolve: true),
|
||||
authorization: activeAuthenticationBox.userAuthorization
|
||||
)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { completion in
|
||||
// no-op
|
||||
} receiveValue: { [weak self] result in
|
||||
let value = result.value
|
||||
if let foundAccount = value.accounts.first {
|
||||
self?.doneWithResults([
|
||||
"openURL": "mastodon://profile/\(foundAccount.acct)"
|
||||
])
|
||||
} else if let foundStatus = value.statuses.first {
|
||||
self?.doneWithResults([
|
||||
"openURL": "mastodon://status/\(foundStatus.id)"
|
||||
])
|
||||
} else if let foundHashtag = value.hashtags.first {
|
||||
self?.continueWithSearch(foundHashtag.name)
|
||||
} else {
|
||||
self?.continueWithSearch(url)
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Fallback to In-App Search
|
||||
private extension ActionRequestHandler {
|
||||
func continueWithSearch(_ query: String) {
|
||||
guard
|
||||
let url = URL(string: query),
|
||||
@ -95,7 +139,10 @@ private extension ActionRequestHandler {
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Action response handling
|
||||
private extension ActionRequestHandler {
|
||||
func doneWithInvalidLink() {
|
||||
doneWithResults(["alert": L10n.Extension.OpenIn.invalidLinkError])
|
||||
}
|
||||
|
10
OpenInActionExtension/OpenInActionExtension.entitlements
Normal file
10
OpenInActionExtension/OpenInActionExtension.entitlements
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.org.joinmastodon.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
Loading…
Reference in New Issue
Block a user