diff options
-rw-r--r-- | src/ios.h | 1 | ||||
-rw-r--r-- | src/ios.m | 29 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 69 |
3 files changed, 79 insertions, 20 deletions
@@ -37,6 +37,7 @@ iBool processEvent_iOS (const SDL_Event *); | |||
37 | void playHapticEffect_iOS (enum iHapticEffect effect); | 37 | void playHapticEffect_iOS (enum iHapticEffect effect); |
38 | void exportDownloadedFile_iOS(const iString *path); | 38 | void exportDownloadedFile_iOS(const iString *path); |
39 | void pickFileForOpening_iOS (void); | 39 | void pickFileForOpening_iOS (void); |
40 | void pickFile_iOS (const char *command); /* ` path:%s` will be appended */ | ||
40 | 41 | ||
41 | iBool isPhone_iOS (void); | 42 | iBool isPhone_iOS (void); |
42 | void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); | 43 | void safeAreaInsets_iOS (float *left, float *top, float *right, float *bottom); |
@@ -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 | ||
456 | void pickFileForOpening_iOS(void) { | 473 | void pickFileForOpening_iOS(void) { |
474 | pickFile_iOS("file.open"); | ||
475 | } | ||
476 | |||
477 | void 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 | ||
39 | iDefineObjectConstruction(UploadWidget) | 44 | iDefineObjectConstruction(UploadWidget) |
40 | 45 | ||
@@ -64,6 +69,16 @@ struct Impl_UploadWidget { | |||
64 | iAtomicInt isRequestUpdated; | 69 | iAtomicInt isRequestUpdated; |
65 | }; | 70 | }; |
66 | 71 | ||
72 | static 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 | |||
67 | static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, size_t total) { | 82 | static 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 | ||
239 | void deinit_UploadWidget(iUploadWidget *d) { | 254 | void 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 | ||
323 | static 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 | |||
307 | static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { | 343 | static 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); |