mirror of
https://github.com/Dimillian/IceCubesApp.git
synced 2024-11-22 00:11:00 +00:00
Action extension that would open a deep link in the app (#423)
* Early version of an action that would open a deeplink in the app * Extend routeur support + catch deeplinks * Cleaning extension code, using what local packages has to offer * Removed useless stuff from the extension * Added action icon ; Thanks Dall-E for the icon * Added the action name within a localizable file * Fix routeur --------- Co-authored-by: Thomas Ricouard <ricouard77@gmail.com>
This commit is contained in:
parent
ea3f3882c6
commit
8cac9df8c6
10 changed files with 390 additions and 0 deletions
22
IceCubesActionExtension/Action.js
Normal file
22
IceCubesActionExtension/Action.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
//
|
||||||
|
// Action.js
|
||||||
|
// IceCubesActionExtension
|
||||||
|
//
|
||||||
|
// Created by Thomas Durand on 26/01/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
var Action = function() {};
|
||||||
|
|
||||||
|
Action.prototype = {
|
||||||
|
run: function(arguments) {
|
||||||
|
arguments.completionFunction({ "url" : document.URL })
|
||||||
|
},
|
||||||
|
finalize: function(arguments) {
|
||||||
|
var openingUrl = arguments["deeplink"]
|
||||||
|
if (openingUrl) {
|
||||||
|
document.location.href = openingUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ExtensionPreprocessingJS = new Action
|
104
IceCubesActionExtension/ActionRequestHandler.swift
Normal file
104
IceCubesActionExtension/ActionRequestHandler.swift
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
//
|
||||||
|
// ActionRequestHandler.swift
|
||||||
|
// IceCubesActionExtension
|
||||||
|
//
|
||||||
|
// Created by Thomas Durand on 26/01/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
|
import Models
|
||||||
|
import Network
|
||||||
|
|
||||||
|
// Sample code was sending this from a thread to another, let asume @Sendable for this
|
||||||
|
extension NSExtensionContext: @unchecked Sendable { }
|
||||||
|
|
||||||
|
class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
|
||||||
|
enum Error: Swift.Error {
|
||||||
|
case inputProviderNotFound
|
||||||
|
case loadedItemHasWrongType
|
||||||
|
case urlNotFound
|
||||||
|
case noHost
|
||||||
|
case notMastodonInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
func beginRequest(with context: NSExtensionContext) {
|
||||||
|
// Do not call super in an Action extension with no user interface
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
let url = try await url(from: context)
|
||||||
|
guard await url.isMastodonInstance else {
|
||||||
|
throw Error.notMastodonInstance
|
||||||
|
}
|
||||||
|
await MainActor.run {
|
||||||
|
let deeplink = url.iceCubesAppDeepLink
|
||||||
|
let output = output(wrapping: deeplink)
|
||||||
|
context.completeRequest(returningItems: output)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
await MainActor.run {
|
||||||
|
context.completeRequest(returningItems: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
var isMastodonInstance: Bool {
|
||||||
|
get async {
|
||||||
|
do {
|
||||||
|
guard let host = host() else {
|
||||||
|
throw ActionRequestHandler.Error.noHost
|
||||||
|
}
|
||||||
|
let _: Instance = try await Client(server: host).get(endpoint: Instances.instance)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var iceCubesAppDeepLink: URL {
|
||||||
|
var components = URLComponents(url: self, resolvingAgainstBaseURL: false)!
|
||||||
|
components.scheme = AppInfo.scheme.trimmingCharacters(in: [":", "/"])
|
||||||
|
return components.url!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ActionRequestHandler {
|
||||||
|
/// Will look for an input item that might provide the property list that Javascript sent us
|
||||||
|
private func url(from context: NSExtensionContext) async throws -> URL {
|
||||||
|
for item in context.inputItems as! [NSExtensionItem] {
|
||||||
|
guard let attachments = item.attachments else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for itemProvider in attachments {
|
||||||
|
guard itemProvider.hasItemConformingToTypeIdentifier(UTType.propertyList.identifier) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
guard let dictionary = try await itemProvider.loadItem(forTypeIdentifier: UTType.propertyList.identifier) as? [String: Any] else {
|
||||||
|
throw Error.loadedItemHasWrongType
|
||||||
|
}
|
||||||
|
let input = dictionary[NSExtensionJavaScriptPreprocessingResultsKey] as! [String: Any]? ?? [:]
|
||||||
|
guard let absoluteStringUrl = input["url"] as? String, let url = URL(string: absoluteStringUrl) else {
|
||||||
|
throw Error.urlNotFound
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw Error.inputProviderNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrap the output to the expected object so we send back results to JS
|
||||||
|
private func output(wrapping deeplink: URL) -> [NSExtensionItem] {
|
||||||
|
let results = ["deeplink": deeplink.absoluteString]
|
||||||
|
let dictionary = [NSExtensionJavaScriptFinalizeArgumentKey: results]
|
||||||
|
let provider = NSItemProvider(item: dictionary as NSDictionary, typeIdentifier: UTType.propertyList.identifier)
|
||||||
|
let item = NSExtensionItem()
|
||||||
|
item.attachments = [provider]
|
||||||
|
return [item]
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ActionIcon1024.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
6
IceCubesActionExtension/Assets.xcassets/Contents.json
Normal file
6
IceCubesActionExtension/Assets.xcassets/Contents.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
33
IceCubesActionExtension/Info.plist
Normal file
33
IceCubesActionExtension/Info.plist
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?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>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationRule</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationSupportsFileWithMaxCount</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
<key>NSExtensionActivationSupportsText</key>
|
||||||
|
<false/>
|
||||||
|
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionJavaScriptPreprocessingFile</key>
|
||||||
|
<string>Action</string>
|
||||||
|
<key>NSExtensionServiceFinderPreviewIconName</key>
|
||||||
|
<string>NSActionTemplate</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.services</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).ActionRequestHandler</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
9
IceCubesActionExtension/en.lproj/InfoPlist.strings
Normal file
9
IceCubesActionExtension/en.lproj/InfoPlist.strings
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
InfoPlist.strings
|
||||||
|
IceCubesApp
|
||||||
|
|
||||||
|
Created by Thomas Durand on 27/01/2023.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
"CFBundleDisplayName" = "Open in Ice Cubes";
|
|
@ -74,7 +74,15 @@
|
||||||
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE151A5293C90F900E9683D /* IconSelectorView.swift */; };
|
9FE151A6293C90F900E9683D /* IconSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FE151A5293C90F900E9683D /* IconSelectorView.swift */; };
|
||||||
9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; };
|
9FE3DB57296FEFCA00628CB0 /* AppAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 9FE3DB56296FEFCA00628CB0 /* AppAccount */; };
|
||||||
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */; };
|
C9B22677297F6C2E001F9EFE /* ContentSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */; };
|
||||||
|
E92817FA298443D600875FD1 /* Models in Frameworks */ = {isa = PBXBuildFile; productRef = E92817F9298443D600875FD1 /* Models */; };
|
||||||
|
E92817FC298443D600875FD1 /* Network in Frameworks */ = {isa = PBXBuildFile; productRef = E92817FB298443D600875FD1 /* Network */; };
|
||||||
|
E92817FE29844DB700875FD1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E92817FD29844DB700875FD1 /* Assets.xcassets */; };
|
||||||
|
E970C10829845A9400E88A8C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E970C10A29845A9400E88A8C /* InfoPlist.strings */; };
|
||||||
E9B576C329743F4C00BCE646 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E9B576C529743F4C00BCE646 /* Localizable.strings */; };
|
E9B576C329743F4C00BCE646 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E9B576C529743F4C00BCE646 /* Localizable.strings */; };
|
||||||
|
E9DF41FC29830FEC0003AAD2 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */; };
|
||||||
|
E9DF420129830FEC0003AAD2 /* ActionRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9DF420029830FEC0003AAD2 /* ActionRequestHandler.swift */; };
|
||||||
|
E9DF420329830FEC0003AAD2 /* Action.js in Resources */ = {isa = PBXBuildFile; fileRef = E9DF420229830FEC0003AAD2 /* Action.js */; };
|
||||||
|
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -92,6 +100,13 @@
|
||||||
remoteGlobalIDString = 9FAD858729743F7400496AB1;
|
remoteGlobalIDString = 9FAD858729743F7400496AB1;
|
||||||
remoteInfo = IceCubesShareExtension;
|
remoteInfo = IceCubesShareExtension;
|
||||||
};
|
};
|
||||||
|
E9DF420529830FEC0003AAD2 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 9FBFE631292A715500C250E9 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = E9DF41F929830FEC0003AAD2;
|
||||||
|
remoteInfo = IceCubesActionExtension;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
@ -101,6 +116,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
E9DF420729830FEC0003AAD2 /* IceCubesActionExtension.appex in Embed Foundation Extensions */,
|
||||||
9F2A541D296AB631009B2D7C /* IceCubesNotifications.appex in Embed Foundation Extensions */,
|
9F2A541D296AB631009B2D7C /* IceCubesNotifications.appex in Embed Foundation Extensions */,
|
||||||
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */,
|
9FAD859229743F7400496AB1 /* IceCubesShareExtension.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
|
@ -181,8 +197,15 @@
|
||||||
C465A53D297C5E0C00864FB7 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
C465A53D297C5E0C00864FB7 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||||
C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentSettingsView.swift; sourceTree = "<group>"; };
|
C9B22676297F6C2E001F9EFE /* ContentSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentSettingsView.swift; sourceTree = "<group>"; };
|
||||||
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = IceCubesApp.xcconfig; sourceTree = "<group>"; };
|
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = IceCubesApp.xcconfig; sourceTree = "<group>"; };
|
||||||
|
E92817FD29844DB700875FD1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
E970C10929845A9400E88A8C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||||
E9B576C429743F4C00BCE646 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
E9B576C429743F4C00BCE646 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
E9B576CC2974AAAF00BCE646 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
E9B576CC2974AAAF00BCE646 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = IceCubesActionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
|
||||||
|
E9DF420029830FEC0003AAD2 /* ActionRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRequestHandler.swift; sourceTree = "<group>"; };
|
||||||
|
E9DF420229830FEC0003AAD2 /* Action.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Action.js; sourceTree = "<group>"; };
|
||||||
|
E9DF420429830FEC0003AAD2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
F355EEDA297A8BD500E362C0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
F355EEDA297A8BD500E362C0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
@ -236,6 +259,16 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
E9DF41F729830FEC0003AAD2 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E92817FC298443D600875FD1 /* Network in Frameworks */,
|
||||||
|
E92817FA298443D600875FD1 /* Models in Frameworks */,
|
||||||
|
E9DF41FC29830FEC0003AAD2 /* UniformTypeIdentifiers.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
@ -321,6 +354,7 @@
|
||||||
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */,
|
DD31E2E5297FB68B00A4BE29 /* IceCubesApp.xcconfig */,
|
||||||
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */,
|
9F7D939529800B0300EE6B7A /* IceCubesApp-release.xcconfig */,
|
||||||
9FBFE63B292A715500C250E9 /* IceCubesApp */,
|
9FBFE63B292A715500C250E9 /* IceCubesApp */,
|
||||||
|
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */,
|
||||||
9F2A5417296AB631009B2D7C /* IceCubesNotifications */,
|
9F2A5417296AB631009B2D7C /* IceCubesNotifications */,
|
||||||
9FAD858929743F7400496AB1 /* IceCubesShareExtension */,
|
9FAD858929743F7400496AB1 /* IceCubesShareExtension */,
|
||||||
9FBFE63A292A715500C250E9 /* Products */,
|
9FBFE63A292A715500C250E9 /* Products */,
|
||||||
|
@ -346,6 +380,7 @@
|
||||||
9FBFE639292A715500C250E9 /* IceCubesApp.app */,
|
9FBFE639292A715500C250E9 /* IceCubesApp.app */,
|
||||||
9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */,
|
9F2A5416296AB631009B2D7C /* IceCubesNotifications.appex */,
|
||||||
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */,
|
9FAD858829743F7400496AB1 /* IceCubesShareExtension.appex */,
|
||||||
|
E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -370,6 +405,7 @@
|
||||||
9F2A5404296995FB009B2D7C /* QuickLookUI.framework */,
|
9F2A5404296995FB009B2D7C /* QuickLookUI.framework */,
|
||||||
9F7335EE29674F7100AFF0BA /* QuickLook.framework */,
|
9F7335EE29674F7100AFF0BA /* QuickLook.framework */,
|
||||||
9F7335EB2967461B00AFF0BA /* AVKit.framework */,
|
9F7335EB2967461B00AFF0BA /* AVKit.framework */,
|
||||||
|
E9DF41FB29830FEC0003AAD2 /* UniformTypeIdentifiers.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -399,6 +435,18 @@
|
||||||
path = Localization;
|
path = Localization;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E9DF41FD29830FEC0003AAD2 /* IceCubesActionExtension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E9DF420029830FEC0003AAD2 /* ActionRequestHandler.swift */,
|
||||||
|
E9DF420229830FEC0003AAD2 /* Action.js */,
|
||||||
|
E9DF420429830FEC0003AAD2 /* Info.plist */,
|
||||||
|
E92817FD29844DB700875FD1 /* Assets.xcassets */,
|
||||||
|
E970C10A29845A9400E88A8C /* InfoPlist.strings */,
|
||||||
|
);
|
||||||
|
path = IceCubesActionExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
@ -465,6 +513,7 @@
|
||||||
dependencies = (
|
dependencies = (
|
||||||
9F2A541C296AB631009B2D7C /* PBXTargetDependency */,
|
9F2A541C296AB631009B2D7C /* PBXTargetDependency */,
|
||||||
9FAD859129743F7400496AB1 /* PBXTargetDependency */,
|
9FAD859129743F7400496AB1 /* PBXTargetDependency */,
|
||||||
|
E9DF420629830FEC0003AAD2 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = IceCubesApp;
|
name = IceCubesApp;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -487,6 +536,27 @@
|
||||||
productReference = 9FBFE639292A715500C250E9 /* IceCubesApp.app */;
|
productReference = 9FBFE639292A715500C250E9 /* IceCubesApp.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
|
E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = E9DF420A29830FEC0003AAD2 /* Build configuration list for PBXNativeTarget "IceCubesActionExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
E9DF41F629830FEC0003AAD2 /* Sources */,
|
||||||
|
E9DF41F729830FEC0003AAD2 /* Frameworks */,
|
||||||
|
E9DF41F829830FEC0003AAD2 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = IceCubesActionExtension;
|
||||||
|
packageProductDependencies = (
|
||||||
|
E92817F9298443D600875FD1 /* Models */,
|
||||||
|
E92817FB298443D600875FD1 /* Network */,
|
||||||
|
);
|
||||||
|
productName = IceCubesActionExtension;
|
||||||
|
productReference = E9DF41FA29830FEC0003AAD2 /* IceCubesActionExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
|
@ -506,6 +576,9 @@
|
||||||
9FBFE638292A715500C250E9 = {
|
9FBFE638292A715500C250E9 = {
|
||||||
CreatedOnToolsVersion = 14.1;
|
CreatedOnToolsVersion = 14.1;
|
||||||
};
|
};
|
||||||
|
E9DF41F929830FEC0003AAD2 = {
|
||||||
|
CreatedOnToolsVersion = 14.2;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 9FBFE634292A715500C250E9 /* Build configuration list for PBXProject "IceCubesApp" */;
|
buildConfigurationList = 9FBFE634292A715500C250E9 /* Build configuration list for PBXProject "IceCubesApp" */;
|
||||||
|
@ -534,6 +607,7 @@
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
9FBFE638292A715500C250E9 /* IceCubesApp */,
|
9FBFE638292A715500C250E9 /* IceCubesApp */,
|
||||||
|
E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */,
|
||||||
9F2A5415296AB631009B2D7C /* IceCubesNotifications */,
|
9F2A5415296AB631009B2D7C /* IceCubesNotifications */,
|
||||||
9FAD858729743F7400496AB1 /* IceCubesShareExtension */,
|
9FAD858729743F7400496AB1 /* IceCubesShareExtension */,
|
||||||
);
|
);
|
||||||
|
@ -576,6 +650,16 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
E9DF41F829830FEC0003AAD2 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E92817FE29844DB700875FD1 /* Assets.xcassets in Resources */,
|
||||||
|
E970C10829845A9400E88A8C /* InfoPlist.strings in Resources */,
|
||||||
|
E9DF420329830FEC0003AAD2 /* Action.js in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
@ -624,6 +708,14 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
E9DF41F629830FEC0003AAD2 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E9DF420129830FEC0003AAD2 /* ActionRequestHandler.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
@ -639,6 +731,11 @@
|
||||||
target = 9FAD858729743F7400496AB1 /* IceCubesShareExtension */;
|
target = 9FAD858729743F7400496AB1 /* IceCubesShareExtension */;
|
||||||
targetProxy = 9FAD859029743F7400496AB1 /* PBXContainerItemProxy */;
|
targetProxy = 9FAD859029743F7400496AB1 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
E9DF420629830FEC0003AAD2 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = E9DF41F929830FEC0003AAD2 /* IceCubesActionExtension */;
|
||||||
|
targetProxy = E9DF420529830FEC0003AAD2 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
@ -658,6 +755,14 @@
|
||||||
name = Localizable.stringsdict;
|
name = Localizable.stringsdict;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E970C10A29845A9400E88A8C /* InfoPlist.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
E970C10929845A9400E88A8C /* en */,
|
||||||
|
);
|
||||||
|
name = InfoPlist.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E9B576C529743F4C00BCE646 /* Localizable.strings */ = {
|
E9B576C529743F4C00BCE646 /* Localizable.strings */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1018,6 +1123,69 @@
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
E9DF420829830FEC0003AAD2 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = ActionIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 730;
|
||||||
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = IceCubesActionExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Open in Ice Cube";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.1;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
E9DF420929830FEC0003AAD2 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = ActionIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "-";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
|
||||||
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 730;
|
||||||
|
DEVELOPMENT_TEAM = "$(DEVELOPMENT_TEAM)";
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = IceCubesActionExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "Open in Ice Cube";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.1;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.1;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_PREFIX).IceCubesApp.IceCubesActionExtension";
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
@ -1057,6 +1225,15 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
E9DF420A29830FEC0003AAD2 /* Build configuration list for PBXNativeTarget "IceCubesActionExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
E9DF420829830FEC0003AAD2 /* Debug */,
|
||||||
|
E9DF420929830FEC0003AAD2 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
@ -1184,6 +1361,14 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = AppAccount;
|
productName = AppAccount;
|
||||||
};
|
};
|
||||||
|
E92817F9298443D600875FD1 /* Models */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Models;
|
||||||
|
};
|
||||||
|
E92817FB298443D600875FD1 /* Network */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Network;
|
||||||
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 9FBFE631292A715500C250E9 /* Project object */;
|
rootObject = 9FBFE631292A715500C250E9 /* Project object */;
|
||||||
|
|
|
@ -19,8 +19,15 @@ private struct SafariRouter: ViewModifier {
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
content
|
content
|
||||||
.environment(\.openURL, OpenURLAction { url in
|
.environment(\.openURL, OpenURLAction { url in
|
||||||
|
// Open internal URL.
|
||||||
routerPath.handle(url: url)
|
routerPath.handle(url: url)
|
||||||
})
|
})
|
||||||
|
.onOpenURL(perform: { url in
|
||||||
|
// Open external URL (from icecubesapp://)
|
||||||
|
let urlString = url.absoluteString.replacingOccurrences(of: "icecubesapp://", with: "https://")
|
||||||
|
guard let url = URL(string: urlString) else { return }
|
||||||
|
_ = routerPath.handle(url: url)
|
||||||
|
})
|
||||||
.onAppear {
|
.onAppear {
|
||||||
routerPath.urlHandler = { url in
|
routerPath.urlHandler = { url in
|
||||||
if url.absoluteString.contains("@twitter.com"), url.absoluteString.hasPrefix("mailto:") {
|
if url.absoluteString.contains("@twitter.com"), url.absoluteString.hasPrefix("mailto:") {
|
||||||
|
|
|
@ -107,6 +107,16 @@ public class RouterPath: ObservableObject {
|
||||||
await navigateToAccountFrom(acct: acct, url: url)
|
await navigateToAccountFrom(acct: acct, url: url)
|
||||||
}
|
}
|
||||||
return .handled
|
return .handled
|
||||||
|
} else if let client = client,
|
||||||
|
client.isAuth,
|
||||||
|
client.hasConnection(with: url),
|
||||||
|
let id = Int(url.lastPathComponent) {
|
||||||
|
if url.absoluteString.contains(client.server) {
|
||||||
|
navigate(to: .statusDetail(id: String(id)))
|
||||||
|
} else {
|
||||||
|
navigate(to: .remoteStatusDetail(url: url))
|
||||||
|
}
|
||||||
|
return .handled
|
||||||
}
|
}
|
||||||
return urlHandler?(url) ?? .systemAction
|
return urlHandler?(url) ?? .systemAction
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue