@@ -972,28 +972,29 @@ - (void)downloadBase64File:(NSString *)base64String {
972972
973973 NSData *fileData = [[NSData alloc ] initWithBase64EncodedString: base64ContentPart options: NSDataBase64DecodingIgnoreUnknownCharacters ];
974974 NSString *fileExtension = [self fileExtensionFromBase64String: base64String];
975+ [self showDownloadAlert: fileExtension invokeDownload: ^{
976+ NSString *tempFilePath = [NSTemporaryDirectory () stringByAppendingPathComponent: [NSString stringWithFormat: @" File.%@ " , fileExtension]];
977+ [fileData writeToFile: tempFilePath atomically: YES ];
978+
979+ NSURL *tempFileURL = [NSURL fileURLWithPath: tempFilePath];
980+
981+ UIDocumentPickerViewController *documentPicker = nil ;
982+ if (@available (iOS 14.0 , *)) {
983+ documentPicker = [[UIDocumentPickerViewController alloc ] initForExportingURLs: @[tempFileURL] asCopy: YES ];
984+ } else {
985+ // Usage of initWithURL:inMode: might lose file's extension and user has to type it manually
986+ // Problem was solved for iOS 14 and higher with initForExportingURLs
987+ documentPicker = [[UIDocumentPickerViewController alloc ] initWithURL: tempFileURL inMode: UIDocumentPickerModeExportToService];
988+ }
989+ documentPicker.delegate = self;
990+ documentPicker.modalPresentationStyle = UIModalPresentationFullScreen;
975991
976- NSString *tempFilePath = [NSTemporaryDirectory () stringByAppendingPathComponent: [NSString stringWithFormat: @" File.%@ " , fileExtension]];
977- [fileData writeToFile: tempFilePath atomically: YES ];
978-
979- NSURL *tempFileURL = [NSURL fileURLWithPath: tempFilePath];
980-
981- UIDocumentPickerViewController *documentPicker = nil ;
982- if (@available (iOS 14.0 , *)) {
983- documentPicker = [[UIDocumentPickerViewController alloc ] initForExportingURLs: @[tempFileURL] asCopy: YES ];
984- } else {
985- // Usage of initWithURL:inMode: might lose file's extension and user has to type it manually
986- // Problem was solved for iOS 14 and higher with initForExportingURLs
987- documentPicker = [[UIDocumentPickerViewController alloc ] initWithURL: tempFileURL inMode: UIDocumentPickerModeExportToService];
988- }
989- documentPicker.delegate = self;
990- documentPicker.modalPresentationStyle = UIModalPresentationFullScreen;
991-
992- UIViewController *rootViewController = [UIApplication sharedApplication ].keyWindow .rootViewController ;
993- while (rootViewController.presentedViewController ) {
994- rootViewController = rootViewController.presentedViewController ;
995- }
992+ UIViewController *rootViewController = [UIApplication sharedApplication ].keyWindow .rootViewController ;
993+ while (rootViewController.presentedViewController ) {
994+ rootViewController = rootViewController.presentedViewController ;
995+ }
996996 [rootViewController presentViewController: documentPicker animated: YES completion: nil ];
997+ }];
997998}
998999
9991000- (NSString *)fileExtensionFromBase64String : (NSString *)base64String {
@@ -2103,6 +2104,56 @@ - (void)handleRegularFileDownload:(NSString *)urlString {
21032104 }];
21042105}
21052106
2107+ - (void )showDownloadAlert: (NSString *)fileExtension
2108+ invokeDownload: (void (^)(void ))invokeDownload {
2109+ NSString *title =
2110+ [NSString stringWithFormat: @" Do you want to download File.%@ ?" ,
2111+ fileExtension ?: @" " ];
2112+
2113+ UIAlertController *alert = [UIAlertController
2114+ alertControllerWithTitle: title
2115+ message: nil
2116+ preferredStyle: UIAlertControllerStyleAlert];
2117+
2118+ UIAlertAction *cancelAction =
2119+ [UIAlertAction actionWithTitle: @" Cancel"
2120+ style: UIAlertActionStyleCancel
2121+ handler: nil ];
2122+
2123+ UIAlertAction *downloadAction =
2124+ [UIAlertAction actionWithTitle: @" Download"
2125+ style: UIAlertActionStyleDefault
2126+ handler: ^(UIAlertAction *_Nonnull action) {
2127+ if (invokeDownload) {
2128+ invokeDownload ();
2129+ }
2130+ }];
2131+
2132+ [alert addAction: cancelAction];
2133+ [alert addAction: downloadAction];
2134+
2135+ UIViewController *rootViewController =
2136+ [UIApplication sharedApplication ].keyWindow .rootViewController ;
2137+ if (rootViewController) {
2138+ [rootViewController presentViewController: alert
2139+ animated: YES
2140+ completion: nil ];
2141+ } else {
2142+ NSLog (@" Error: No root view controller to present alert" );
2143+ }
2144+
2145+ // Disable download button initially to prevent Tap jacking
2146+ downloadAction.enabled = NO ;
2147+
2148+ // Enable button after 500ms
2149+ dispatch_after (
2150+ dispatch_time (DISPATCH_TIME_NOW, (int64_t )(500 * NSEC_PER_MSEC)),
2151+ dispatch_get_main_queue (), ^{
2152+ downloadAction.enabled = YES ;
2153+ });
2154+ }
2155+
2156+
21062157@end
21072158
21082159@implementation RNCWeakScriptMessageDelegate
0 commit comments