feat: extension code to send image to servers

This commit is contained in:
Rio Keefe
2025-05-03 10:40:36 +01:00
parent cd39559834
commit 2a838c81f2

View File

@ -7,24 +7,97 @@
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: "http://192.168.1.199:3040/image/")!
var bearerToken: String?
override func viewDidLoad() {
super.viewDidLoad()
// Load the bearer token from the App Group
if let sharedDefaults = UserDefaults(suiteName: appGroupName) {
bearerToken = sharedDefaults.string(forKey: tokenKey)
print("Retrieved bearer token: \(bearerToken ?? "nil")")
} else {
print("Error accessing App Group UserDefaults.")
}
if let item = extensionContext?.inputItems.first as? NSExtensionItem,
let provider = item.attachments?.first as? NSItemProvider {
if provider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
let semaphore = DispatchSemaphore(value: 0)
var rawImageData: Data?
var extractedName = "image.png" // Default name
provider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] (item, error) in
guard let self = self else {
semaphore.signal()
return
}
if let url = item as? URL, let data = try? Data(contentsOf: url) {
rawImageData = data
extractedName = url.lastPathComponent
if let dotRange = extractedName.range(of: ".", options: .backwards) {
extractedName = String(extractedName[..<dotRange.lowerBound])
}
} else if let data = item as? Data {
rawImageData = data
extractedName = provider.suggestedName ?? "image"
} else {
print("Error loading image data: \(error?.localizedDescription ?? "Unknown error")")
self.extensionContext?.cancelRequest(withError: error ?? NSError(domain: "ShareExtension", code: -2, userInfo: nil))
}
semaphore.signal()
}
semaphore.wait()
if let dataToUpload = rawImageData {
self.uploadRawData(dataToUpload, imageName: extractedName, bearerToken: self.bearerToken)
}
} else {
print("No image found.")
self.extensionContext?.cancelRequest(withError: NSError(domain: "ShareExtension", code: -3, userInfo: nil))
}
}
}
func uploadRawData(_ rawData: Data, imageName: String, bearerToken: String?) {
guard let token = bearerToken else {
print("Bearer token is missing.")
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
return
}
let uploadURLwithName = uploadURL.appendingPathComponent(imageName)
var request = URLRequest(url: uploadURLwithName)
request.httpMethod = "POST"
request.httpBody = rawData
request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
print("Upload finished. Error: \(error?.localizedDescription ?? "None"), Response: \(response?.description ?? "None")")
self?.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}
task.resume()
}
override func isContentValid() -> Bool {
// Do validation of contentText and/or NSExtensionContext attachments here
return true
return true // Always valid for now
}
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
// Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
// The upload happens in uploadRawData after the data is loaded
}
override func configurationItems() -> [Any]! {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return []
}
}