diff --git a/mobile/app.json b/mobile/app.json index 8e39a01..3270b5d 100644 --- a/mobile/app.json +++ b/mobile/app.json @@ -57,6 +57,7 @@ "react-native-ble-plx", "expo-notifications", "expo-web-browser", + "./plugins/with-share-intent-multifile", [ "expo-share-intent", { diff --git a/mobile/plugins/with-share-intent-multifile.js b/mobile/plugins/with-share-intent-multifile.js new file mode 100644 index 0000000..da245c7 --- /dev/null +++ b/mobile/plugins/with-share-intent-multifile.js @@ -0,0 +1,98 @@ +const fs = require('node:fs'); +const path = require('node:path'); +const { withXcodeProject } = require('@expo/config-plugins'); + +const SHARE_EXTENSION_DIRECTORY = 'InFEDEOhochladen'; + +function replaceOnce(source, search, replacement, label) { + if (!source.includes(search)) { + throw new Error(`Multi-File-Patch konnte ${label} nicht finden.`); + } + return source.replace(search, replacement); +} + +module.exports = function withShareIntentMultifile(config) { + return withXcodeProject(config, async (modConfig) => { + const controllerPath = path.join( + modConfig.modRequest.platformProjectRoot, + SHARE_EXTENSION_DIRECTORY, + 'ShareViewController.swift' + ); + + let source = fs.readFileSync(controllerPath, 'utf8'); + + source = replaceOnce( + source, + ' var sharedText: [String] = []\n', + ' var sharedText: [String] = []\n var processedMediaAttachmentCount = 0\n', + 'den Attachment-Zähler' + ); + + const imageCompletion = ` // If this is the last item, save imagesData in userDefaults and redirect to host app + if index == (content.attachments?.count)! - 1 { + let userDefaults = UserDefaults(suiteName: self.hostAppGroupIdentifier) + userDefaults?.set(self.toData(data: self.sharedMedia), forKey: self.sharedKey) + userDefaults?.synchronize() + self.redirectToHostApp(type: .media) + }`; + + source = replaceOnce( + source, + imageCompletion, + ' self.finishMediaAttachment(content: content, type: .media)', + 'den Abschluss der Bildverarbeitung' + ); + + source = replaceOnce( + source, + imageCompletion, + ' self.finishMediaAttachment(content: content, type: .media)', + 'den Abschluss der Videoverarbeitung' + ); + + const fileCompletion = ` if index == (content.attachments?.count)! - 1 { + let userDefaults = UserDefaults(suiteName: self.hostAppGroupIdentifier) + userDefaults?.set(self.toData(data: self.sharedMedia), forKey: self.sharedKey) + userDefaults?.synchronize() + self.redirectToHostApp(type: .file) + }`; + + source = replaceOnce( + source, + fileCompletion, + ' self.finishMediaAttachment(content: content, type: .file)', + 'den Abschluss der Dateiverarbeitung' + ); + + const redirectMethod = ' private func redirectToHostApp(type: RedirectType) {'; + const completionMethod = ` private func finishMediaAttachment(content: NSExtensionItem, type: RedirectType) { + processedMediaAttachmentCount += 1 + let expectedMediaAttachmentCount = content.attachments?.filter { attachment in + attachment.hasItemConformingToTypeIdentifier(imageContentType) + || attachment.hasItemConformingToTypeIdentifier(videoContentType) + || attachment.hasItemConformingToTypeIdentifier(vcardContentType) + || attachment.hasItemConformingToTypeIdentifier(fileURLType) + || attachment.hasItemConformingToTypeIdentifier(pkpassContentType) + || attachment.hasItemConformingToTypeIdentifier(pdfContentType) + }.count ?? 0 + guard processedMediaAttachmentCount == expectedMediaAttachmentCount else { return } + + let userDefaults = UserDefaults(suiteName: hostAppGroupIdentifier) + userDefaults?.set(toData(data: sharedMedia), forKey: sharedKey) + userDefaults?.synchronize() + redirectToHostApp(type: type) + } + +`; + + source = replaceOnce( + source, + redirectMethod, + completionMethod + redirectMethod, + 'die Weiterleitungsmethode' + ); + + fs.writeFileSync(controllerPath, source); + return modConfig; + }); +};