// // //  ShareViewController.swift //  Haystack // //  Created by Rio Keefe on 03/05/2025. // import UIKit import Social import MobileCoreServices class ShareViewController: SLComposeServiceViewController { let appGroupName = "group.com.haystack.app" // Replace with your actual App Group identifier let tokenKey = "sharedAuthToken" let uploadURL = URL(string: "https://haystack.johncosta.tech/image/")! var bearerToken: String? // Store the item provider to access it later in didSelectPost private var imageItemProvider: NSItemProvider? private var extractedImageName: String = "image" // Default name override func viewDidLoad() { super.viewDidLoad() // Load the bearer token from the App Group in viewDidLoad // This is okay as reading from UserDefaults is fast if let sharedDefaults = UserDefaults(suiteName: appGroupName) { bearerToken = sharedDefaults.string(forKey: tokenKey) print("Retrieved bearer token: \(bearerToken ?? "nil")") } else { print("Error accessing App Group UserDefaults.") // Optionally inform the user or disable posting if token is crucial // self.isContentValid() could check if bearerToken is nil } // Store the item provider, but don't load the data synchronously yet if let item = extensionContext?.inputItems.first as? NSExtensionItem, let provider = item.attachments?.first as? NSItemProvider { if provider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) { self.imageItemProvider = provider // Attempt to get a suggested name early if available extractedImageName = provider.suggestedName ?? "image" if let dotRange = extractedImageName.range(of: ".", options: .backwards) { extractedImageName = String(extractedImageName[.. Bool { // Content is valid only if we have an item provider for an image AND a bearer token return imageItemProvider != nil && bearerToken != nil } override func didSelectPost() { // This method is called when the user taps the "Post" button. // Start the asynchronous operation here. guard let provider = imageItemProvider else { print("Error: No image item provider found when posting.") // Inform the user or log an error extensionContext!.completeRequest(returningItems: [], completionHandler: nil) return } guard let token = bearerToken else { print("Error: Bearer token is missing when posting.") // Inform the user or log an error extensionContext!.completeRequest(returningItems: [], completionHandler: nil) return } // Load the image data asynchronously provider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] (item, error) in guard let self = self else { return } if let error = error { print("Error loading image data for upload: \(error.localizedDescription)") // Inform the user about the failure self.extensionContext!.cancelRequest(withError: error) return } var rawImageData: Data? var finalImageName = self.extractedImageName // Use the name extracted earlier if let url = item as? URL, let data = try? Data(contentsOf: url) { rawImageData = data // Refine the name extraction here if necessary, though doing it in viewDidLoad is also an option finalImageName = url.lastPathComponent if let dotRange = finalImageName.range(of: ".", options: .backwards) { finalImageName = String(finalImageName[.. [Any]! { // You can add items here if you want to allow the user to enter additional info // e.g., a text field for a caption. // This example only handles image upload, so no config items are needed. return [] } }