const fs = require('node:fs'); const path = require('node:path'); const { withXcodeProject } = require('@expo/config-plugins'); const SHARE_EXTENSION_DIRECTORY = 'InFEDEOhochladen'; const SIRI_INTENTS_FILE = 'FEDEOSiriIntents.swift'; 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 siriTemplatePath = path.join(__dirname, 'ios', SIRI_INTENTS_FILE); const siriDestinationPath = path.join(modConfig.modRequest.platformProjectRoot, 'FEDEO', SIRI_INTENTS_FILE); fs.copyFileSync(siriTemplatePath, siriDestinationPath); const project = modConfig.modResults; const appTarget = project.pbxTargetByName('FEDEO'); const appGroup = project.pbxGroupByName('FEDEO'); const appTargetUUID = Object.entries(project.pbxNativeTargetSection()).find( ([key, entry]) => !key.endsWith('_comment') && entry === appTarget )?.[0]; const appGroupUUID = Object.entries(project.hash.project.objects.PBXGroup).find( ([key, entry]) => !key.endsWith('_comment') && entry === appGroup )?.[0]; const fileReferences = project.pbxFileReferenceSection(); const siriFileExists = Object.values(fileReferences).some( (entry) => entry && typeof entry === 'object' && String(entry.path || entry.name || '').includes(SIRI_INTENTS_FILE) ); if (!siriFileExists) { if (!appTargetUUID || !appGroupUUID) { throw new Error('FEDEO-App-Target für Siri App Intents wurde nicht gefunden.'); } project.addSourceFile( `FEDEO/${SIRI_INTENTS_FILE}`, { target: appTargetUUID }, appGroupUUID ); } 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; }); };