Code Monkey home page Code Monkey logo

Comments (11)

tarangshah19 avatar tarangshah19 commented on July 18, 2024 1

thanks

from send-intent.

tarangshah19 avatar tarangshah19 commented on July 18, 2024

hi i dont have solution but i am not able to do successfully on ios can you please tell how you add and how you create group id or if you dont mind can you share code please

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

Hello,

thankYou for your answer.

Im using your code from doc. See details below.

AppDelegate.swift
`import UIKit
import Capacitor
import SendIntent

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
let store = ShareStore.store

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    return true
}

func applicationWillResignActive(_ application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}

func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}

func applicationDidBecomeActive(_ application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

    var success = true
    if CAPBridge.handleOpenUrl(url, options) {
        success = ApplicationDelegateProxy.shared.application(app, open: url, options: options)
    }

    guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
          let params = components.queryItems else {
              return false
          }

    let titles = params.filter { $0.name == "title" }
    let descriptions = params.filter { $0.name == "description" }
    let types = params.filter { $0.name == "type" }
    let urls = params.filter { $0.name == "url" }

    store.shareItems.removeAll()
    if(titles.count > 0){
        for index in 0...titles.count-1 {
            var shareItem: JSObject = JSObject()
            shareItem["title"] = titles[index].value!
            shareItem["description"] = descriptions[index].value!
            shareItem["type"] = types[index].value!
            shareItem["url"] = urls[index].value!
            store.shareItems.append(shareItem)
        }
    }

    dump(store.shareItems)

    store.processed = false
    let nc = NotificationCenter.default
    nc.post(name: Notification.Name("triggerSendIntent"), object: nil )

    return success
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // Called when the app was launched with an activity, including Universal Links.
    // Feel free to add additional processing here, but if you want the App API to support
    // tracking app url opens, make sure to keep this call
    return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
  NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}

}
`
ShareViewController.swift

`
import MobileCoreServices
import Social
import UIKit

class ShareItem {

public var title: String?
public var type: String?
public var url: String?

}

class ShareViewController: UIViewController {

private var shareItems: [ShareItem] = []

override public func viewDidAppear(_ animated: Bool) {
   super.viewDidAppear(animated)
   self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}

private func sendData() {
    let queryItems = shareItems.map {
        [
            URLQueryItem(
                name: "title",
                value: $0.title?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
            URLQueryItem(name: "description", value: ""),
            URLQueryItem(
                name: "type",
                value: $0.type?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
            URLQueryItem(
                name: "url",
                value: $0.url?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""),
        ]
    }.flatMap({ $0 })

    var urlComps = URLComponents(string: "vcpgo://")!
    urlComps.queryItems = queryItems
    openURL(urlComps.url!)
}

fileprivate func createSharedFileUrl(_ url: URL?) -> String {
    let fileManager = FileManager.default

    let copyFileUrl =
    fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.vcpgo")!
        .absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! + "/" + url!
        .lastPathComponent.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
    try? Data(contentsOf: url!).write(to: URL(string: copyFileUrl)!)

    return copyFileUrl
}

func saveScreenshot(_ image: UIImage) -> String {
    let fileManager = FileManager.default

    let copyFileUrl =
    fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.vcpgo")!
        .absoluteString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
    + "/screenshot.png"
    do {
        try image.pngData()?.write(to: URL(string: copyFileUrl)!)
        return copyFileUrl
    } catch {
        print(error.localizedDescription)
        return ""
    }
}

fileprivate func handleTypeUrl(_ attachment: NSItemProvider)
async throws -> ShareItem
{
    let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil)
    let url = results as! URL?
    let shareItem: ShareItem = ShareItem()
    
    if url!.isFileURL {
        shareItem.title = url!.lastPathComponent
        shareItem.type = "application/" + url!.pathExtension.lowercased()
        shareItem.url = createSharedFileUrl(url)
    } else {
        shareItem.title = url!.absoluteString
        shareItem.url = url!.absoluteString
        shareItem.type = "text/plain"
    }
    
    return shareItem
}

fileprivate func handleTypeText(_ attachment: NSItemProvider)
async throws -> ShareItem
{
    let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeText as String, options: nil)
    let shareItem: ShareItem = ShareItem()
    let text = results as! String
    shareItem.title = text
    shareItem.type = "text/plain"
    return shareItem
}

fileprivate func handleTypeMovie(_ attachment: NSItemProvider)
async throws -> ShareItem
{
    let results = try await attachment.loadItem(forTypeIdentifier: kUTTypeMovie as String, options: nil)
    let shareItem: ShareItem = ShareItem()
    
    let url = results as! URL?
    shareItem.title = url!.lastPathComponent
    shareItem.type = "video/" + url!.pathExtension.lowercased()
    shareItem.url = createSharedFileUrl(url)
    return shareItem
}

fileprivate func handleTypeImage(_ attachment: NSItemProvider)
async throws -> ShareItem
{
    let data = try await attachment.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil)
    
    let shareItem: ShareItem = ShareItem()
    switch data {
    case let image as UIImage:
        shareItem.title = "screenshot"
        shareItem.type = "image/png"
        shareItem.url = self.saveScreenshot(image)
    case let url as URL:
        shareItem.title = url.lastPathComponent
        shareItem.type = "image/" + url.pathExtension.lowercased()
        shareItem.url = self.createSharedFileUrl(url)
    default:
        print("Unexpected image data:", type(of: data))
    }
    return shareItem
}

override public func viewDidLoad() {
    super.viewDidLoad()
    
    shareItems.removeAll()
    
    let extensionItem = extensionContext?.inputItems[0] as! NSExtensionItem
    Task {
        try await withThrowingTaskGroup(
            of: ShareItem.self,
            body: { taskGroup in
                
                for attachment in extensionItem.attachments! {
                    if attachment.hasItemConformingToTypeIdentifier(kUTTypeURL as String) {
                        taskGroup.addTask {
                            return try await self.handleTypeUrl(attachment)
                        }
                    } else if attachment.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
                        taskGroup.addTask {
                            return try await self.handleTypeText(attachment)
                        }
                    } else if attachment.hasItemConformingToTypeIdentifier(kUTTypeMovie as String) {
                        taskGroup.addTask {
                            return try await self.handleTypeMovie(attachment)
                        }
                    } else if attachment.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
                        taskGroup.addTask {
                            return try await self.handleTypeImage(attachment)
                        }
                    }
                }
                
                for try await item in taskGroup {
                    self.shareItems.append(item)
                }
            })
        
        self.sendData()
        
    }
}

@objc func openURL(_ url: URL) -> Bool {
    var responder: UIResponder? = self
    while responder != nil {
        if let application = responder as? UIApplication {
            return application.perform(#selector(openURL(_:)), with: url) != nil
        }
        responder = responder?.next
    }
    return false
}

}
`
Dump from AppDelegate.swift shows following data. Even if Im sharing 5 different files, in the dump you can see one exact file 5 times instead of 5 different files.

5 elements ▿ 4 key/value pairs ▿ (2 elements) - key: "title" - value: "PHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "description" - value: "" ▿ (2 elements) - key: "type" - value: "application%2Fjpg" ▿ (2 elements) - key: "url" - value: "file%3A%2F%2F%2Fprivate%2Fvar%2Fmobile%2FContainers%2FShared%2FAppGroup%2FAF4D217D-A918-4245-9C60-ACDF619D2EBC%2F%2FPHOTO-2023-03-24-09-49-39.jpg" ▿ 4 key/value pairs ▿ (2 elements) - key: "url" - value: "file%3A%2F%2F%2Fprivate%2Fvar%2Fmobile%2FContainers%2FShared%2FAppGroup%2FAF4D217D-A918-4245-9C60-ACDF619D2EBC%2F%2FPHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "type" - value: "application%2Fjpg" ▿ (2 elements) - key: "description" - value: "" ▿ (2 elements) - key: "title" - value: "PHOTO-2023-03-24-09-49-39.jpg" ▿ 4 key/value pairs ▿ (2 elements) - key: "title" - value: "PHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "url" - value: "file%3A%2F%2F%2Fprivate%2Fvar%2Fmobile%2FContainers%2FShared%2FAppGroup%2FAF4D217D-A918-4245-9C60-ACDF619D2EBC%2F%2FPHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "type" - value: "application%2Fjpg" ▿ (2 elements) - key: "description" - value: "" ▿ 4 key/value pairs ▿ (2 elements) - key: "description" - value: "" ▿ (2 elements) - key: "type" - value: "application%2Fjpg" ▿ (2 elements) - key: "title" - value: "PHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "url" - value: "file%3A%2F%2F%2Fprivate%2Fvar%2Fmobile%2FContainers%2FShared%2FAppGroup%2FAF4D217D-A918-4245-9C60-ACDF619D2EBC%2F%2FPHOTO-2023-03-24-09-49-39.jpg" ▿ 4 key/value pairs ▿ (2 elements) - key: "title" - value: "PHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "url" - value: "file%3A%2F%2F%2Fprivate%2Fvar%2Fmobile%2FContainers%2FShared%2FAppGroup%2FAF4D217D-A918-4245-9C60-ACDF619D2EBC%2F%2FPHOTO-2023-03-24-09-49-39.jpg" ▿ (2 elements) - key: "type" - value: "application%2Fjpg" ▿ (2 elements) - key: "description" - value: ""

from send-intent.

carsten-klaffke avatar carsten-klaffke commented on July 18, 2024

Hello! Is this only on Whatsapp? Have you tried debugging ShareViewController.swift to see if the data arrives correctly at the plugin? (If not, I will test it later but I will have to set up a case first)
Best regards

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

@carsten-klaffke Hi, it only happens when I share from WhatsApp, sharing multiple files from gallery works great. I tried to debug ShareViewController but I was not able to come to anything. ThankYou very much.

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

@tarangshah19 @carsten-klaffke Guys, any update on this issue please?

from send-intent.

carsten-klaffke avatar carsten-klaffke commented on July 18, 2024

I created an Example (uploaded it to this repository) to test multiple file share. But I only have an iPad (no iPhone) and Whatsapp is not available for that. If you'd find another app where this happens, I could test it. Otherwise I have to wait to get an iPhone borrowed.

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

@carsten-klaffke same thing happens when you share from Telegram or Signal messaging app, can you please test it in one of those apps, they might be available for iPad, ThankYou!

from send-intent.

carsten-klaffke avatar carsten-klaffke commented on July 18, 2024

Hey @StepZEROsk, I was now able to reproduce the bug (with Signal). There was an error in ShareViewController.swift, which put the same name for all images if they come as type image and not URL. I fixed it in the Code of SendIntentExample and also updated the Readme accordingly. Please let me know if this solves it for you!

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

@carsten-klaffke it works with Signal and Telegram, but still doesn't work with WhatsApp. Im not sure what the different is, but when I share from WhatsApp i'm getting the actual file name, not the name generated with the index, like Im getting from Signal and Telegram.

from send-intent.

StepZEROsk avatar StepZEROsk commented on July 18, 2024

@carsten-klaffke From WhatsApp they comes like URL

from send-intent.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.