Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ios/instagram): implement share video on instagram with support to limited photos picker #117

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 150 additions & 34 deletions ios/Classes/SwiftFlutterShareMePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class SwiftFlutterShareMePlugin: NSObject, FlutterPlugin, SharingDelegate

var result: FlutterResult?
var documentInteractionController: UIDocumentInteractionController?
var onPickFileCompletionHandler: ((String?) -> Void)? = nil


public static func register(with registrar: FlutterPluginRegistrar) {
Expand Down Expand Up @@ -68,7 +69,7 @@ public class SwiftFlutterShareMePlugin: NSObject, FlutterPlugin, SharingDelegate
}
else if(call.method.elementsEqual(_methodInstagram)){
let args = call.arguments as? Dictionary<String,Any>
shareInstagram(args: args!)
shareInstagram(args: args!, result: result)
}
else if(call.method.elementsEqual(_methodTelegramShare)){
let args = call.arguments as? Dictionary<String,Any>
Expand Down Expand Up @@ -272,48 +273,52 @@ public class SwiftFlutterShareMePlugin: NSObject, FlutterPlugin, SharingDelegate

// share image via instagram stories.
// @ args image url
func shareInstagram(args:Dictionary<String,Any>) {
let imageUrl=args["url"] as! String

let image = UIImage(named: imageUrl)
if(image==nil){
self.result!("File format not supported Please check the file.")
return;
}
func shareInstagram(args: Dictionary<String,Any>, result: @escaping FlutterResult) {
let file = args["url"] as! String
let fileType = args["fileType"] as! String

guard let instagramURL = NSURL(string: "instagram://app") else {
if let result = result {
self.result?("Instagram app is not installed on your device")
result(false)
}
result("Instagram app is not installed on your device")
return
}

do{
try PHPhotoLibrary.shared().performChangesAndWait {
let request = PHAssetChangeRequest.creationRequestForAsset(from: image!)
let assetId = request.placeholderForCreatedAsset?.localIdentifier
let instShareUrl:String? = "instagram://library?LocalIdentifier=" + assetId!

//Share image
self.requestAddFileToPhotoLibraryPermission { newStatus in
print("The new status is \(newStatus.rawValue)")

if #available(iOS 14, *) {
if ![PHAuthorizationStatus.authorized, PHAuthorizationStatus.limited].contains(newStatus) {
result("permission not granted")
return
}
} else {
if newStatus != .authorized {
result("permission not granted")
return
}
}

self.addFileToPhotoLibrary(to: file, fileType: fileType) { destinationIdentifier in
guard let destinationIdentifier else {
result("failed to save file to library")
return
}

let instaShareUrl = "instagram://library?LocalIdentifier=\(destinationIdentifier)"

// Share file
if UIApplication.shared.canOpenURL(instagramURL as URL) {
if let sharingUrl = instShareUrl {
if let urlForRedirect = NSURL(string: sharingUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(urlForRedirect as URL, options: [:], completionHandler: nil)
}
else{
UIApplication.shared.openURL(urlForRedirect as URL)
}
if let urlForRedirect = NSURL(string: instaShareUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(urlForRedirect as URL, options: [:], completionHandler: nil)
} else{
UIApplication.shared.openURL(urlForRedirect as URL)
}
self.result?("Success")
}
} else{
self.result?("Instagram app is not installed on your device")
result("Success")
} else {
result("Instagram app is not installed on your device")
}
}

} catch {
print("Fail")
}
}

Expand All @@ -331,4 +336,115 @@ public class SwiftFlutterShareMePlugin: NSObject, FlutterPlugin, SharingDelegate
public func sharerDidCancel(_ sharer: Sharing) {
print("Share: Cancel")
}

private func requestAddFileToPhotoLibraryPermission(_ completionHandler: @escaping (PHAuthorizationStatus) -> Void ) {
if #available(iOS 14.0, *) {
let status = PHPhotoLibrary.authorizationStatus(for: .readWrite)
if [PHAuthorizationStatus.authorized, PHAuthorizationStatus.limited].contains(status) {
completionHandler(status)
return
}

PHPhotoLibrary.requestAuthorization(for: .readWrite) { newStatus in
completionHandler(newStatus)
}
} else {
PHPhotoLibrary.requestAuthorization { newStatus in
completionHandler(newStatus)
}
}
}

private func addFileToPhotoLibrary(to filePath: String,
fileType: String,
completionHandler: @escaping (String?) -> Void) {
guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) as NSData else {
print("error getting file data")
completionHandler(nil)
return
}

PHPhotoLibrary.shared().performChanges {
if fileType == "image" {
PHAssetChangeRequest.creationRequestForAssetFromImage(
atFileURL: URL(fileURLWithPath: filePath)
)
} else {
PHAssetChangeRequest.creationRequestForAssetFromVideo(
atFileURL: URL(fileURLWithPath: filePath)
)
}
} completionHandler: { success, error in
if let error {
print("error saving file to PHPhotoLibrary \(error.localizedDescription)")
}

if success {
if #available(iOS 14, *),
PHPhotoLibrary.authorizationStatus(for: .readWrite) == PHAuthorizationStatus.limited {
self.displayPHPhotoPicker { fileIdentifier in
completionHandler(fileIdentifier)
}
return
}

let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",
ascending: false)]
let fetchResult = PHAsset.fetchAssets(
with: fileType == "image" ? .image : .video,
options: fetchOptions
)

if let assetToShare = fetchResult.firstObject {
completionHandler(assetToShare.localIdentifier)
return
} else {
print("error querying file asset")
}
}

completionHandler(nil)
}
}
}

// - MARK: PHPickerViewControllerDelegate
@available(iOS 14, *)
extension SwiftFlutterShareMePlugin: PHPickerViewControllerDelegate {
private func displayPHPhotoPicker(completionHandler: ((String?) -> Void)?) {
self.onPickFileCompletionHandler = completionHandler
DispatchQueue.main.async {
self.triggerPicker()
}
}

@IBAction private func triggerPicker() {
let photoLibrary = PHPhotoLibrary.shared()
var configuration = PHPickerConfiguration(photoLibrary: photoLibrary)
configuration.selectionLimit = 1
configuration.preferredAssetRepresentationMode = .compatible

let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self

UIApplication.shared.keyWindow?.rootViewController?.present(picker, animated: true)
}

public func picker(_ picker: PHPickerViewController,
didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
let identifiers = results.compactMap(\.assetIdentifier)
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",
ascending: false)]
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: fetchOptions)
guard let localId = fetchResult.firstObject else {
print("no asset selected")
self.onPickFileCompletionHandler?(nil)
return
}

self.onPickFileCompletionHandler?(localId.localIdentifier)
}
}