From 5dae5b6aa51f38ffb0161d2fc9a65ea819428b07 Mon Sep 17 00:00:00 2001 From: florianfederspiel Date: Sat, 8 Aug 2026 22:41:58 +0200 Subject: [PATCH] =?UTF-8?q?KI-AGENT:=20Multi-File-Upload=20f=C3=BCr=20iOS?= =?UTF-8?q?=20Share=20Target=20absichern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mobile/app.json | 1 + mobile/plugins/with-share-intent-multifile.js | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 mobile/plugins/with-share-intent-multifile.js 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; + }); +};