chore: fix file cleanup on ios when sharing files into sn
This commit is contained in:
@@ -118,7 +118,18 @@ class ReceiveSharingIntent: NSObject {
|
|||||||
|
|
||||||
@objc
|
@objc
|
||||||
func clearFileNames(){
|
func clearFileNames(){
|
||||||
print("clearFileNames");
|
let containerURL = FileManager.default
|
||||||
|
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(Bundle.main.bundleIdentifier!)")!
|
||||||
|
let shareTempDirPath = containerURL.appendingPathComponent("ShareTemp", isDirectory: true)
|
||||||
|
do {
|
||||||
|
let fileNames = try FileManager.default.contentsOfDirectory(atPath: shareTempDirPath.relativePath)
|
||||||
|
for fileName in fileNames {
|
||||||
|
let filePath = shareTempDirPath.appendingPathComponent(fileName)
|
||||||
|
try FileManager.default.removeItem(at: filePath)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -95,16 +95,11 @@ class ShareViewController: SLComposeServiceViewController {
|
|||||||
attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in
|
attachment.loadItem(forTypeIdentifier: imageContentType, options: nil) { [weak self] data, error in
|
||||||
|
|
||||||
if error == nil, let url = data as? URL, let this = self {
|
if error == nil, let url = data as? URL, let this = self {
|
||||||
// this.redirectToHostApp(type: .media)
|
|
||||||
// Always copy
|
// Always copy
|
||||||
let fileExtension = this.getExtension(from: url, type: .video)
|
let fileExtension = this.getExtension(from: url, type: .video)
|
||||||
let newName = UUID().uuidString
|
let newName = UUID().uuidString
|
||||||
let newPath = FileManager.default
|
if let copiedPath = this.copyToTemporaryPath(url: url, name: "\(newName).\(fileExtension)") {
|
||||||
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
|
this.sharedMedia.append(SharedMediaFile(path: copiedPath, thumbnail: nil, duration: nil, type: .image))
|
||||||
.appendingPathComponent("\(newName).\(fileExtension)")
|
|
||||||
let copied = this.copyFile(at: url, to: newPath)
|
|
||||||
if(copied) {
|
|
||||||
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == (content.attachments?.count)! - 1 {
|
if index == (content.attachments?.count)! - 1 {
|
||||||
@@ -125,15 +120,8 @@ class ShareViewController: SLComposeServiceViewController {
|
|||||||
// Always copy
|
// Always copy
|
||||||
let fileExtension = this.getExtension(from: url, type: .video)
|
let fileExtension = this.getExtension(from: url, type: .video)
|
||||||
let newName = UUID().uuidString
|
let newName = UUID().uuidString
|
||||||
let newPath = FileManager.default
|
if let copiedPath = this.copyToTemporaryPath(url: url, name: "\(newName).\(fileExtension)") {
|
||||||
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
|
this.sharedMedia.append(SharedMediaFile(path: copiedPath, thumbnail: nil, duration: nil, type: .video))
|
||||||
.appendingPathComponent("\(newName).\(fileExtension)")
|
|
||||||
let copied = this.copyFile(at: url, to: newPath)
|
|
||||||
if(copied) {
|
|
||||||
guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.sharedMedia.append(sharedFile)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == (content.attachments?.count)! - 1 {
|
if index == (content.attachments?.count)! - 1 {
|
||||||
@@ -151,14 +139,9 @@ class ShareViewController: SLComposeServiceViewController {
|
|||||||
|
|
||||||
if error == nil, let url = data as? URL, let this = self {
|
if error == nil, let url = data as? URL, let this = self {
|
||||||
|
|
||||||
// Always copy
|
|
||||||
let newName = this.getFileName(from :url)
|
let newName = this.getFileName(from :url)
|
||||||
let newPath = FileManager.default
|
if let copiedPath = this.copyToTemporaryPath(url: url, name: newName) {
|
||||||
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
|
this.sharedMedia.append(SharedMediaFile(path: copiedPath, thumbnail: nil, duration: nil, type: .file))
|
||||||
.appendingPathComponent("\(newName)")
|
|
||||||
let copied = this.copyFile(at: url, to: newPath)
|
|
||||||
if (copied) {
|
|
||||||
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .file))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == (content.attachments?.count)! - 1 {
|
if index == (content.attachments?.count)! - 1 {
|
||||||
@@ -171,6 +154,32 @@ class ShareViewController: SLComposeServiceViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func directoryExistsAtPath(_ path: String) -> Bool {
|
||||||
|
var isDirectory = ObjCBool(true)
|
||||||
|
let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
|
||||||
|
return exists && isDirectory.boolValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private func copyToTemporaryPath(url: URL, name: String) -> String? {
|
||||||
|
let containerURL = FileManager.default
|
||||||
|
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
|
||||||
|
let shareTempDirPath = containerURL.appendingPathComponent("ShareTemp", isDirectory: true)
|
||||||
|
if !directoryExistsAtPath(shareTempDirPath.absoluteString) {
|
||||||
|
do {
|
||||||
|
try FileManager.default.createDirectory(atPath: shareTempDirPath.relativePath, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let newPath = shareTempDirPath
|
||||||
|
.appendingPathComponent("\(name)")
|
||||||
|
let copied = self.copyFile(at: url, to: newPath)
|
||||||
|
if (copied) {
|
||||||
|
return newPath.absoluteString
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
private func redirectToHostApp() {
|
private func redirectToHostApp() {
|
||||||
let userDefaults = UserDefaults(suiteName: "group.\(hostAppBundleIdentifier)")
|
let userDefaults = UserDefaults(suiteName: "group.\(hostAppBundleIdentifier)")
|
||||||
userDefaults?.set(self.toData(data: self.sharedMedia), forKey: "\(self.sharedKey).media")
|
userDefaults?.set(self.toData(data: self.sharedMedia), forKey: "\(self.sharedKey).media")
|
||||||
@@ -263,40 +272,6 @@ class ShareViewController: SLComposeServiceViewController {
|
|||||||
return true
|
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: "group.\(hostAppBundleIdentifier)")!
|
|
||||||
.appendingPathComponent("\(fileName).jpg")
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
class SharedMediaFile: Codable {
|
class SharedMediaFile: Codable {
|
||||||
var path: String; // can be image, video or url path. It can also be text content
|
var path: String; // can be image, video or url path. It can also be text content
|
||||||
var thumbnail: String?; // video thumbnail
|
var thumbnail: String?; // video thumbnail
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export class ReceivedSharedItemsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
|
ReceiveSharingIntent.clearFileNames()
|
||||||
this.receivedItemsQueue = []
|
this.receivedItemsQueue = []
|
||||||
this.eventSub?.remove()
|
this.eventSub?.remove()
|
||||||
}
|
}
|
||||||
@@ -100,17 +101,13 @@ export class ReceivedSharedItemsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleItemsQueue = async () => {
|
handleItemsQueue = async () => {
|
||||||
if (!this.receivedItemsQueue.length) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const item = this.receivedItemsQueue.shift()
|
const item = this.receivedItemsQueue.shift()
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isReceivedAndroidFile(item) || isReceivedIosFile(item)) {
|
if (isReceivedAndroidFile(item) || isReceivedIosFile(item)) {
|
||||||
this.sendFileToWebView(item).catch(console.error)
|
await this.sendFileToWebView(item).catch(console.error)
|
||||||
} else if (isReceivedWeblink(item)) {
|
} else if (isReceivedWeblink(item)) {
|
||||||
this.webViewRef.current?.postMessage(
|
this.webViewRef.current?.postMessage(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@@ -134,6 +131,14 @@ export class ReceivedSharedItemsHandler {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.receivedItemsQueue.length) {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
ReceiveSharingIntent.clearFileNames()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.handleItemsQueue().catch(console.error)
|
this.handleItemsQueue().catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +162,12 @@ export class ReceivedSharedItemsHandler {
|
|||||||
private addSharedItemsToQueue = async (url?: string) => {
|
private addSharedItemsToQueue = async (url?: string) => {
|
||||||
const received =
|
const received =
|
||||||
Platform.OS === 'ios' ? await ReceiveSharingIntent.getFileNames(url) : await ReceiveSharingIntent.getFileNames()
|
Platform.OS === 'ios' ? await ReceiveSharingIntent.getFileNames(url) : await ReceiveSharingIntent.getFileNames()
|
||||||
ReceiveSharingIntent.clearFileNames()
|
|
||||||
|
// On iOS, we need to wait for the whole queue
|
||||||
|
// to finish before clearing
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
ReceiveSharingIntent.clearFileNames()
|
||||||
|
}
|
||||||
|
|
||||||
if (!received) {
|
if (!received) {
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in New Issue
Block a user