ios/Mobile/DocumentViewController.mm |   51 +++++++++++++++++++++++++++++++++-
 kit/ChildSession.cpp                 |   52 +----------------------------------
 2 files changed, 52 insertions(+), 51 deletions(-)

New commits:
commit 3c3e38b4b1f42fa2059813e2ea84d38f523c50d6
Author:     Tor Lillqvist <t...@collabora.com>
AuthorDate: Mon Apr 13 15:48:51 2020 +0300
Commit:     Andras Timar <andras.ti...@collabora.com>
CommitDate: Mon Apr 13 17:28:06 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>
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92115
    Reviewed-by: Andras Timar <andras.ti...@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

Reply via email to