Add Open in Tusker action extension
This commit is contained in:
parent
47fb0ea868
commit
18ce21c2c6
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// Action.js
|
||||||
|
// OpenInTusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 5/22/21.
|
||||||
|
// Copyright © 2021 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
var Action = function() {};
|
||||||
|
|
||||||
|
Action.prototype = {
|
||||||
|
|
||||||
|
run: function(arguments) {
|
||||||
|
const results = {
|
||||||
|
url: window.location.href,
|
||||||
|
};
|
||||||
|
const el = document.querySelector('link[rel=alternate][type="application/activity+json"]');
|
||||||
|
if (el) {
|
||||||
|
results.activityPubURL = el.href;
|
||||||
|
}
|
||||||
|
arguments.completionFunction(results);
|
||||||
|
},
|
||||||
|
|
||||||
|
finalize: function(arguments) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var ExtensionPreprocessingJS = new Action();
|
|
@ -0,0 +1,100 @@
|
||||||
|
//
|
||||||
|
// ActionViewController.swift
|
||||||
|
// OpenInTusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 5/23/21.
|
||||||
|
// Copyright © 2021 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
|
class ActionViewController: UIViewController {
|
||||||
|
|
||||||
|
@IBOutlet weak var imageView: UIImageView!
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
findURLFromWebPage { (components) in
|
||||||
|
if let components = components {
|
||||||
|
self.searchForURLInApp(components)
|
||||||
|
} else {
|
||||||
|
self.findURLItem { (components) in
|
||||||
|
if let components = components {
|
||||||
|
self.searchForURLInApp(components)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func findURLFromWebPage(completion: @escaping (URLComponents?) -> Void) {
|
||||||
|
for item in extensionContext!.inputItems as! [NSExtensionItem] {
|
||||||
|
for provider in item.attachments! {
|
||||||
|
guard provider.hasItemConformingToTypeIdentifier(kUTTypePropertyList as String) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
provider.loadItem(forTypeIdentifier: kUTTypePropertyList as String, options: nil) { (result, error) in
|
||||||
|
guard let result = result as? [String: Any],
|
||||||
|
let jsResult = result[NSExtensionJavaScriptPreprocessingResultsKey] as? [String: Any],
|
||||||
|
let urlString = jsResult["activityPubURL"] as? String ?? jsResult["url"] as? String,
|
||||||
|
let components = URLComponents(string: urlString) else {
|
||||||
|
completion(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(components)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func findURLItem(completion: @escaping (URLComponents?) -> Void) {
|
||||||
|
for item in extensionContext!.inputItems as! [NSExtensionItem] {
|
||||||
|
for provider in item.attachments! {
|
||||||
|
guard provider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
provider.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil) { (result, error) in
|
||||||
|
guard let result = result as? URL,
|
||||||
|
let components = URLComponents(url: result, resolvingAgainstBaseURL: false) else {
|
||||||
|
completion(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
completion(components)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completion(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func searchForURLInApp(_ components: URLComponents) {
|
||||||
|
var components = components
|
||||||
|
components.scheme = "tusker"
|
||||||
|
self.openURL(components.url!)
|
||||||
|
self.extensionContext!.completeRequest(returningItems: nil, completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func openURL(_ url: URL) {
|
||||||
|
var responder: UIResponder = self
|
||||||
|
while let parent = responder.next {
|
||||||
|
if let application = parent as? UIApplication {
|
||||||
|
application.perform(#selector(openURL(_:)), with: url)
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
responder = parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func done() {
|
||||||
|
extensionContext!.completeRequest(returningItems: nil, completionHandler: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ObA-dk-sSI">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Image-->
|
||||||
|
<scene sceneID="7MM-of-jgj">
|
||||||
|
<objects>
|
||||||
|
<viewController title="Image" id="ObA-dk-sSI" customClass="ActionViewController" customModule="OpenInTusker" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="zMn-AG-sqS">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="528"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<navigationBar contentMode="scaleToFill" horizontalCompressionResistancePriority="751" verticalCompressionResistancePriority="751" translatesAutoresizingMaskIntoConstraints="NO" id="NOA-Dm-cuz">
|
||||||
|
<rect key="frame" x="0.0" y="44" width="320" height="44"/>
|
||||||
|
<items>
|
||||||
|
<navigationItem id="3HJ-uW-3hn">
|
||||||
|
<barButtonItem key="leftBarButtonItem" title="Done" style="done" id="WYi-yp-eM6">
|
||||||
|
<connections>
|
||||||
|
<action selector="done" destination="ObA-dk-sSI" id="Qdu-qn-U6V"/>
|
||||||
|
</connections>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
|
</items>
|
||||||
|
</navigationBar>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Unable to find Mastodon link on this page." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Yho-gp-VyR">
|
||||||
|
<rect key="frame" x="0.0" y="254" width="320" height="20.5"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="VVe-Uw-JpX"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="VVe-Uw-JpX" firstAttribute="trailing" secondItem="NOA-Dm-cuz" secondAttribute="trailing" id="A05-Pj-hrr"/>
|
||||||
|
<constraint firstItem="NOA-Dm-cuz" firstAttribute="leading" secondItem="VVe-Uw-JpX" secondAttribute="leading" id="HxO-8t-aoh"/>
|
||||||
|
<constraint firstItem="Yho-gp-VyR" firstAttribute="centerY" secondItem="zMn-AG-sqS" secondAttribute="centerY" id="R7q-OB-hhA"/>
|
||||||
|
<constraint firstItem="Yho-gp-VyR" firstAttribute="leading" secondItem="VVe-Uw-JpX" secondAttribute="leading" id="TEy-zi-dP7"/>
|
||||||
|
<constraint firstItem="Yho-gp-VyR" firstAttribute="trailing" secondItem="VVe-Uw-JpX" secondAttribute="trailing" id="Uvn-0x-Y6N"/>
|
||||||
|
<constraint firstItem="NOA-Dm-cuz" firstAttribute="top" secondItem="VVe-Uw-JpX" secondAttribute="top" id="we0-1t-bgp"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
|
<size key="freeformSize" width="320" height="528"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="view" destination="zMn-AG-sqS" id="Qma-de-2ek"/>
|
||||||
|
</connections>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="X47-rx-isc" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="-61" y="-57"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<systemColor name="systemBackgroundColor">
|
||||||
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</systemColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?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>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Open in Tusker</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(MARKETING_VERSION)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionJavaScriptPreprocessingFile</key>
|
||||||
|
<string>Action</string>
|
||||||
|
<key>NSExtensionActivationRule</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationSupportsAttachmentsWithMinCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionServiceAllowsFinderPreviewItem</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSExtensionServiceAllowsTouchBarItem</key>
|
||||||
|
<true/>
|
||||||
|
<key>NSExtensionServiceFinderPreviewIconName</key>
|
||||||
|
<string>NSActionTemplate</string>
|
||||||
|
<key>NSExtensionServiceTouchBarBezelColorName</key>
|
||||||
|
<string>TouchBarBezel</string>
|
||||||
|
<key>NSExtensionServiceTouchBarIconName</key>
|
||||||
|
<string>NSActionTemplate</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionMainStoryboard</key>
|
||||||
|
<string>MainInterface</string>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.ui-services</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 900 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,103 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "60x60@2x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "60x60@3x.png",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "76x76@2x.png",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "83.5x83.5@2x.png",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "83.5x83.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "1024x1024@1x.png",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
},
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"color" : {
|
||||||
|
"reference" : "systemPurpleColor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -307,6 +307,11 @@
|
||||||
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
D6DFC69E242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */; };
|
||||||
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */; };
|
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */; };
|
||||||
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
|
||||||
|
D6E343AB265AAD6B00C4AA01 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6E343AA265AAD6B00C4AA01 /* Media.xcassets */; };
|
||||||
|
D6E343AD265AAD6B00C4AA01 /* ActionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E343AC265AAD6B00C4AA01 /* ActionViewController.swift */; };
|
||||||
|
D6E343B0265AAD6B00C4AA01 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6E343AE265AAD6B00C4AA01 /* MainInterface.storyboard */; };
|
||||||
|
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
D6E343BA265AAD8C00C4AA01 /* Action.js in Resources */ = {isa = PBXBuildFile; fileRef = D6E343B9265AAD8C00C4AA01 /* Action.js */; };
|
||||||
D6E4267725327FB400C02E1C /* ComposeAutocompleteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */; };
|
D6E4267725327FB400C02E1C /* ComposeAutocompleteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */; };
|
||||||
D6E4269D2532A3E100C02E1C /* FuzzyMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E4269C2532A3E100C02E1C /* FuzzyMatcher.swift */; };
|
D6E4269D2532A3E100C02E1C /* FuzzyMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E4269C2532A3E100C02E1C /* FuzzyMatcher.swift */; };
|
||||||
D6E426AD25334DA500C02E1C /* FuzzyMatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */; };
|
D6E426AD25334DA500C02E1C /* FuzzyMatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */; };
|
||||||
|
@ -363,9 +368,27 @@
|
||||||
remoteGlobalIDString = D6D4DDCB212518A000E1C4BB;
|
remoteGlobalIDString = D6D4DDCB212518A000E1C4BB;
|
||||||
remoteInfo = Tusker;
|
remoteInfo = Tusker;
|
||||||
};
|
};
|
||||||
|
D6E343B2265AAD6B00C4AA01 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = D6E343A7265AAD6B00C4AA01;
|
||||||
|
remoteInfo = OpenInTusker;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
D6E3438F2659849800C4AA01 /* Embed App Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed App Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed App Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
D6F953E52125197500CF0F2B /* Embed Frameworks */ = {
|
D6F953E52125197500CF0F2B /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -687,6 +710,13 @@
|
||||||
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
D6DFC69D242C490400ACC392 /* TrackpadScrollGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackpadScrollGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||||
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakArray.swift; sourceTree = "<group>"; };
|
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakArray.swift; sourceTree = "<group>"; };
|
||||||
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
|
||||||
|
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OpenInTusker.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D6E343AA265AAD6B00C4AA01 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = "<group>"; };
|
||||||
|
D6E343AC265AAD6B00C4AA01 /* ActionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionViewController.swift; sourceTree = "<group>"; };
|
||||||
|
D6E343AF265AAD6B00C4AA01 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
||||||
|
D6E343B1265AAD6B00C4AA01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
D6E343B5265AAD6B00C4AA01 /* OpenInTusker.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = OpenInTusker.entitlements; sourceTree = "<group>"; };
|
||||||
|
D6E343B9265AAD8C00C4AA01 /* Action.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = Action.js; sourceTree = "<group>"; };
|
||||||
D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAutocompleteView.swift; sourceTree = "<group>"; };
|
D6E4267625327FB400C02E1C /* ComposeAutocompleteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAutocompleteView.swift; sourceTree = "<group>"; };
|
||||||
D6E4269C2532A3E100C02E1C /* FuzzyMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FuzzyMatcher.swift; sourceTree = "<group>"; };
|
D6E4269C2532A3E100C02E1C /* FuzzyMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FuzzyMatcher.swift; sourceTree = "<group>"; };
|
||||||
D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FuzzyMatcherTests.swift; sourceTree = "<group>"; };
|
D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FuzzyMatcherTests.swift; sourceTree = "<group>"; };
|
||||||
|
@ -752,6 +782,13 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D6E343A5265AAD6B00C4AA01 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
@ -1472,6 +1509,7 @@
|
||||||
D6D4DDCE212518A000E1C4BB /* Tusker */,
|
D6D4DDCE212518A000E1C4BB /* Tusker */,
|
||||||
D6D4DDE3212518A200E1C4BB /* TuskerTests */,
|
D6D4DDE3212518A200E1C4BB /* TuskerTests */,
|
||||||
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
||||||
|
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
D6D4DDCD212518A000E1C4BB /* Products */,
|
D6D4DDCD212518A000E1C4BB /* Products */,
|
||||||
D65A37F221472F300087646E /* Frameworks */,
|
D65A37F221472F300087646E /* Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -1485,6 +1523,7 @@
|
||||||
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
||||||
D61099AB2144B0CC00432DC2 /* Pachyderm.framework */,
|
D61099AB2144B0CC00432DC2 /* Pachyderm.framework */,
|
||||||
D61099B32144B0CC00432DC2 /* PachydermTests.xctest */,
|
D61099B32144B0CC00432DC2 /* PachydermTests.xctest */,
|
||||||
|
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1552,6 +1591,19 @@
|
||||||
path = TuskerUITests;
|
path = TuskerUITests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D6E343B5265AAD6B00C4AA01 /* OpenInTusker.entitlements */,
|
||||||
|
D6E343AA265AAD6B00C4AA01 /* Media.xcassets */,
|
||||||
|
D6E343AC265AAD6B00C4AA01 /* ActionViewController.swift */,
|
||||||
|
D6E343AE265AAD6B00C4AA01 /* MainInterface.storyboard */,
|
||||||
|
D6E343B1265AAD6B00C4AA01 /* Info.plist */,
|
||||||
|
D6E343B9265AAD8C00C4AA01 /* Action.js */,
|
||||||
|
);
|
||||||
|
path = OpenInTusker;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D6F1F84E2193B9BE00F5FE67 /* Caching */ = {
|
D6F1F84E2193B9BE00F5FE67 /* Caching */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1642,11 +1694,13 @@
|
||||||
D6D4DDCA212518A000E1C4BB /* Resources */,
|
D6D4DDCA212518A000E1C4BB /* Resources */,
|
||||||
D6F953E52125197500CF0F2B /* Embed Frameworks */,
|
D6F953E52125197500CF0F2B /* Embed Frameworks */,
|
||||||
D65F612C23AE957600F3CFD3 /* Embed debug-only frameworks */,
|
D65F612C23AE957600F3CFD3 /* Embed debug-only frameworks */,
|
||||||
|
D6E3438F2659849800C4AA01 /* Embed App Extensions */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D61099BF2144B0CC00432DC2 /* PBXTargetDependency */,
|
D61099BF2144B0CC00432DC2 /* PBXTargetDependency */,
|
||||||
|
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Tusker;
|
name = Tusker;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -1696,13 +1750,30 @@
|
||||||
productReference = D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */;
|
productReference = D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.ui-testing";
|
productType = "com.apple.product-type.bundle.ui-testing";
|
||||||
};
|
};
|
||||||
|
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = D6E343B6265AAD6B00C4AA01 /* Build configuration list for PBXNativeTarget "OpenInTusker" */;
|
||||||
|
buildPhases = (
|
||||||
|
D6E343A4265AAD6B00C4AA01 /* Sources */,
|
||||||
|
D6E343A5265AAD6B00C4AA01 /* Frameworks */,
|
||||||
|
D6E343A6265AAD6B00C4AA01 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = OpenInTusker;
|
||||||
|
productName = OpenInTusker;
|
||||||
|
productReference = D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
D6D4DDC4212518A000E1C4BB /* Project object */ = {
|
D6D4DDC4212518A000E1C4BB /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1200;
|
LastSwiftUpdateCheck = 1250;
|
||||||
LastUpgradeCheck = 1250;
|
LastUpgradeCheck = 1250;
|
||||||
ORGANIZATIONNAME = Shadowfacts;
|
ORGANIZATIONNAME = Shadowfacts;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
@ -1729,6 +1800,9 @@
|
||||||
LastSwiftMigration = 1020;
|
LastSwiftMigration = 1020;
|
||||||
TestTargetID = D6D4DDCB212518A000E1C4BB;
|
TestTargetID = D6D4DDCB212518A000E1C4BB;
|
||||||
};
|
};
|
||||||
|
D6E343A7265AAD6B00C4AA01 = {
|
||||||
|
CreatedOnToolsVersion = 12.5;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = D6D4DDC7212518A000E1C4BB /* Build configuration list for PBXProject "Tusker" */;
|
buildConfigurationList = D6D4DDC7212518A000E1C4BB /* Build configuration list for PBXProject "Tusker" */;
|
||||||
|
@ -1760,6 +1834,7 @@
|
||||||
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
||||||
D61099AA2144B0CC00432DC2 /* Pachyderm */,
|
D61099AA2144B0CC00432DC2 /* Pachyderm */,
|
||||||
D61099B22144B0CC00432DC2 /* PachydermTests */,
|
D61099B22144B0CC00432DC2 /* PachydermTests */,
|
||||||
|
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
@ -1827,6 +1902,16 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D6E343A6265AAD6B00C4AA01 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D6E343BA265AAD8C00C4AA01 /* Action.js in Resources */,
|
||||||
|
D6E343AB265AAD6B00C4AA01 /* Media.xcassets in Resources */,
|
||||||
|
D6E343B0265AAD6B00C4AA01 /* MainInterface.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
@ -2170,6 +2255,14 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
D6E343A4265AAD6B00C4AA01 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D6E343AD265AAD6B00C4AA01 /* ActionViewController.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
@ -2198,6 +2291,11 @@
|
||||||
target = D6D4DDCB212518A000E1C4BB /* Tusker */;
|
target = D6D4DDCB212518A000E1C4BB /* Tusker */;
|
||||||
targetProxy = D6D4DDEC212518A200E1C4BB /* PBXContainerItemProxy */;
|
targetProxy = D6D4DDEC212518A200E1C4BB /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = D6E343A7265AAD6B00C4AA01 /* OpenInTusker */;
|
||||||
|
targetProxy = D6E343B2265AAD6B00C4AA01 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
@ -2209,6 +2307,14 @@
|
||||||
name = LaunchScreen.storyboard;
|
name = LaunchScreen.storyboard;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D6E343AE265AAD6B00C4AA01 /* MainInterface.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
D6E343AF265AAD6B00C4AA01 /* Base */,
|
||||||
|
);
|
||||||
|
name = MainInterface.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */ = {
|
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2234,6 +2340,7 @@
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = Pachyderm/Info.plist;
|
INFOPLIST_FILE = Pachyderm/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -2264,6 +2371,7 @@
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
INFOPLIST_FILE = Pachyderm/Info.plist;
|
INFOPLIST_FILE = Pachyderm/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -2451,7 +2559,7 @@
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||||
INFOPLIST_FILE = Tusker/Info.plist;
|
INFOPLIST_FILE = Tusker/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.0;
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -2480,7 +2588,7 @@
|
||||||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||||
INFOPLIST_FILE = Tusker/Info.plist;
|
INFOPLIST_FILE = Tusker/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.0;
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
|
@ -2578,6 +2686,60 @@
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
D6E343B7265AAD6B00C4AA01 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
|
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||||
|
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 2021.1;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.OpenInTusker;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2,6";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
D6E343B8265AAD6B00C4AA01 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
|
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||||
|
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 2021.1;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.OpenInTusker;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2,6";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
@ -2635,6 +2797,15 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
D6E343B6265AAD6B00C4AA01 /* Build configuration list for PBXNativeTarget "OpenInTusker" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
D6E343B7265AAD6B00C4AA01 /* Debug */,
|
||||||
|
D6E343B8265AAD6B00C4AA01 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
|
|
|
@ -76,9 +76,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
|
|
||||||
case .newPost:
|
case .newPost:
|
||||||
return "compose"
|
return "compose"
|
||||||
|
|
||||||
default:
|
|
||||||
fatalError("no scene for activity type \(type)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
handlePendingCrashReport(report, session: session)
|
handlePendingCrashReport(report, session: session)
|
||||||
} else {
|
} else {
|
||||||
showAppOrOnboardingUI(session: session)
|
showAppOrOnboardingUI(session: session)
|
||||||
|
if connectionOptions.urlContexts.count > 0 {
|
||||||
|
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window!.makeKeyAndVisible()
|
window!.makeKeyAndVisible()
|
||||||
|
@ -50,20 +53,10 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
if url.host == "x-callback-url" {
|
if url.host == "x-callback-url" {
|
||||||
_ = XCBManager.handle(url: url)
|
_ = XCBManager.handle(url: url)
|
||||||
} else if var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
} else if var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||||
let tabBarController = window!.rootViewController as? MainTabBarViewController,
|
let rootViewController = window!.rootViewController as? TuskerRootViewController {
|
||||||
let exploreNavController = tabBarController.getTabController(tab: .explore) as? UINavigationController,
|
|
||||||
let exploreController = exploreNavController.viewControllers.first as? ExploreViewController {
|
|
||||||
|
|
||||||
tabBarController.select(tab: .explore)
|
|
||||||
exploreNavController.popToRootViewController(animated: false)
|
|
||||||
|
|
||||||
exploreController.loadViewIfNeeded()
|
|
||||||
exploreController.searchController.isActive = true
|
|
||||||
|
|
||||||
components.scheme = "https"
|
components.scheme = "https"
|
||||||
let query = url.absoluteString
|
let query = components.string!
|
||||||
exploreController.searchController.searchBar.text = query
|
rootViewController.performSearch(query: query)
|
||||||
exploreController.resultsController.performSearch(query: query)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,14 +71,21 @@ extension AccountSwitchingContainerViewController {
|
||||||
|
|
||||||
extension AccountSwitchingContainerViewController: TuskerRootViewController {
|
extension AccountSwitchingContainerViewController: TuskerRootViewController {
|
||||||
func presentCompose() {
|
func presentCompose() {
|
||||||
|
loadViewIfNeeded()
|
||||||
root.presentCompose()
|
root.presentCompose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func select(tab: MainTabBarViewController.Tab) {
|
func select(tab: MainTabBarViewController.Tab) {
|
||||||
|
loadViewIfNeeded()
|
||||||
root.select(tab: tab)
|
root.select(tab: tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController? {
|
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController? {
|
||||||
root.getTabController(tab: tab)
|
loadViewIfNeeded()
|
||||||
|
return root.getTabController(tab: tab)
|
||||||
|
}
|
||||||
|
|
||||||
|
func performSearch(query: String) {
|
||||||
|
root.performSearch(query: query)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ class MainSidebarViewController: UIViewController {
|
||||||
|
|
||||||
private(set) var previouslySelectedItem: Item?
|
private(set) var previouslySelectedItem: Item?
|
||||||
var selectedItem: Item? {
|
var selectedItem: Item? {
|
||||||
guard let indexPath = collectionView.indexPathsForSelectedItems?.first else {
|
guard let indexPath = collectionView?.indexPathsForSelectedItems?.first else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return dataSource.itemIdentifier(for: indexPath)
|
return dataSource.itemIdentifier(for: indexPath)
|
||||||
|
|
|
@ -19,6 +19,10 @@ class MainSplitViewController: UISplitViewController {
|
||||||
|
|
||||||
private var tabBarViewController: MainTabBarViewController!
|
private var tabBarViewController: MainTabBarViewController!
|
||||||
|
|
||||||
|
private var secondaryNavController: UINavigationController! {
|
||||||
|
viewController(for: .secondary) as? UINavigationController
|
||||||
|
}
|
||||||
|
|
||||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||||
return .portrait
|
return .portrait
|
||||||
|
@ -67,8 +71,7 @@ class MainSplitViewController: UISplitViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func select(item: MainSidebarViewController.Item) {
|
func select(item: MainSidebarViewController.Item) {
|
||||||
let nav = viewController(for: .secondary) as! UINavigationController
|
secondaryNavController.viewControllers = getOrCreateNavigationStack(item: item)
|
||||||
nav.viewControllers = getOrCreateNavigationStack(item: item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOrCreateNavigationStack(item: MainSidebarViewController.Item) -> [UIViewController] {
|
func getOrCreateNavigationStack(item: MainSidebarViewController.Item) -> [UIViewController] {
|
||||||
|
@ -109,8 +112,7 @@ extension MainSplitViewController: UISplitViewControllerDelegate {
|
||||||
private func transferNavigationStack(from item: MainSidebarViewController.Item, to destination: UINavigationController, dropFirst: Bool = false, append: Bool = false) {
|
private func transferNavigationStack(from item: MainSidebarViewController.Item, to destination: UINavigationController, dropFirst: Bool = false, append: Bool = false) {
|
||||||
var itemNavStack: [UIViewController]
|
var itemNavStack: [UIViewController]
|
||||||
if item == sidebar.selectedItem {
|
if item == sidebar.selectedItem {
|
||||||
let detailNav = viewController(for: .secondary) as! UINavigationController
|
itemNavStack = secondaryNavController.viewControllers
|
||||||
itemNavStack = detailNav.viewControllers
|
|
||||||
} else {
|
} else {
|
||||||
itemNavStack = navigationStacks[item] ?? []
|
itemNavStack = navigationStacks[item] ?? []
|
||||||
navigationStacks.removeValue(forKey: item)
|
navigationStacks.removeValue(forKey: item)
|
||||||
|
@ -190,8 +192,7 @@ extension MainSplitViewController: UISplitViewControllerDelegate {
|
||||||
// Make sure viewDidLoad is called so that the searchController/resultsController have been initialized
|
// Make sure viewDidLoad is called so that the searchController/resultsController have been initialized
|
||||||
explore.loadViewIfNeeded()
|
explore.loadViewIfNeeded()
|
||||||
|
|
||||||
let nav = viewController(for: .secondary) as! UINavigationController
|
let search = secondaryNavController.viewControllers.first as! SearchViewController
|
||||||
let search = nav.viewControllers.first as! SearchViewController
|
|
||||||
// Copy the search query from the search VC to the Explore VC's search controller.
|
// Copy the search query from the search VC to the Explore VC's search controller.
|
||||||
let query = search.searchController.searchBar.text ?? ""
|
let query = search.searchController.searchBar.text ?? ""
|
||||||
explore.searchController.searchBar.text = query
|
explore.searchController.searchBar.text = query
|
||||||
|
@ -318,9 +319,8 @@ extension MainSplitViewController: MainSidebarViewControllerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sidebar(_ sidebarViewController: MainSidebarViewController, didSelectItem item: MainSidebarViewController.Item) {
|
func sidebar(_ sidebarViewController: MainSidebarViewController, didSelectItem item: MainSidebarViewController.Item) {
|
||||||
let nav = viewController(for: .secondary) as! UINavigationController
|
|
||||||
if let previous = sidebar.previouslySelectedItem {
|
if let previous = sidebar.previouslySelectedItem {
|
||||||
navigationStacks[previous] = nav.viewControllers
|
navigationStacks[previous] = secondaryNavController.viewControllers
|
||||||
}
|
}
|
||||||
select(item: item)
|
select(item: item)
|
||||||
}
|
}
|
||||||
|
@ -365,12 +365,19 @@ extension MainSplitViewController: TuskerRootViewController {
|
||||||
} else {
|
} else {
|
||||||
if tab == .compose {
|
if tab == .compose {
|
||||||
presentCompose()
|
presentCompose()
|
||||||
|
} else {
|
||||||
|
if presentedViewController != nil {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
self.select(item: .tab(tab))
|
||||||
|
self.sidebar.select(item: .tab(tab), animated: false)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
select(item: .tab(tab))
|
select(item: .tab(tab))
|
||||||
sidebar.select(item: .tab(tab), animated: false)
|
sidebar.select(item: .tab(tab), animated: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController? {
|
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController? {
|
||||||
if traitCollection.horizontalSizeClass == .compact {
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
|
@ -379,12 +386,43 @@ extension MainSplitViewController: TuskerRootViewController {
|
||||||
if tab == .compose {
|
if tab == .compose {
|
||||||
return nil
|
return nil
|
||||||
} else if case .tab(tab) = sidebar.selectedItem {
|
} else if case .tab(tab) = sidebar.selectedItem {
|
||||||
return viewController(for: .secondary)
|
return secondaryNavController
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func performSearch(query: String) {
|
||||||
|
guard traitCollection.horizontalSizeClass != .compact else {
|
||||||
|
// ensure the tab bar VC is loaded
|
||||||
|
loadViewIfNeeded()
|
||||||
|
tabBarViewController.performSearch(query: query)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sidebar.selectedItem != .search {
|
||||||
|
select(item: .search)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let searchViewController = secondaryNavController.viewControllers.first as? SearchViewController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secondaryNavController.popToRootViewController(animated: false)
|
||||||
|
|
||||||
|
if searchViewController.isViewLoaded {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
searchViewController.searchController.isActive = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
searchViewController.searchControllerStatusOnAppearance = true
|
||||||
|
searchViewController.loadViewIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
searchViewController.searchController.searchBar.text = query
|
||||||
|
searchViewController.resultsController.performSearch(query: query)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MainSplitViewController: BackgroundableViewController {
|
extension MainSplitViewController: BackgroundableViewController {
|
||||||
|
|
|
@ -137,6 +137,8 @@ extension MainTabBarViewController {
|
||||||
if tab == .compose {
|
if tab == .compose {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
|
// viewWControllers array is setup in viewDidLoad
|
||||||
|
loadViewIfNeeded()
|
||||||
return viewControllers![tab.rawValue]
|
return viewControllers![tab.rawValue]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,10 +169,40 @@ extension MainTabBarViewController: TuskerRootViewController {
|
||||||
func select(tab: Tab) {
|
func select(tab: Tab) {
|
||||||
if tab == .compose {
|
if tab == .compose {
|
||||||
presentCompose()
|
presentCompose()
|
||||||
|
} else {
|
||||||
|
// when switching tabs, dismiss the currently presented VC
|
||||||
|
// otherwise the selected tab changes behind the presented VC
|
||||||
|
if presentedViewController != nil {
|
||||||
|
dismiss(animated: true) {
|
||||||
|
self.selectedIndex = tab.rawValue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
selectedIndex = tab.rawValue
|
selectedIndex = tab.rawValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func performSearch(query: String) {
|
||||||
|
guard let exploreNavController = getTabController(tab: .explore) as? UINavigationController,
|
||||||
|
let exploreController = exploreNavController.viewControllers.first as? ExploreViewController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
select(tab: .explore)
|
||||||
|
exploreNavController.popToRootViewController(animated: false)
|
||||||
|
|
||||||
|
// setting searchController.isActive directly doesn't work until the view has loaded/appeared for the first time
|
||||||
|
if exploreController.isViewLoaded {
|
||||||
|
exploreController.searchController.isActive = true
|
||||||
|
} else {
|
||||||
|
exploreController.searchControllerStatusOnAppearance = true
|
||||||
|
// we still need to load the view so that we can setup the search query
|
||||||
|
exploreController.loadViewIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
exploreController.searchController.searchBar.text = query
|
||||||
|
exploreController.resultsController.performSearch(query: query)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MainTabBarViewController: BackgroundableViewController {
|
extension MainTabBarViewController: BackgroundableViewController {
|
||||||
|
|
|
@ -12,4 +12,5 @@ protocol TuskerRootViewController: UIViewController {
|
||||||
func presentCompose()
|
func presentCompose()
|
||||||
func select(tab: MainTabBarViewController.Tab)
|
func select(tab: MainTabBarViewController.Tab)
|
||||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController?
|
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController?
|
||||||
|
func performSearch(query: String)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SearchViewController: UIViewController {
|
||||||
resultsController = SearchResultsViewController(mastodonController: mastodonController)
|
resultsController = SearchResultsViewController(mastodonController: mastodonController)
|
||||||
resultsController.exploreNavigationController = self.navigationController
|
resultsController.exploreNavigationController = self.navigationController
|
||||||
searchController = UISearchController(searchResultsController: resultsController)
|
searchController = UISearchController(searchResultsController: resultsController)
|
||||||
searchController.searchResultsUpdater = resultsController
|
searchController.obscuresBackgroundDuringPresentation = false
|
||||||
searchController.searchBar.autocapitalizationType = .none
|
searchController.searchBar.autocapitalizationType = .none
|
||||||
searchController.searchBar.delegate = resultsController
|
searchController.searchBar.delegate = resultsController
|
||||||
searchController.hidesNavigationBarDuringPresentation = false
|
searchController.hidesNavigationBarDuringPresentation = false
|
||||||
|
|
Loading…
Reference in New Issue