summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-09-15 14:05:42 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-09-15 14:05:42 +0300
commit6580b4e2c396f2fdfb0fb017ec4249baa2fba5ff (patch)
tree1a0db802aa76dbf9f8b5c595e8b1a687ecdf4667
parent5119a72481a2c752972470ea7b488a5c9e58b720 (diff)
iOS: Picking files for upload
-rw-r--r--src/ios.h1
-rw-r--r--src/ios.m29
-rw-r--r--src/ui/uploadwidget.c69
3 files changed, 79 insertions, 20 deletions
diff --git a/src/ios.h b/src/ios.h
index 70b889bf..85177409 100644
--- a/src/ios.h
+++ b/src/ios.h
@@ -37,6 +37,7 @@ iBool processEvent_iOS (const SDL_Event *);
37void playHapticEffect_iOS (enum iHapticEffect effect); 37void playHapticEffect_iOS (enum iHapticEffect effect);
38void exportDownloadedFile_iOS(const iString *path); 38void exportDownloadedFile_iOS(const iString *path);
39void pickFileForOpening_iOS (void); 39void pickFileForOpening_iOS (void);
40void pickFile_iOS (const char *command); /* ` path:%s` will be appended */
40 41
41iBool isPhone_iOS (void); 42iBool isPhone_iOS (void);
42void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); 43void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom);
diff --git a/src/ios.m b/src/ios.m
index c493e4f9..3fb0af48 100644
--- a/src/ios.m
+++ b/src/ios.m
@@ -161,6 +161,7 @@ API_AVAILABLE(ios(13.0))
161 161
162@interface AppState : NSObject<UIDocumentPickerDelegate> { 162@interface AppState : NSObject<UIDocumentPickerDelegate> {
163 iString *fileBeingSaved; 163 iString *fileBeingSaved;
164 iString *pickFileCommand;
164} 165}
165@property (nonatomic, assign) BOOL isHapticsAvailable; 166@property (nonatomic, assign) BOOL isHapticsAvailable;
166@property (nonatomic, strong) NSObject *haptic; 167@property (nonatomic, strong) NSObject *haptic;
@@ -173,9 +174,17 @@ static AppState *appState_;
173-(instancetype)init { 174-(instancetype)init {
174 self = [super init]; 175 self = [super init];
175 fileBeingSaved = NULL; 176 fileBeingSaved = NULL;
177 pickFileCommand = NULL;
176 return self; 178 return self;
177} 179}
178 180
181-(void)setPickFileCommand:(const char *)command {
182 if (!pickFileCommand) {
183 pickFileCommand = new_String();
184 }
185 setCStr_String(pickFileCommand, command);
186}
187
179-(void)setFileBeingSaved:(const iString *)path { 188-(void)setFileBeingSaved:(const iString *)path {
180 fileBeingSaved = copy_String(path); 189 fileBeingSaved = copy_String(path);
181} 190}
@@ -213,7 +222,11 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
213 NSURL *url = [urls firstObject]; 222 NSURL *url = [urls firstObject];
214 iString *path = localFilePathFromUrl_String(collectNewCStr_String([[url absoluteString] 223 iString *path = localFilePathFromUrl_String(collectNewCStr_String([[url absoluteString]
215 UTF8String])); 224 UTF8String]));
216 postCommandf_App("file.open temp:1 path:%s", cstrCollect_String(path)); 225 postCommandf_App("%s temp:1 path:%s",
226 cstr_String(pickFileCommand),
227 cstrCollect_String(path));
228 delete_String(pickFileCommand);
229 pickFileCommand = NULL;
217 } 230 }
218} 231}
219 232
@@ -221,6 +234,10 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
221 if (fileBeingSaved) { 234 if (fileBeingSaved) {
222 [self removeSavedFile]; 235 [self removeSavedFile];
223 } 236 }
237 if (pickFileCommand) {
238 delete_String(pickFileCommand);
239 pickFileCommand = NULL;
240 }
224} 241}
225 242
226-(void)keyboardOnScreen:(NSNotification *)notification { 243-(void)keyboardOnScreen:(NSNotification *)notification {
@@ -454,11 +471,13 @@ void exportDownloadedFile_iOS(const iString *path) {
454} 471}
455 472
456void pickFileForOpening_iOS(void) { 473void pickFileForOpening_iOS(void) {
474 pickFile_iOS("file.open");
475}
476
477void pickFile_iOS(const char *command) {
478 [appState_ setPickFileCommand:command];
457 UIDocumentPickerViewController *picker = [[UIDocumentPickerViewController alloc] 479 UIDocumentPickerViewController *picker = [[UIDocumentPickerViewController alloc]
458 initWithDocumentTypes:@[@"fi.skyjake.lagrange.gemini", 480 initWithDocumentTypes:@[@"public.data"]
459 @"public.text",
460 @"public.image",
461 @"public.audio"]
462 inMode:UIDocumentPickerModeImport]; 481 inMode:UIDocumentPickerModeImport];
463 picker.delegate = appState_; 482 picker.delegate = appState_;
464 [viewController_(get_Window()) presentViewController:picker animated:YES completion:nil]; 483 [viewController_(get_Window()) presentViewController:picker animated:YES completion:nil];
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 34cace08..3f8b78dc 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -33,8 +33,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
33#include "gmcerts.h" 33#include "gmcerts.h"
34#include "app.h" 34#include "app.h"
35 35
36#if defined (iPlatformAppleMobile)
37# include "ios.h"
38#endif
39
36#include <the_Foundation/file.h> 40#include <the_Foundation/file.h>
37#include <the_Foundation/fileinfo.h> 41#include <the_Foundation/fileinfo.h>
42#include <the_Foundation/path.h>
38 43
39iDefineObjectConstruction(UploadWidget) 44iDefineObjectConstruction(UploadWidget)
40 45
@@ -64,6 +69,16 @@ struct Impl_UploadWidget {
64 iAtomicInt isRequestUpdated; 69 iAtomicInt isRequestUpdated;
65}; 70};
66 71
72static void releaseFile_UploadWidget_(iUploadWidget *d) {
73#if defined (iPlatformAppleMobile)
74 if (!isEmpty_String(&d->filePath)) {
75 /* Delete the temporary file that was copied for uploading. */
76 remove(cstr_String(&d->filePath));
77 }
78#endif
79 clear_String(&d->filePath);
80}
81
67static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, size_t total) { 82static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, size_t total) {
68 iUploadWidget *d = userData_Object(request); 83 iUploadWidget *d = userData_Object(request);
69 postCommand_Widget(d, 84 postCommand_Widget(d,
@@ -157,8 +172,8 @@ void init_UploadWidget(iUploadWidget *d) {
157 }, actions, iElemCount(actions)); 172 }, actions, iElemCount(actions));
158 d->info = findChild_Widget(w, "upload.info"); 173 d->info = findChild_Widget(w, "upload.info");
159 d->input = findChild_Widget(w, "upload.text"); 174 d->input = findChild_Widget(w, "upload.text");
160 d->filePathLabel = findChild_Widget(w, "upload.file.name"); 175 d->filePathLabel = findChild_Widget(w, "upload.filepathlabel");
161 d->fileSizeLabel = findChild_Widget(w, "upload.file.size"); 176 d->fileSizeLabel = findChild_Widget(w, "upload.filesizelabel");
162 d->mime = findChild_Widget(w, "upload.mime"); 177 d->mime = findChild_Widget(w, "upload.mime");
163 d->token = findChild_Widget(w, "upload.token"); 178 d->token = findChild_Widget(w, "upload.token");
164 d->counter = findChild_Widget(w, "upload.counter"); 179 d->counter = findChild_Widget(w, "upload.counter");
@@ -237,6 +252,7 @@ void init_UploadWidget(iUploadWidget *d) {
237} 252}
238 253
239void deinit_UploadWidget(iUploadWidget *d) { 254void deinit_UploadWidget(iUploadWidget *d) {
255 releaseFile_UploadWidget_(d);
240 deinit_Block(&d->idFingerprint); 256 deinit_Block(&d->idFingerprint);
241 deinit_String(&d->filePath); 257 deinit_String(&d->filePath);
242 deinit_String(&d->url); 258 deinit_String(&d->url);
@@ -304,6 +320,26 @@ static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) {
304 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint)))); 320 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint))));
305} 321}
306 322
323static void updateFileInfo_UploadWidget_(iUploadWidget *d) {
324 iFileInfo *info = iClob(new_FileInfo(&d->filePath));
325 if (isDirectory_FileInfo(info)) {
326 makeMessage_Widget("${heading.upload.error.file}",
327 "${upload.error.directory}",
328 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
329 clear_String(&d->filePath);
330 d->fileSize = 0;
331 return iTrue;
332 }
333 d->fileSize = size_FileInfo(info);
334#if defined (iPlatformMobile)
335 setTextCStr_LabelWidget(d->filePathLabel, cstr_Rangecc(baseName_Path(&d->filePath)));
336#else
337 setText_LabelWidget(d->filePathLabel, &d->filePath);
338#endif
339 setTextCStr_LabelWidget(d->fileSizeLabel, formatCStrs_Lang("num.bytes.n", d->fileSize));
340 setTextCStr_InputWidget(d->mime, mediaType_Path(&d->filePath));
341}
342
307static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { 343static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
308 iWidget *w = as_Widget(d); 344 iWidget *w = as_Widget(d);
309 const char *cmd = command_UserEvent(ev); 345 const char *cmd = command_UserEvent(ev);
@@ -430,6 +466,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
430 d->request = NULL; /* DocumentWidget has it now. */ 466 d->request = NULL; /* DocumentWidget has it now. */
431 } 467 }
432 setupSheetTransition_Mobile(w, iFalse); 468 setupSheetTransition_Mobile(w, iFalse);
469 releaseFile_UploadWidget_(d);
433 destroy_Widget(w); 470 destroy_Widget(w);
434 return iTrue; 471 return iTrue;
435 } 472 }
@@ -439,24 +476,26 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
439 refresh_Widget(w); 476 refresh_Widget(w);
440 return iTrue; 477 return iTrue;
441 } 478 }
479 else if (isCommand_Widget(w, ev, "upload.pickfile")) {
480#if defined (iPlatformAppleMobile)
481 if (hasLabel_Command(cmd, "path")) {
482 releaseFile_UploadWidget_(d);
483 set_String(&d->filePath, collect_String(suffix_Command(cmd, "path")));
484 updateFileInfo_UploadWidget_(d);
485 }
486 else {
487 pickFile_iOS(format_CStr("upload.pickfile ptr:%p", d));
488 }
489#endif
490 return iTrue;
491 }
442 if (ev->type == SDL_DROPFILE) { 492 if (ev->type == SDL_DROPFILE) {
443 /* Switch to File tab. */ 493 /* Switch to File tab. */
444 iWidget *tabs = findChild_Widget(w, "upload.tabs"); 494 iWidget *tabs = findChild_Widget(w, "upload.tabs");
445 showTabPage_Widget(tabs, tabPage_Widget(tabs, 1)); 495 showTabPage_Widget(tabs, tabPage_Widget(tabs, 1));
496 releaseFile_UploadWidget_(d);
446 setCStr_String(&d->filePath, ev->drop.file); 497 setCStr_String(&d->filePath, ev->drop.file);
447 iFileInfo *info = iClob(new_FileInfo(&d->filePath)); 498 updateFileInfo_UploadWidget_(d);
448 if (isDirectory_FileInfo(info)) {
449 makeMessage_Widget("${heading.upload.error.file}",
450 "${upload.error.directory}",
451 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
452 clear_String(&d->filePath);
453 d->fileSize = 0;
454 return iTrue;
455 }
456 d->fileSize = size_FileInfo(info);
457 setText_LabelWidget(d->filePathLabel, &d->filePath);
458 setTextCStr_LabelWidget(d->fileSizeLabel, formatCStrs_Lang("num.bytes.n", d->fileSize));
459 setTextCStr_InputWidget(d->mime, mediaType_Path(&d->filePath));
460 return iTrue; 499 return iTrue;
461 } 500 }
462 return processEvent_Widget(w, ev); 501 return processEvent_Widget(w, ev);