forked from shadowfacts/Tusker
Initial share extension implementation
This commit is contained in:
parent
06855420da
commit
6c371f868f
|
@ -12,16 +12,24 @@ import PencilKit
|
||||||
import TuskerComponents
|
import TuskerComponents
|
||||||
|
|
||||||
public struct ComposeUIConfig {
|
public struct ComposeUIConfig {
|
||||||
|
// Config
|
||||||
|
public var allowSwitchingDrafts = true
|
||||||
|
public var textSelectionStartsAtBeginning = false
|
||||||
|
|
||||||
|
// Style
|
||||||
public var backgroundColor = Color(uiColor: .systemBackground)
|
public var backgroundColor = Color(uiColor: .systemBackground)
|
||||||
public var groupedBackgroundColor = Color(uiColor: .systemGroupedBackground)
|
public var groupedBackgroundColor = Color(uiColor: .systemGroupedBackground)
|
||||||
public var groupedCellBackgroundColor = Color(uiColor: .systemBackground)
|
public var groupedCellBackgroundColor = Color(uiColor: .systemBackground)
|
||||||
public var fillColor = Color(uiColor: .systemFill)
|
public var fillColor = Color(uiColor: .systemFill)
|
||||||
public var avatarStyle = AvatarImageView.Style.roundRect
|
public var avatarStyle = AvatarImageView.Style.roundRect
|
||||||
|
|
||||||
|
// Preferences
|
||||||
public var useTwitterKeyboard = false
|
public var useTwitterKeyboard = false
|
||||||
public var contentType = StatusContentType.plain
|
public var contentType = StatusContentType.plain
|
||||||
public var automaticallySaveDrafts = false
|
public var automaticallySaveDrafts = false
|
||||||
public var requireAttachmentDescriptions = false
|
public var requireAttachmentDescriptions = false
|
||||||
|
|
||||||
|
// Host callbacks
|
||||||
public var dismiss: @MainActor (DismissMode) -> Void = { _ in }
|
public var dismiss: @MainActor (DismissMode) -> Void = { _ in }
|
||||||
public var presentAssetPicker: ((@MainActor @escaping ([PHPickerResult]) -> Void) -> Void)?
|
public var presentAssetPicker: ((@MainActor @escaping ([PHPickerResult]) -> Void) -> Void)?
|
||||||
public var presentDrawing: ((PKDrawing, @escaping (PKDrawing) -> Void) -> Void)?
|
public var presentDrawing: ((PKDrawing, @escaping (PKDrawing) -> Void) -> Void)?
|
||||||
|
|
|
@ -351,7 +351,7 @@ public final class ComposeController: ViewController {
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var postButton: some View {
|
private var postButton: some View {
|
||||||
if draft.hasContent {
|
if draft.hasContent || !controller.config.allowSwitchingDrafts {
|
||||||
Button(action: controller.postStatus) {
|
Button(action: controller.postStatus) {
|
||||||
Text("Post")
|
Text("Post")
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ struct MainTextView: View {
|
||||||
|
|
||||||
@State private var hasFirstAppeared = false
|
@State private var hasFirstAppeared = false
|
||||||
@State private var height: CGFloat?
|
@State private var height: CGFloat?
|
||||||
|
@State private var updateSelection: ((UITextView) -> Void)?
|
||||||
private let minHeight: CGFloat = 150
|
private let minHeight: CGFloat = 150
|
||||||
private var effectiveHeight: CGFloat { height ?? minHeight }
|
private var effectiveHeight: CGFloat { height ?? minHeight }
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ struct MainTextView: View {
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWrappedTextViewRepresentable(text: $draft.text, becomeFirstResponder: $controller.mainComposeTextViewBecomeFirstResponder, textDidChange: textDidChange)
|
MainWrappedTextViewRepresentable(text: $draft.text, becomeFirstResponder: $controller.mainComposeTextViewBecomeFirstResponder, updateSelection: $updateSelection, textDidChange: textDidChange)
|
||||||
}
|
}
|
||||||
.frame(height: effectiveHeight)
|
.frame(height: effectiveHeight)
|
||||||
.onAppear(perform: becomeFirstResponderOnFirstAppearance)
|
.onAppear(perform: becomeFirstResponderOnFirstAppearance)
|
||||||
|
@ -44,6 +45,11 @@ struct MainTextView: View {
|
||||||
if !hasFirstAppeared {
|
if !hasFirstAppeared {
|
||||||
hasFirstAppeared = true
|
hasFirstAppeared = true
|
||||||
controller.mainComposeTextViewBecomeFirstResponder = true
|
controller.mainComposeTextViewBecomeFirstResponder = true
|
||||||
|
if config.textSelectionStartsAtBeginning {
|
||||||
|
updateSelection = { textView in
|
||||||
|
textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +63,7 @@ fileprivate struct MainWrappedTextViewRepresentable: UIViewRepresentable {
|
||||||
|
|
||||||
@Binding var text: String
|
@Binding var text: String
|
||||||
@Binding var becomeFirstResponder: Bool
|
@Binding var becomeFirstResponder: Bool
|
||||||
|
@Binding var updateSelection: ((UITextView) -> Void)?
|
||||||
let textDidChange: (UITextView) -> Void
|
let textDidChange: (UITextView) -> Void
|
||||||
|
|
||||||
@EnvironmentObject private var controller: ComposeController
|
@EnvironmentObject private var controller: ComposeController
|
||||||
|
@ -85,6 +92,11 @@ fileprivate struct MainWrappedTextViewRepresentable: UIViewRepresentable {
|
||||||
|
|
||||||
context.coordinator.text = $text
|
context.coordinator.text = $text
|
||||||
|
|
||||||
|
if let updateSelection {
|
||||||
|
updateSelection(uiView)
|
||||||
|
self.updateSelection = nil
|
||||||
|
}
|
||||||
|
|
||||||
// wait until the next runloop iteration so that SwiftUI view updates have finished and
|
// wait until the next runloop iteration so that SwiftUI view updates have finished and
|
||||||
// the text view knows its new content size
|
// the text view knows its new content size
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="j1y-V4-xli">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Share View Controller-->
|
||||||
|
<scene sceneID="ceB-am-kn3">
|
||||||
|
<objects>
|
||||||
|
<viewController id="j1y-V4-xli" customClass="ShareViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<view key="view" opaque="NO" contentMode="scaleToFill" id="wbc-yd-nQP">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<viewLayoutGuide key="safeArea" id="1Xd-am-t49"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="CEy-Cv-SGf" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionActivationRule</key>
|
||||||
|
<string>TRUEPREDICATE</string>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionMainStoryboard</key>
|
||||||
|
<string>MainInterface</string>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.share-services</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?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.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.space.vaccor.Tusker</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,154 @@
|
||||||
|
//
|
||||||
|
// ShareHostingController.swift
|
||||||
|
// ShareExtension
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 4/17/23.
|
||||||
|
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import ComposeUI
|
||||||
|
import TuskerComponents
|
||||||
|
import WebURLFoundationExtras
|
||||||
|
import Combine
|
||||||
|
import TuskerPreferences
|
||||||
|
|
||||||
|
class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||||
|
private static func fetchAvatar(_ url: URL) async -> UIImage? {
|
||||||
|
guard let (data, _) = try? await URLSession.shared.data(from: url),
|
||||||
|
let image = UIImage(data: data) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return await image.byPreparingThumbnail(ofSize: CGSize(width: 50, height: 50)) ?? image
|
||||||
|
}
|
||||||
|
|
||||||
|
private let controller: ComposeController
|
||||||
|
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
init(draft: Draft, mastodonContext: ShareMastodonContext) {
|
||||||
|
controller = ComposeController(
|
||||||
|
draft: draft,
|
||||||
|
config: ComposeUIConfig(),
|
||||||
|
mastodonController: mastodonContext,
|
||||||
|
fetchAvatar: Self.fetchAvatar,
|
||||||
|
fetchStatus: { _ in fatalError("replies aren't allowed in share sheet") },
|
||||||
|
displayNameLabel: { account, style, _ in AnyView(Text(account.displayName).font(.system(style))) },
|
||||||
|
replyContentView: { _, _ in fatalError("replies aren't allowed in share sheet") },
|
||||||
|
emojiImageView: {
|
||||||
|
AnyView(AsyncImage(url: URL($0.url)!) {
|
||||||
|
$0
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
} placeholder: {
|
||||||
|
Image(systemName: "smiley.fill")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
super.init(rootView: View(controller: controller))
|
||||||
|
|
||||||
|
updateConfig()
|
||||||
|
|
||||||
|
mastodonContext.$ownAccount
|
||||||
|
.sink { [unowned self] in self.controller.currentAccount = $0 }
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateConfig() {
|
||||||
|
var config = ComposeUIConfig()
|
||||||
|
config.allowSwitchingDrafts = false
|
||||||
|
config.textSelectionStartsAtBeginning = true
|
||||||
|
// note: in the share sheet, we ignore this preference
|
||||||
|
config.automaticallySaveDrafts = false
|
||||||
|
|
||||||
|
config.backgroundColor = Color(uiColor: .appBackground)
|
||||||
|
config.groupedBackgroundColor = Color(uiColor: .appGroupedBackground)
|
||||||
|
config.groupedCellBackgroundColor = Color(uiColor: .appGroupedCellBackground)
|
||||||
|
config.fillColor = Color(uiColor: .appFill)
|
||||||
|
switch Preferences.shared.avatarStyle {
|
||||||
|
case .roundRect:
|
||||||
|
config.avatarStyle = .roundRect
|
||||||
|
case .circle:
|
||||||
|
config.avatarStyle = .circle
|
||||||
|
}
|
||||||
|
config.useTwitterKeyboard = Preferences.shared.useTwitterKeyboard
|
||||||
|
config.contentType = Preferences.shared.statusContentType
|
||||||
|
config.requireAttachmentDescriptions = Preferences.shared.requireAttachmentDescriptions
|
||||||
|
|
||||||
|
config.dismiss = { [unowned self] in self.dismiss(mode: $0) }
|
||||||
|
|
||||||
|
controller.config = config
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dismiss(mode: DismissMode) {
|
||||||
|
guard let extensionContext else { return }
|
||||||
|
switch mode {
|
||||||
|
case .cancel:
|
||||||
|
extensionContext.cancelRequest(withError: Error.cancelled)
|
||||||
|
case .post:
|
||||||
|
extensionContext.completeRequest(returningItems: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct View: SwiftUI.View {
|
||||||
|
let controller: ComposeController
|
||||||
|
|
||||||
|
var body: some SwiftUI.View {
|
||||||
|
ControllerView(controller: { controller })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Error: Swift.Error {
|
||||||
|
case cancelled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: shouldn't just copy this from the main Colors.swift
|
||||||
|
extension UIColor {
|
||||||
|
static let appBackground = UIColor { traitCollection in
|
||||||
|
if case .dark = traitCollection.userInterfaceStyle,
|
||||||
|
!Preferences.shared.pureBlackDarkMode {
|
||||||
|
return UIColor(hue: 230/360, saturation: 23/100, brightness: 10/100, alpha: 1)
|
||||||
|
} else {
|
||||||
|
return .systemBackground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static let appGroupedBackground = UIColor { traitCollection in
|
||||||
|
if case .dark = traitCollection.userInterfaceStyle,
|
||||||
|
!Preferences.shared.pureBlackDarkMode {
|
||||||
|
if traitCollection.userInterfaceLevel == .elevated {
|
||||||
|
return UIColor(hue: 230/360, saturation: 23/100, brightness: 10/100, alpha: 1)
|
||||||
|
} else {
|
||||||
|
return UIColor(hue: 230/360, saturation: 23/100, brightness: 5/100, alpha: 1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .systemGroupedBackground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static let appGroupedCellBackground = UIColor { traitCollection in
|
||||||
|
if case .dark = traitCollection.userInterfaceStyle {
|
||||||
|
if Preferences.shared.pureBlackDarkMode {
|
||||||
|
return .secondarySystemBackground
|
||||||
|
} else {
|
||||||
|
return .appFill
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .systemBackground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static let appFill = UIColor { traitCollection in
|
||||||
|
if case .dark = traitCollection.userInterfaceStyle,
|
||||||
|
!Preferences.shared.pureBlackDarkMode {
|
||||||
|
return UIColor(hue: 230/360, saturation: 20/100, brightness: 17/100, alpha: 1)
|
||||||
|
} else {
|
||||||
|
return .systemFill
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
//
|
||||||
|
// ShareMastodonContext.swift
|
||||||
|
// ShareExtension
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 4/17/23.
|
||||||
|
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Pachyderm
|
||||||
|
import ComposeUI
|
||||||
|
import UserAccounts
|
||||||
|
import InstanceFeatures
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
class ShareMastodonContext: ComposeMastodonContext, ObservableObject {
|
||||||
|
let accountInfo: UserAccountInfo?
|
||||||
|
let client: Client
|
||||||
|
let instanceFeatures: InstanceFeatures
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
private var customEmojis: [Emoji]?
|
||||||
|
|
||||||
|
@Published var ownAccount: Account?
|
||||||
|
|
||||||
|
init(accountInfo: UserAccountInfo) {
|
||||||
|
self.accountInfo = accountInfo
|
||||||
|
self.client = Client(baseURL: accountInfo.instanceURL, accessToken: accountInfo.accessToken)
|
||||||
|
self.instanceFeatures = InstanceFeatures()
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
async let instance = try? await run(Client.getInstance()).0
|
||||||
|
async let nodeInfo: NodeInfo? = await withCheckedContinuation({ continuation in
|
||||||
|
self.client.nodeInfo { response in
|
||||||
|
switch response {
|
||||||
|
case .success(let nodeInfo, _):
|
||||||
|
continuation.resume(returning: nodeInfo)
|
||||||
|
case .failure(_):
|
||||||
|
continuation.resume(returning: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
guard let instance = await instance else { return }
|
||||||
|
self.instanceFeatures.update(instance: instance, nodeInfo: await nodeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
if let account = try? await run(Client.getSelfAccount()).0 {
|
||||||
|
self.ownAccount = account
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: CompmoseMastodonContext
|
||||||
|
|
||||||
|
func run<Result: Decodable & Sendable>(_ request: Request<Result>) async throws -> (Result, Pagination?) {
|
||||||
|
return try await withCheckedThrowingContinuation({ continuation in
|
||||||
|
client.run(request) { response in
|
||||||
|
switch response {
|
||||||
|
case .success(let result, let pagination):
|
||||||
|
continuation.resume(returning: (result, pagination))
|
||||||
|
case .failure(let error):
|
||||||
|
continuation.resume(throwing: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func getCustomEmojis(completion: @escaping ([Emoji]) -> Void) {
|
||||||
|
if let customEmojis {
|
||||||
|
completion(customEmojis)
|
||||||
|
} else {
|
||||||
|
Task.detached { @MainActor in
|
||||||
|
let emojis = (try? await self.run(Client.getCustomEmoji()).0) ?? []
|
||||||
|
self.customEmojis = emojis
|
||||||
|
completion(emojis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchCachedAccounts(query: String) -> [AccountProtocol] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
func cachedRelationship(for accountID: String) -> RelationshipProtocol? {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchCachedHashtags(query: String) -> [Hashtag] {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
//
|
||||||
|
// ShareViewController.swift
|
||||||
|
// ShareExtension
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 4/17/23.
|
||||||
|
// Copyright © 2023 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import UserAccounts
|
||||||
|
import ComposeUI
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
import TuskerPreferences
|
||||||
|
|
||||||
|
class ShareViewController: UIViewController {
|
||||||
|
|
||||||
|
private var state: State = .loading
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.tintColor = Preferences.shared.accentColor.color
|
||||||
|
|
||||||
|
if let account = UserAccountsManager.shared.getMostRecentAccount() {
|
||||||
|
Task { @MainActor in
|
||||||
|
let draft = await createDraft(account: account)
|
||||||
|
state = .ok
|
||||||
|
|
||||||
|
let context = ShareMastodonContext(accountInfo: account)
|
||||||
|
let host = ShareHostingController(draft: draft, mastodonContext: context)
|
||||||
|
let nav = UINavigationController(rootViewController: host)
|
||||||
|
self.addChild(nav)
|
||||||
|
nav.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
self.view.addSubview(nav.view)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
nav.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
|
||||||
|
nav.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
|
||||||
|
nav.view.topAnchor.constraint(equalTo: self.view.topAnchor),
|
||||||
|
nav.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
|
||||||
|
])
|
||||||
|
nav.didMove(toParent: self)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state = .notLoggedIn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createDraft(account: UserAccountInfo) async -> Draft {
|
||||||
|
let (text, attachments) = await getDraftConfigurationFromExtensionContext()
|
||||||
|
let draft = Draft(
|
||||||
|
accountID: account.id,
|
||||||
|
text: text,
|
||||||
|
contentWarning: "",
|
||||||
|
inReplyToID: nil,
|
||||||
|
// TODO: get the default visibility from preferences
|
||||||
|
visibility: .public,
|
||||||
|
localOnly: false
|
||||||
|
)
|
||||||
|
draft.attachments = attachments
|
||||||
|
return draft
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getDraftConfigurationFromExtensionContext() async -> (String, [DraftAttachment]) {
|
||||||
|
guard let extensionContext,
|
||||||
|
let inputItem = (extensionContext.inputItems as? [NSExtensionItem])?.first,
|
||||||
|
let itemProvider = inputItem.attachments?.first else {
|
||||||
|
return ("", [])
|
||||||
|
}
|
||||||
|
if let url: NSURL = await getObject(from: itemProvider) {
|
||||||
|
if let title = inputItem.attributedTitle ?? inputItem.attributedContentText {
|
||||||
|
return ("\n\n\(title.string)\n\(url.absoluteString ?? "")", [])
|
||||||
|
} else {
|
||||||
|
return ("\n\n\(url.absoluteString ?? "")", [])
|
||||||
|
}
|
||||||
|
} else if let text: NSString = await getObject(from: itemProvider) {
|
||||||
|
return ("\n\n\(text)", [])
|
||||||
|
} else if let attachment: DraftAttachment = await getObject(from: itemProvider) {
|
||||||
|
return ("", [attachment])
|
||||||
|
} else if let attributedContent = inputItem.attributedContentText {
|
||||||
|
return ("\n\n\(attributedContent.string)", [])
|
||||||
|
} else {
|
||||||
|
return ("", [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getObject<T: NSItemProviderReading>(from itemProvider: NSItemProvider) async -> T? {
|
||||||
|
guard itemProvider.canLoadObject(ofClass: T.self) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return await withCheckedContinuation({ continuation in
|
||||||
|
itemProvider.loadObject(ofClass: T.self) { object, error in
|
||||||
|
continuation.resume(returning: object as? T)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
if case .notLoggedIn = state {
|
||||||
|
let alert = UIAlertController(title: "Not Logged In", message: "You need to log in to an account through the app before you can post.", preferredStyle: .alert)
|
||||||
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [unowned self] _ in
|
||||||
|
self.extensionContext!.cancelRequest(withError: Error.notLoggedIn)
|
||||||
|
}))
|
||||||
|
present(alert, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
case loading
|
||||||
|
case notLoggedIn
|
||||||
|
case ok
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Error: Swift.Error {
|
||||||
|
case notLoggedIn
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -220,6 +220,16 @@
|
||||||
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */; };
|
D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */; };
|
||||||
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */; };
|
D6A3BC8A2321F79B00FD64D5 /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */; };
|
||||||
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */; };
|
D6A3BC8B2321F79B00FD64D5 /* AccountTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */; };
|
||||||
|
D6A4531629EF64BA00032932 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4531529EF64BA00032932 /* ShareViewController.swift */; };
|
||||||
|
D6A4531929EF64BA00032932 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6A4531729EF64BA00032932 /* MainInterface.storyboard */; };
|
||||||
|
D6A4531D29EF64BA00032932 /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D6A4531329EF64BA00032932 /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
D6A4532429EF665200032932 /* ComposeUI in Frameworks */ = {isa = PBXBuildFile; productRef = D6A4532329EF665200032932 /* ComposeUI */; };
|
||||||
|
D6A4532629EF665600032932 /* InstanceFeatures in Frameworks */ = {isa = PBXBuildFile; productRef = D6A4532529EF665600032932 /* InstanceFeatures */; };
|
||||||
|
D6A4532829EF665800032932 /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D6A4532729EF665800032932 /* Pachyderm */; };
|
||||||
|
D6A4532A29EF665A00032932 /* TuskerPreferences in Frameworks */ = {isa = PBXBuildFile; productRef = D6A4532929EF665A00032932 /* TuskerPreferences */; };
|
||||||
|
D6A4532C29EF665D00032932 /* UserAccounts in Frameworks */ = {isa = PBXBuildFile; productRef = D6A4532B29EF665D00032932 /* UserAccounts */; };
|
||||||
|
D6A4532E29EF7DDD00032932 /* ShareHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4532D29EF7DDD00032932 /* ShareHostingController.swift */; };
|
||||||
|
D6A4533029EF7DEE00032932 /* ShareMastodonContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4532F29EF7DEE00032932 /* ShareMastodonContext.swift */; };
|
||||||
D6A4DCCC2553667800D9DE31 /* FastAccountSwitcherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4DCCA2553667800D9DE31 /* FastAccountSwitcherViewController.swift */; };
|
D6A4DCCC2553667800D9DE31 /* FastAccountSwitcherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4DCCA2553667800D9DE31 /* FastAccountSwitcherViewController.swift */; };
|
||||||
D6A4DCCD2553667800D9DE31 /* FastAccountSwitcherViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A4DCCB2553667800D9DE31 /* FastAccountSwitcherViewController.xib */; };
|
D6A4DCCD2553667800D9DE31 /* FastAccountSwitcherViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6A4DCCB2553667800D9DE31 /* FastAccountSwitcherViewController.xib */; };
|
||||||
D6A4DCE525537C7A00D9DE31 /* FastSwitchingAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4DCE425537C7A00D9DE31 /* FastSwitchingAccountView.swift */; };
|
D6A4DCE525537C7A00D9DE31 /* FastSwitchingAccountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A4DCE425537C7A00D9DE31 /* FastSwitchingAccountView.swift */; };
|
||||||
|
@ -335,6 +345,13 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
D6A4531B29EF64BA00032932 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = D6A4531229EF64BA00032932;
|
||||||
|
remoteInfo = ShareExtension;
|
||||||
|
};
|
||||||
D6D4DDE1212518A200E1C4BB /* PBXContainerItemProxy */ = {
|
D6D4DDE1212518A200E1C4BB /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
containerPortal = D6D4DDC4212518A000E1C4BB /* Project object */;
|
||||||
|
@ -365,6 +382,7 @@
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
|
D6A4531D29EF64BA00032932 /* ShareExtension.appex in Embed Foundation Extensions */,
|
||||||
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed Foundation Extensions */,
|
D6E343B4265AAD6B00C4AA01 /* OpenInTusker.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed Foundation Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
|
@ -597,6 +615,13 @@
|
||||||
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FollowNotificationGroupTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
|
D6A3BC882321F79B00FD64D5 /* AccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountTableViewCell.xib; sourceTree = "<group>"; };
|
D6A3BC892321F79B00FD64D5 /* AccountTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
D6A4531329EF64BA00032932 /* ShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D6A4531529EF64BA00032932 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||||
|
D6A4531829EF64BA00032932 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
|
||||||
|
D6A4531A29EF64BA00032932 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
D6A4531E29EF64BA00032932 /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = "<group>"; };
|
||||||
|
D6A4532D29EF7DDD00032932 /* ShareHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareHostingController.swift; sourceTree = "<group>"; };
|
||||||
|
D6A4532F29EF7DEE00032932 /* ShareMastodonContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareMastodonContext.swift; sourceTree = "<group>"; };
|
||||||
D6A4DCCA2553667800D9DE31 /* FastAccountSwitcherViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FastAccountSwitcherViewController.swift; sourceTree = "<group>"; };
|
D6A4DCCA2553667800D9DE31 /* FastAccountSwitcherViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FastAccountSwitcherViewController.swift; sourceTree = "<group>"; };
|
||||||
D6A4DCCB2553667800D9DE31 /* FastAccountSwitcherViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FastAccountSwitcherViewController.xib; sourceTree = "<group>"; };
|
D6A4DCCB2553667800D9DE31 /* FastAccountSwitcherViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FastAccountSwitcherViewController.xib; sourceTree = "<group>"; };
|
||||||
D6A4DCE425537C7A00D9DE31 /* FastSwitchingAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FastSwitchingAccountView.swift; sourceTree = "<group>"; };
|
D6A4DCE425537C7A00D9DE31 /* FastSwitchingAccountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FastSwitchingAccountView.swift; sourceTree = "<group>"; };
|
||||||
|
@ -723,6 +748,18 @@
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
D6A4531029EF64BA00032932 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D6A4532829EF665800032932 /* Pachyderm in Frameworks */,
|
||||||
|
D6A4532A29EF665A00032932 /* TuskerPreferences in Frameworks */,
|
||||||
|
D6A4532629EF665600032932 /* InstanceFeatures in Frameworks */,
|
||||||
|
D6A4532C29EF665D00032932 /* UserAccounts in Frameworks */,
|
||||||
|
D6A4532429EF665200032932 /* ComposeUI in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
D6D4DDC9212518A000E1C4BB /* Frameworks */ = {
|
D6D4DDC9212518A000E1C4BB /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -1264,6 +1301,19 @@
|
||||||
path = "Status Action Account List";
|
path = "Status Action Account List";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D6A4531429EF64BA00032932 /* ShareExtension */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D6A4531E29EF64BA00032932 /* ShareExtension.entitlements */,
|
||||||
|
D6A4532F29EF7DEE00032932 /* ShareMastodonContext.swift */,
|
||||||
|
D6A4531529EF64BA00032932 /* ShareViewController.swift */,
|
||||||
|
D6A4532D29EF7DDD00032932 /* ShareHostingController.swift */,
|
||||||
|
D6A4531729EF64BA00032932 /* MainInterface.storyboard */,
|
||||||
|
D6A4531A29EF64BA00032932 /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = ShareExtension;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D6A4DCC92553666600D9DE31 /* Fast Account Switcher */ = {
|
D6A4DCC92553666600D9DE31 /* Fast Account Switcher */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1408,6 +1458,7 @@
|
||||||
D6D4DDE3212518A200E1C4BB /* TuskerTests */,
|
D6D4DDE3212518A200E1C4BB /* TuskerTests */,
|
||||||
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
|
||||||
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
D6E343A9265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
|
D6A4531429EF64BA00032932 /* ShareExtension */,
|
||||||
D6D4DDCD212518A000E1C4BB /* Products */,
|
D6D4DDCD212518A000E1C4BB /* Products */,
|
||||||
D65A37F221472F300087646E /* Frameworks */,
|
D65A37F221472F300087646E /* Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -1420,6 +1471,7 @@
|
||||||
D6D4DDE0212518A200E1C4BB /* TuskerTests.xctest */,
|
D6D4DDE0212518A200E1C4BB /* TuskerTests.xctest */,
|
||||||
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
D6D4DDEB212518A200E1C4BB /* TuskerUITests.xctest */,
|
||||||
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
D6E343A8265AAD6B00C4AA01 /* OpenInTusker.appex */,
|
||||||
|
D6A4531329EF64BA00032932 /* ShareExtension.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1578,6 +1630,30 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
D6A4531229EF64BA00032932 /* ShareExtension */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */;
|
||||||
|
buildPhases = (
|
||||||
|
D6A4530F29EF64BA00032932 /* Sources */,
|
||||||
|
D6A4531029EF64BA00032932 /* Frameworks */,
|
||||||
|
D6A4531129EF64BA00032932 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
name = ShareExtension;
|
||||||
|
packageProductDependencies = (
|
||||||
|
D6A4532329EF665200032932 /* ComposeUI */,
|
||||||
|
D6A4532529EF665600032932 /* InstanceFeatures */,
|
||||||
|
D6A4532729EF665800032932 /* Pachyderm */,
|
||||||
|
D6A4532929EF665A00032932 /* TuskerPreferences */,
|
||||||
|
D6A4532B29EF665D00032932 /* UserAccounts */,
|
||||||
|
);
|
||||||
|
productName = ShareExtension;
|
||||||
|
productReference = D6A4531329EF64BA00032932 /* ShareExtension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
D6D4DDCB212518A000E1C4BB /* Tusker */ = {
|
D6D4DDCB212518A000E1C4BB /* Tusker */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = D6D4DDF4212518A200E1C4BB /* Build configuration list for PBXNativeTarget "Tusker" */;
|
buildConfigurationList = D6D4DDF4212518A200E1C4BB /* Build configuration list for PBXNativeTarget "Tusker" */;
|
||||||
|
@ -1594,6 +1670,7 @@
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
D6E343B3265AAD6B00C4AA01 /* PBXTargetDependency */,
|
||||||
|
D6A4531C29EF64BA00032932 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Tusker;
|
name = Tusker;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
|
@ -1676,10 +1753,13 @@
|
||||||
D6D4DDC4212518A000E1C4BB /* Project object */ = {
|
D6D4DDC4212518A000E1C4BB /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1250;
|
LastSwiftUpdateCheck = 1430;
|
||||||
LastUpgradeCheck = 1400;
|
LastUpgradeCheck = 1400;
|
||||||
ORGANIZATIONNAME = Shadowfacts;
|
ORGANIZATIONNAME = Shadowfacts;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
D6A4531229EF64BA00032932 = {
|
||||||
|
CreatedOnToolsVersion = 14.3;
|
||||||
|
};
|
||||||
D6D4DDCB212518A000E1C4BB = {
|
D6D4DDCB212518A000E1C4BB = {
|
||||||
CreatedOnToolsVersion = 10.0;
|
CreatedOnToolsVersion = 10.0;
|
||||||
LastSwiftMigration = 1420;
|
LastSwiftMigration = 1420;
|
||||||
|
@ -1728,11 +1808,20 @@
|
||||||
D6D4DDDF212518A200E1C4BB /* TuskerTests */,
|
D6D4DDDF212518A200E1C4BB /* TuskerTests */,
|
||||||
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
D6D4DDEA212518A200E1C4BB /* TuskerUITests */,
|
||||||
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
D6E343A7265AAD6B00C4AA01 /* OpenInTusker */,
|
||||||
|
D6A4531229EF64BA00032932 /* ShareExtension */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
D6A4531129EF64BA00032932 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D6A4531929EF64BA00032932 /* MainInterface.storyboard in Resources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
D6D4DDCA212518A000E1C4BB /* Resources */ = {
|
D6D4DDCA212518A000E1C4BB /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -1832,6 +1921,16 @@
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
D6A4530F29EF64BA00032932 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D6A4532E29EF7DDD00032932 /* ShareHostingController.swift in Sources */,
|
||||||
|
D6A4531629EF64BA00032932 /* ShareViewController.swift in Sources */,
|
||||||
|
D6A4533029EF7DEE00032932 /* ShareMastodonContext.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
D6D4DDC8212518A000E1C4BB /* Sources */ = {
|
D6D4DDC8212518A000E1C4BB /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -2150,6 +2249,11 @@
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
D6A4531C29EF64BA00032932 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = D6A4531229EF64BA00032932 /* ShareExtension */;
|
||||||
|
targetProxy = D6A4531B29EF64BA00032932 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
D6D4DDE2212518A200E1C4BB /* PBXTargetDependency */ = {
|
D6D4DDE2212518A200E1C4BB /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = D6D4DDCB212518A000E1C4BB /* Tusker */;
|
target = D6D4DDCB212518A000E1C4BB /* Tusker */;
|
||||||
|
@ -2169,6 +2273,14 @@
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
|
D6A4531729EF64BA00032932 /* MainInterface.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
D6A4531829EF64BA00032932 /* Base */,
|
||||||
|
);
|
||||||
|
name = MainInterface.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */ = {
|
D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -2349,6 +2461,93 @@
|
||||||
};
|
};
|
||||||
name = Dist;
|
name = Dist;
|
||||||
};
|
};
|
||||||
|
D6A4531F29EF64BA00032932 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Shadowfacts. All rights reserved.";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
D6A4532029EF64BA00032932 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Shadowfacts. All rights reserved.";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
D6A4532129EF64BA00032932 /* Dist */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = ShareExtension;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Shadowfacts. All rights reserved.";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = space.vaccor.Tusker.ShareExtension;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SUPPORTS_MACCATALYST = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Dist;
|
||||||
|
};
|
||||||
D6D4DDF2212518A200E1C4BB /* Debug */ = {
|
D6D4DDF2212518A200E1C4BB /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = D6D706A829498C82000827ED /* Tusker.xcconfig */;
|
baseConfigurationReference = D6D706A829498C82000827ED /* Tusker.xcconfig */;
|
||||||
|
@ -2667,6 +2866,16 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
D6A4532229EF64BA00032932 /* Build configuration list for PBXNativeTarget "ShareExtension" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
D6A4531F29EF64BA00032932 /* Debug */,
|
||||||
|
D6A4532029EF64BA00032932 /* Release */,
|
||||||
|
D6A4532129EF64BA00032932 /* Dist */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
D6D4DDC7212518A000E1C4BB /* Build configuration list for PBXProject "Tusker" */ = {
|
D6D4DDC7212518A000E1C4BB /* Build configuration list for PBXProject "Tusker" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
@ -2791,6 +3000,26 @@
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = Pachyderm;
|
productName = Pachyderm;
|
||||||
};
|
};
|
||||||
|
D6A4532329EF665200032932 /* ComposeUI */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = ComposeUI;
|
||||||
|
};
|
||||||
|
D6A4532529EF665600032932 /* InstanceFeatures */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = InstanceFeatures;
|
||||||
|
};
|
||||||
|
D6A4532729EF665800032932 /* Pachyderm */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = Pachyderm;
|
||||||
|
};
|
||||||
|
D6A4532929EF665A00032932 /* TuskerPreferences */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = TuskerPreferences;
|
||||||
|
};
|
||||||
|
D6A4532B29EF665D00032932 /* UserAccounts */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = UserAccounts;
|
||||||
|
};
|
||||||
D6B0026D29B5248800C70BE2 /* UserAccounts */ = {
|
D6B0026D29B5248800C70BE2 /* UserAccounts */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
productName = UserAccounts;
|
productName = UserAccounts;
|
||||||
|
|
Loading…
Reference in New Issue