forked from shadowfacts/Tusker
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 */; };
|
||||
D6DFC6A0242C4CCC00ACC392 /* WeakArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DFC69F242C4CCC00ACC392 /* WeakArray.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 */; };
|
||||
D6E4269D2532A3E100C02E1C /* FuzzyMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E4269C2532A3E100C02E1C /* FuzzyMatcher.swift */; };
|
||||
D6E426AD25334DA500C02E1C /* FuzzyMatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */; };
|
||||
|
@ -363,9 +368,27 @@
|
|||
remoteGlobalIDString = D6D4DDCB212518A000E1C4BB;
|
||||
remoteInfo = Tusker;
|
||||
};
|
||||
D6E343B2265AAD6B00C4AA01 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D6E343A7265AAD6B00C4AA01;
|
||||
remoteInfo = OpenInTusker;
|
||||
};
|
||||
/* End PBXContainerItemProxy 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 */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -687,6 +710,13 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -752,6 +782,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E343A5265AAD6B00C4AA01 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
@ -1472,6 +1509,7 @@
|
|||
D6D4DDCE212518A000E1C4BB /* Tusker */,
|
||||
D6D4DDE3212518A200E1C4BB /* TuskerTests */,
|
||||
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
||||
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
||||
D6D4DDCD212518A000E1C4BB /* Products */,
|
||||
D65A37F221472F300087646E /* Frameworks */,
|
||||
);
|
||||
|
@ -1485,6 +1523,7 @@
|
|||
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
||||
D61099AB2144B0CC00432DC2 /* Pachyderm.framework */,
|
||||
D61099B32144B0CC00432DC2 /* PachydermTests.xctest */,
|
||||
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1552,6 +1591,19 @@
|
|||
path = TuskerUITests;
|
||||
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 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1642,11 +1694,13 @@
|
|||
D6D4DDCA212518A000E1C4BB /* Resources */,
|
||||
D6F953E52125197500CF0F2B /* Embed Frameworks */,
|
||||
D65F612C23AE957600F3CFD3 /* Embed debug-only frameworks */,
|
||||
D6E3438F2659849800C4AA01 /* Embed App Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D61099BF2144B0CC00432DC2 /* PBXTargetDependency */,
|
||||
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Tusker;
|
||||
packageProductDependencies = (
|
||||
|
@ -1696,13 +1750,30 @@
|
|||
productReference = D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */;
|
||||
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 */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
D6D4DDC4212518A000E1C4BB /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1200;
|
||||
LastSwiftUpdateCheck = 1250;
|
||||
LastUpgradeCheck = 1250;
|
||||
ORGANIZATIONNAME = Shadowfacts;
|
||||
TargetAttributes = {
|
||||
|
@ -1729,6 +1800,9 @@
|
|||
LastSwiftMigration = 1020;
|
||||
TestTargetID = D6D4DDCB212518A000E1C4BB;
|
||||
};
|
||||
D6E343A7265AAD6B00C4AA01 = {
|
||||
CreatedOnToolsVersion = 12.5;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D6D4DDC7212518A000E1C4BB /* Build configuration list for PBXProject "Tusker" */;
|
||||
|
@ -1760,6 +1834,7 @@
|
|||
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
||||
D61099AA2144B0CC00432DC2 /* Pachyderm */,
|
||||
D61099B22144B0CC00432DC2 /* PachydermTests */,
|
||||
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -1827,6 +1902,16 @@
|
|||
);
|
||||
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 */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
|
@ -2170,6 +2255,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D6E343A4265AAD6B00C4AA01 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D6E343AD265AAD6B00C4AA01 /* ActionViewController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
@ -2198,6 +2291,11 @@
|
|||
target = D6D4DDCB212518A000E1C4BB /* Tusker */;
|
||||
targetProxy = D6D4DDEC212518A200E1C4BB /* PBXContainerItemProxy */;
|
||||
};
|
||||
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D6E343A7265AAD6B00C4AA01 /* OpenInTusker */;
|
||||
targetProxy = D6E343B2265AAD6B00C4AA01 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
|
@ -2209,6 +2307,14 @@
|
|||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E343AE265AAD6B00C4AA01 /* MainInterface.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
D6E343AF265AAD6B00C4AA01 /* Base */,
|
||||
);
|
||||
name = MainInterface.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D6E57FA525C26FAB00341037 /* Localizable.stringsdict */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
@ -2234,6 +2340,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Pachyderm/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -2264,6 +2371,7 @@
|
|||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Pachyderm/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -2451,7 +2559,7 @@
|
|||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||
INFOPLIST_FILE = Tusker/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.0;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -2480,7 +2588,7 @@
|
|||
DEVELOPMENT_TEAM = V4WK9KR9U2;
|
||||
INFOPLIST_FILE = Tusker/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.0;
|
||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
@ -2578,6 +2686,60 @@
|
|||
};
|
||||
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 */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
@ -2635,6 +2797,15 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D6E343B6265AAD6B00C4AA01 /* Build configuration list for PBXNativeTarget "OpenInTusker" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D6E343B7265AAD6B00C4AA01 /* Debug */,
|
||||
D6E343B8265AAD6B00C4AA01 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
|
|
|
@ -76,9 +76,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
|
||||
case .newPost:
|
||||
return "compose"
|
||||
|
||||
default:
|
||||
fatalError("no scene for activity type \(type)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
handlePendingCrashReport(report, session: session)
|
||||
} else {
|
||||
showAppOrOnboardingUI(session: session)
|
||||
if connectionOptions.urlContexts.count > 0 {
|
||||
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
|
||||
}
|
||||
}
|
||||
|
||||
window!.makeKeyAndVisible()
|
||||
|
@ -50,20 +53,10 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||
if url.host == "x-callback-url" {
|
||||
_ = XCBManager.handle(url: url)
|
||||
} else if var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||
let tabBarController = window!.rootViewController as? MainTabBarViewController,
|
||||
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
|
||||
|
||||
let rootViewController = window!.rootViewController as? TuskerRootViewController {
|
||||
components.scheme = "https"
|
||||
let query = url.absoluteString
|
||||
exploreController.searchController.searchBar.text = query
|
||||
exploreController.resultsController.performSearch(query: query)
|
||||
let query = components.string!
|
||||
rootViewController.performSearch(query: query)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,14 +71,21 @@ extension AccountSwitchingContainerViewController {
|
|||
|
||||
extension AccountSwitchingContainerViewController: TuskerRootViewController {
|
||||
func presentCompose() {
|
||||
loadViewIfNeeded()
|
||||
root.presentCompose()
|
||||
}
|
||||
|
||||
func select(tab: MainTabBarViewController.Tab) {
|
||||
loadViewIfNeeded()
|
||||
root.select(tab: tab)
|
||||
}
|
||||
|
||||
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?
|
||||
var selectedItem: Item? {
|
||||
guard let indexPath = collectionView.indexPathsForSelectedItems?.first else {
|
||||
guard let indexPath = collectionView?.indexPathsForSelectedItems?.first else {
|
||||
return nil
|
||||
}
|
||||
return dataSource.itemIdentifier(for: indexPath)
|
||||
|
|
|
@ -19,6 +19,10 @@ class MainSplitViewController: UISplitViewController {
|
|||
|
||||
private var tabBarViewController: MainTabBarViewController!
|
||||
|
||||
private var secondaryNavController: UINavigationController! {
|
||||
viewController(for: .secondary) as? UINavigationController
|
||||
}
|
||||
|
||||
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
||||
if UIDevice.current.userInterfaceIdiom == .phone {
|
||||
return .portrait
|
||||
|
@ -67,8 +71,7 @@ class MainSplitViewController: UISplitViewController {
|
|||
}
|
||||
|
||||
func select(item: MainSidebarViewController.Item) {
|
||||
let nav = viewController(for: .secondary) as! UINavigationController
|
||||
nav.viewControllers = getOrCreateNavigationStack(item: item)
|
||||
secondaryNavController.viewControllers = getOrCreateNavigationStack(item: item)
|
||||
}
|
||||
|
||||
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) {
|
||||
var itemNavStack: [UIViewController]
|
||||
if item == sidebar.selectedItem {
|
||||
let detailNav = viewController(for: .secondary) as! UINavigationController
|
||||
itemNavStack = detailNav.viewControllers
|
||||
itemNavStack = secondaryNavController.viewControllers
|
||||
} else {
|
||||
itemNavStack = navigationStacks[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
|
||||
explore.loadViewIfNeeded()
|
||||
|
||||
let nav = viewController(for: .secondary) as! UINavigationController
|
||||
let search = nav.viewControllers.first as! SearchViewController
|
||||
let search = secondaryNavController.viewControllers.first as! SearchViewController
|
||||
// Copy the search query from the search VC to the Explore VC's search controller.
|
||||
let query = search.searchController.searchBar.text ?? ""
|
||||
explore.searchController.searchBar.text = query
|
||||
|
@ -318,9 +319,8 @@ extension MainSplitViewController: MainSidebarViewControllerDelegate {
|
|||
}
|
||||
|
||||
func sidebar(_ sidebarViewController: MainSidebarViewController, didSelectItem item: MainSidebarViewController.Item) {
|
||||
let nav = viewController(for: .secondary) as! UINavigationController
|
||||
if let previous = sidebar.previouslySelectedItem {
|
||||
navigationStacks[previous] = nav.viewControllers
|
||||
navigationStacks[previous] = secondaryNavController.viewControllers
|
||||
}
|
||||
select(item: item)
|
||||
}
|
||||
|
@ -365,12 +365,19 @@ extension MainSplitViewController: TuskerRootViewController {
|
|||
} else {
|
||||
if tab == .compose {
|
||||
presentCompose()
|
||||
} else {
|
||||
if presentedViewController != nil {
|
||||
dismiss(animated: true) {
|
||||
self.select(item: .tab(tab))
|
||||
self.sidebar.select(item: .tab(tab), animated: false)
|
||||
}
|
||||
} else {
|
||||
select(item: .tab(tab))
|
||||
sidebar.select(item: .tab(tab), animated: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController? {
|
||||
if traitCollection.horizontalSizeClass == .compact {
|
||||
|
@ -379,12 +386,43 @@ extension MainSplitViewController: TuskerRootViewController {
|
|||
if tab == .compose {
|
||||
return nil
|
||||
} else if case .tab(tab) = sidebar.selectedItem {
|
||||
return viewController(for: .secondary)
|
||||
return secondaryNavController
|
||||
} else {
|
||||
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 {
|
||||
|
|
|
@ -137,6 +137,8 @@ extension MainTabBarViewController {
|
|||
if tab == .compose {
|
||||
return nil
|
||||
} else {
|
||||
// viewWControllers array is setup in viewDidLoad
|
||||
loadViewIfNeeded()
|
||||
return viewControllers![tab.rawValue]
|
||||
}
|
||||
}
|
||||
|
@ -167,12 +169,42 @@ extension MainTabBarViewController: TuskerRootViewController {
|
|||
func select(tab: Tab) {
|
||||
if tab == .compose {
|
||||
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 {
|
||||
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 {
|
||||
func sceneDidEnterBackground() {
|
||||
if let selectedVC = selectedViewController as? BackgroundableViewController {
|
||||
|
|
|
@ -12,4 +12,5 @@ protocol TuskerRootViewController: UIViewController {
|
|||
func presentCompose()
|
||||
func select(tab: MainTabBarViewController.Tab)
|
||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController?
|
||||
func performSearch(query: String)
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ class SearchViewController: UIViewController {
|
|||
resultsController = SearchResultsViewController(mastodonController: mastodonController)
|
||||
resultsController.exploreNavigationController = self.navigationController
|
||||
searchController = UISearchController(searchResultsController: resultsController)
|
||||
searchController.searchResultsUpdater = resultsController
|
||||
searchController.obscuresBackgroundDuringPresentation = false
|
||||
searchController.searchBar.autocapitalizationType = .none
|
||||
searchController.searchBar.delegate = resultsController
|
||||
searchController.hidesNavigationBarDuringPresentation = false
|
||||
|
|
Loading…
Reference in New Issue