ios/Mobile/DocumentViewController.mm | 51 +++++++++++++++++++++++++++++++++- kit/ChildSession.cpp | 52 +---------------------------------- 2 files changed, 52 insertions(+), 51 deletions(-)
New commits: commit 909734e2615cdf259f26ffde58696544859aca34 Author: Tor Lillqvist <t...@collabora.com> AuthorDate: Mon Apr 13 15:48:51 2020 +0300 Commit: Tor Lillqvist <t...@collabora.com> CommitDate: Mon Apr 13 15:35:13 2020 +0200 Implement the "download as" functionality properly in the iOS app We need to catch the downloadas message already in -[DocumentViewController userContentController:didReceiveScriptMessage:] and use an UIDocumentPickerViewController to let the user choose where to download (or export) the document. The iOS-specific code in ChildSession::downloadAs() can go away. Change-Id: I626b9986ec6156f7e83bda02b04e65f7819f8017 Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92112 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Tor Lillqvist <t...@collabora.com> diff --git a/ios/Mobile/DocumentViewController.mm b/ios/Mobile/DocumentViewController.mm index 97ac7ab96..54932be3f 100644 --- a/ios/Mobile/DocumentViewController.mm +++ b/ios/Mobile/DocumentViewController.mm @@ -28,8 +28,9 @@ static DocumentViewController* theSingleton = nil; -@interface DocumentViewController() <WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler, UIScrollViewDelegate> { +@interface DocumentViewController() <WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler, UIScrollViewDelegate, UIDocumentPickerDelegate> { int closeNotificationPipeForForwardingThread[2]; + NSURL *downloadAsTmpURL; } @end @@ -449,6 +450,46 @@ static IMP standardImpOfInputAccessoryView = nil; [application openURL:url options:@{} completionHandler:nil]; return; } + } else if ([message.body hasPrefix:@"downloadas "]) { + NSArray<NSString*> *messageBodyItems = [message.body componentsSeparatedByString:@" "]; + NSString *format = nil; + if ([messageBodyItems count] >= 2) { + for (int i = 1; i < [messageBodyItems count]; i++) { + if ([messageBodyItems[i] hasPrefix:@"format="]) + format = [messageBodyItems[i] substringFromIndex:[@"format=" length]]; + } + + if (format == nil) + return; // Warn? + + // First save it in the requested format to a temporary location. First remove any + // leftover identically named temporary file. + + NSString *tmpFileName = [[[self.document->copyFileURL lastPathComponent] stringByDeletingPathExtension] stringByAppendingString:[@"." stringByAppendingString:format]]; + downloadAsTmpURL = [[NSFileManager.defaultManager temporaryDirectory] URLByAppendingPathComponent:tmpFileName]; + + std::remove([[downloadAsTmpURL path] UTF8String]); + + lok_document->saveAs([[downloadAsTmpURL absoluteString] UTF8String], [format UTF8String], nullptr); + + // Then verify that it indeed was saved, and then use an + // UIDocumentPickerViewController to ask the user where to store the exported + // document. + + struct stat statBuf; + if (stat([[downloadAsTmpURL path] UTF8String], &statBuf) == -1) { + LOG_ERR("Could apparently not save to '" << [[downloadAsTmpURL path] UTF8String] << "'"); + } else { + UIDocumentPickerViewController *picker = + [[UIDocumentPickerViewController alloc] initWithURL:downloadAsTmpURL + inMode:UIDocumentPickerModeExportToService]; + picker.delegate = self; + [self presentViewController:picker + animated:YES + completion:nil]; + } + return; + } } const char *buf = [message.body UTF8String]; @@ -461,6 +502,14 @@ static IMP standardImpOfInputAccessoryView = nil; } } +- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls { + std::remove([[downloadAsTmpURL path] UTF8String]); +} + +- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller { + std::remove([[downloadAsTmpURL path] UTF8String]); +} + - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { scrollView.pinchGestureRecognizer.enabled = NO; } diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index 534d6c2fb..edbe7e8c0 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -921,56 +921,8 @@ bool ChildSession::downloadAs(const char* /*buffer*/, int /*length*/, const Stri } #ifdef IOS - NSURL *docURL = [NSURL URLWithString:[NSString stringWithUTF8String:getDocURL().c_str()]]; - -#if 0 - // Experimentation - - // Check if we can figure out the name of the file provider service the document is on. (No, the - // services dictionary passed to the completion handler is always empty, except for On My iPad - // and iCloud Drive.) - [NSFileManager.defaultManager - getFileProviderServicesForItemAtURL:docURL - completionHandler:^(NSDictionary<NSFileProviderServiceName,NSFileProviderService *> *services, - NSError *error) { - if (services == nil) { - std::cerr << "Could not get file provider services for " << [[docURL absoluteString] UTF8String] << "\n"; - } else if ([services count] == 0) { - std::cerr << "No file provider services returned for " << [[docURL absoluteString] UTF8String] << "\n"; - } else { - std::cerr << "File provider services for " << [[docURL absoluteString] UTF8String] << ":\n"; - for (auto key in [services allKeys]) { - std::cerr << " " << [(NSString*)key UTF8String] << "\n"; - } - } - }]; - - // Check if we can figure out the "ubiquitous item container" name, which apparently means the file provider extension name. - // Alas, this seems to work only for documents on iCloud Drive. - NSError *error; - auto resources = [docURL promisedItemResourceValuesForKeys:@[NSURLUbiquitousItemContainerDisplayNameKey] error:&error]; - if (resources == nil) { - std::cerr << "Could not get ubiquitous container names for " << [[docURL absoluteString] UTF8String] << "\n"; - } else if ([resources count] == 0) { - std::cerr << "No ubiquitous container names for " << [[docURL absoluteString] UTF8String] << "\n"; - } else { - std::cerr << "Ubiquitous container names for " << [[docURL absoluteString] UTF8String] << ":\n"; - for (auto name in [resources allValues]) { - std::cerr << " " << [(NSString*)name UTF8String] << "\n"; - } - } -#endif - - NSArray<NSString *> *pathComponents = [docURL pathComponents]; - NSString *baseName = [[pathComponents lastObject] stringByDeletingPathExtension]; - NSURL *documentDirectory = [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0]; - NSString *dotFormat = [@"." stringByAppendingString:[NSString stringWithUTF8String:format.c_str()]]; - NSURL *exportedURL = [documentDirectory URLByAppendingPathComponent:[baseName stringByAppendingString:dotFormat]]; - LOG_TRC("Exporting as " << [[exportedURL absoluteString] UTF8String]); - - getLOKitDocument()->saveAs([[exportedURL absoluteString] UTF8String], - format.empty() ? nullptr : format.c_str(), - filterOptions.empty() ? nullptr : filterOptions.c_str()); + NSLog(@"We should never come here, aborting"); + std::abort(); #else // Prevent user inputting anything funny here. // A "name" should always be a name, not a path _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits