diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 6754bd46c..3c7d16faf 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,19 +1,37 @@
import UIKit
import Flutter
import flutter_downloader
+import receive_sharing_intent
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
- override func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
- ) -> Bool {
- GeneratedPluginRegistrant.register(with: self)
- FlutterDownloaderPlugin.setPluginRegistrantCallback { registry in
- if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
- FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
- }
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ FlutterDownloaderPlugin.setPluginRegistrantCallback { registry in
+ if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
+ FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
+ }
+ }
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
- }
+
+ override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ let sharingIntent = SwiftReceiveSharingIntentPlugin.instance
+ if sharingIntent.hasMatchingSchemePrefix(url: url) {
+ return sharingIntent.application(app, open: url, options: options)
+ }
+
+ // For example load MSALPublicClientApplication
+ // return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[.sourceApplication] as? String)
+
+ // Cancel url handling
+ // return false
+
+ // Proceed url handling for other Flutter libraries like uni_links
+ return super.application(app, open: url, options:options)
+ }
+
}
diff --git a/ios/TeamMailShareExtension/Info.plist b/ios/TeamMailShareExtension/Info.plist
index 9a277dcf4..02caa4087 100644
--- a/ios/TeamMailShareExtension/Info.plist
+++ b/ios/TeamMailShareExtension/Info.plist
@@ -26,11 +26,22 @@
NSExtensionActivationRule
+ NSExtensionActivationSupportsFileWithMaxCount
+ 15
+ NSExtensionActivationSupportsImageWithMaxCount
+ 15
+ NSExtensionActivationSupportsMovieWithMaxCount
+ 15
NSExtensionActivationSupportsText
-
- NSExtensionActivationSupportsWebURLWithMaxCount
- 1
+
+ NSExtensionActivationSupportsWebURLWithMaxCount
+ 1
+ PHSupportedMediaTypes
+
+ Video
+ Image
+
NSExtensionMainStoryboard
MainInterface
@@ -38,4 +49,4 @@
com.apple.share-services
-
\ No newline at end of file
+
diff --git a/ios/TeamMailShareExtension/ShareViewController.swift b/ios/TeamMailShareExtension/ShareViewController.swift
index dbf47151e..776386a35 100644
--- a/ios/TeamMailShareExtension/ShareViewController.swift
+++ b/ios/TeamMailShareExtension/ShareViewController.swift
@@ -1,28 +1,42 @@
-//
-// ShareViewController.swift
-// TeamMailShareExtension
-//
-// Created by dab.dev on 06/04/2022.
-//
-
import UIKit
import Social
import MobileCoreServices
+import Photos
class ShareViewController: SLComposeServiceViewController {
-
- let hostAppBundleIdentifier = "com.linagora.teammail"
+ var hostAppBundleIdentifier = ""
+ let appGroupId = "group.com.linagora.teammail"
let sharedKey = "ShareKey"
+ var sharedMedia: [SharedMediaFile] = []
var sharedText: [String] = []
+ let imageContentType = kUTTypeImage as String
+ let videoContentType = kUTTypeMovie as String
let textContentType = kUTTypeText as String
let urlContentType = kUTTypeURL as String
+ let fileURLType = kUTTypeFileURL as String;
override func isContentValid() -> Bool {
return true
}
+ private func loadIds() {
+ // loading Share extension App Id
+ let shareExtensionAppBundleIdentifier = Bundle.main.bundleIdentifier!;
+
+
+ // convert ShareExtension id to host app id
+ // By default it is remove last part of id after last point
+ // For example: com.test.ShareExtension -> com.test
+ let lastIndexOfPoint = shareExtensionAppBundleIdentifier.lastIndex(of: ".");
+ hostAppBundleIdentifier = String(shareExtensionAppBundleIdentifier[.. String {
+ let parts = url.lastPathComponent.components(separatedBy: ".")
+ var ex: String? = nil
+ if (parts.count > 1) {
+ ex = parts.last
+ }
+
+ if (ex == nil) {
+ switch type {
+ case .image:
+ ex = "PNG"
+ case .video:
+ ex = "MP4"
+ case .file:
+ ex = "TXT"
+ }
+ }
+ return ex ?? "Unknown"
+ }
+
+ func getFileName(from url: URL, type: SharedMediaType) -> String {
+ var name = url.lastPathComponent
+
+ if (name.isEmpty) {
+ name = UUID().uuidString + "." + getExtension(from: url, type: type)
+ }
+
+ return name
+ }
+
+ func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
+ do {
+ if FileManager.default.fileExists(atPath: dstURL.path) {
+ try FileManager.default.removeItem(at: dstURL)
+ }
+ try FileManager.default.copyItem(at: srcURL, to: dstURL)
+ } catch (let error) {
+ print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
+ return false
+ }
+ return true
+ }
+
+ private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? {
+ let asset = AVAsset(url: forVideo)
+ let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
+ let thumbnailPath = getThumbnailPath(for: forVideo)
+
+ if FileManager.default.fileExists(atPath: thumbnailPath.path) {
+ return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video)
+ }
+
+ var saved = false
+ let assetImgGenerate = AVAssetImageGenerator(asset: asset)
+ assetImgGenerate.appliesPreferredTrackTransform = true
+ // let scale = UIScreen.main.scale
+ assetImgGenerate.maximumSize = CGSize(width: 360, height: 360)
+ do {
+ let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(600, preferredTimescale: Int32(1.0)), actualTime: nil)
+ try UIImage.pngData(UIImage(cgImage: img))()?.write(to: thumbnailPath)
+ saved = true
+ } catch {
+ saved = false
+ }
+
+ return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil
+
+ }
+
+ private func getThumbnailPath(for url: URL) -> URL {
+ let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "")
+ let path = FileManager.default
+ .containerURL(forSecurityApplicationGroupIdentifier: appGroupId)!
+ .appendingPathComponent("\(fileName).jpg")
+ return path
+ }
+
+ class SharedMediaFile: Codable {
+ var path: String; // can be image, video or url path. It can also be text content
+ var thumbnail: String?; // video thumbnail
+ var duration: Double?; // video duration in milliseconds
+ var type: SharedMediaType;
+
+
+ init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) {
+ self.path = path
+ self.thumbnail = thumbnail
+ self.duration = duration
+ self.type = type
+ }
+
+ // Debug method to print out SharedMediaFile details in the console
+ func toString() {
+ print("[SharedMediaFile] \n\tpath: \(self.path)\n\tthumbnail: \(self.thumbnail)\n\tduration: \(self.duration)\n\ttype: \(self.type)")
+ }
+ }
+
+ enum SharedMediaType: Int, Codable {
+ case image
+ case video
+ case file
+ }
+
+ func toData(data: [SharedMediaFile]) -> Data {
+ let encodedData = try? JSONEncoder().encode(data)
+ return encodedData!
+ }
}
extension Array {
diff --git a/pubspec.yaml b/pubspec.yaml
index b92a85c9c..7b9716028 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -144,7 +144,10 @@ dependencies:
package_info_plus: 1.4.1
- receive_sharing_intent: 1.4.5
+ receive_sharing_intent:
+ git:
+ url: https://github.com/ManhNTX/receive_sharing_intent.git
+ ref: master
dropdown_button2: 1.4.0