summaryrefslogtreecommitdiff
path: root/src/ui/uploadwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/uploadwidget.c')
-rw-r--r--src/ui/uploadwidget.c388
1 files changed, 283 insertions, 105 deletions
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 5e1ee493..ba7545fd 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -29,12 +29,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29#include "command.h" 29#include "command.h"
30#include "gmrequest.h" 30#include "gmrequest.h"
31#include "sitespec.h" 31#include "sitespec.h"
32#include "window.h"
33#include "gmcerts.h"
32#include "app.h" 34#include "app.h"
33 35
36#if defined (iPlatformAppleMobile)
37# include "ios.h"
38#endif
39
34#include <the_Foundation/file.h> 40#include <the_Foundation/file.h>
35#include <the_Foundation/fileinfo.h> 41#include <the_Foundation/fileinfo.h>
42#include <the_Foundation/path.h>
36 43
37iDefineObjectConstruction(UploadWidget) 44iDefineObjectConstruction(UploadWidget)
45
46enum iUploadIdentity {
47 none_UploadIdentity,
48 defaultForUrl_UploadIdentity,
49 dropdown_UploadIdentity,
50};
38 51
39struct Impl_UploadWidget { 52struct Impl_UploadWidget {
40 iWidget widget; 53 iWidget widget;
@@ -51,9 +64,21 @@ struct Impl_UploadWidget {
51 iLabelWidget * counter; 64 iLabelWidget * counter;
52 iString filePath; 65 iString filePath;
53 size_t fileSize; 66 size_t fileSize;
67 enum iUploadIdentity idMode;
68 iBlock idFingerprint;
54 iAtomicInt isRequestUpdated; 69 iAtomicInt isRequestUpdated;
55}; 70};
56 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
57static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, size_t total) { 82static void updateProgress_UploadWidget_(iGmRequest *request, size_t current, size_t total) {
58 iUploadWidget *d = userData_Object(request); 83 iUploadWidget *d = userData_Object(request);
59 postCommand_Widget(d, 84 postCommand_Widget(d,
@@ -67,116 +92,202 @@ static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) {
67 iWidget *w = as_Widget(d); 92 iWidget *w = as_Widget(d);
68 /* Calculate how many lines fits vertically in the view. */ 93 /* Calculate how many lines fits vertically in the view. */
69 const iInt2 inputPos = topLeft_Rect(bounds_Widget(as_Widget(d->input))); 94 const iInt2 inputPos = topLeft_Rect(bounds_Widget(as_Widget(d->input)));
70 const int footerHeight = height_Widget(d->token) + 95 const int footerHeight = isUsingPanelLayout_Mobile() ? 0 :
71 height_Widget(findChild_Widget(w, "dialogbuttons")) + 96 (height_Widget(d->token) +
72 6 * gap_UI; 97 height_Widget(findChild_Widget(w, "dialogbuttons")) +
73 const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight; 98 12 * gap_UI);
99 const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight -
100 get_MainWindow()->keyboardHeight;
74 setLineLimits_InputWidget(d->input, 101 setLineLimits_InputWidget(d->input,
75 minLines_InputWidget(d->input), 102 minLines_InputWidget(d->input),
76 iMaxi(minLines_InputWidget(d->input), 103 iMaxi(minLines_InputWidget(d->input),
77 (avail - inputPos.y) / lineHeight_Text(monospace_FontId))); 104 (avail - inputPos.y) / lineHeight_Text(font_InputWidget(d->input))));
105}
106
107static const iArray *makeIdentityItems_UploadWidget_(const iUploadWidget *d) {
108 iArray *items = collectNew_Array(sizeof(iMenuItem));
109 const iGmIdentity *urlId = identityForUrl_GmCerts(certs_App(), &d->url);
110 pushBack_Array(items,
111 &(iMenuItem){ format_CStr("${dlg.upload.id.default} (%s)",
112 urlId ? cstr_String(name_GmIdentity(urlId))
113 : "${dlg.upload.id.none}"),
114 0, 0, "upload.setid arg:1" });
115 pushBack_Array(items, &(iMenuItem){ "${dlg.upload.id.none}", 0, 0, "upload.setid arg:0" });
116 pushBack_Array(items, &(iMenuItem){ "---" });
117 iConstForEach(PtrArray, i, listIdentities_GmCerts(certs_App(), NULL, NULL)) {
118 const iGmIdentity *id = i.ptr;
119 pushBack_Array(
120 items,
121 &(iMenuItem){ cstr_String(name_GmIdentity(id)), 0, 0,
122 format_CStr("upload.setid fp:%s",
123 cstrCollect_String(hexEncode_Block(&id->fingerprint))) });
124 }
125 pushBack_Array(items, &(iMenuItem){ NULL });
126 return items;
78} 127}
79 128
80void init_UploadWidget(iUploadWidget *d) { 129void init_UploadWidget(iUploadWidget *d) {
81 iWidget *w = as_Widget(d); 130 iWidget *w = as_Widget(d);
82 init_Widget(w); 131 init_Widget(w);
83 setId_Widget(w, "upload"); 132 setId_Widget(w, "upload");
84 useSheetStyle_Widget(w);
85 init_String(&d->originalUrl); 133 init_String(&d->originalUrl);
86 init_String(&d->url); 134 init_String(&d->url);
87 d->viewer = NULL; 135 d->viewer = NULL;
88 d->request = NULL; 136 d->request = NULL;
89 init_String(&d->filePath); 137 init_String(&d->filePath);
90 d->fileSize = 0; 138 d->fileSize = 0;
91 addChildFlags_Widget(w, 139 d->idMode = defaultForUrl_UploadIdentity;
92 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)), 140 init_Block(&d->idFingerprint, 0);
93 frameless_WidgetFlag); 141 const iMenuItem actions[] = {
94 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget("", NULL)), 142 { "${upload.port}", 0, 0, "upload.setport" },
95 frameless_WidgetFlag | resizeToParentWidth_WidgetFlag | 143 { "---" },
96 fixedHeight_WidgetFlag); 144 { "${close}", SDLK_ESCAPE, 0, "upload.cancel" },
97 setWrap_LabelWidget(d->info, iTrue); 145 { uiTextAction_ColorEscape "${dlg.upload.send}", SDLK_RETURN, KMOD_PRIMARY, "upload.accept" }
98 /* Tabs for input data. */ 146 };
99 iWidget *tabs = makeTabs_Widget(w); 147 if (isUsingPanelLayout_Mobile()) {
100 /* Make the tabs support vertical expansion based on content. */ { 148 const iMenuItem textItems[] = {
101 setFlags_Widget(tabs, resizeHeightOfChildren_WidgetFlag, iFalse); 149 { "title id:heading.upload.text" },
102 setFlags_Widget(tabs, arrangeHeight_WidgetFlag, iTrue); 150 { "input id:upload.text noheading:1" },
103 iWidget *tabPages = findChild_Widget(tabs, "tabs.pages"); 151 { NULL }
104 setFlags_Widget(tabPages, resizeHeightOfChildren_WidgetFlag, iFalse); 152 };
105 setFlags_Widget(tabPages, arrangeHeight_WidgetFlag, iTrue); 153 const iMenuItem fileItems[] = {
106 } 154 { "title id:heading.upload.file" },
107 iWidget *headings, *values; 155 { "button text:" uiTextAction_ColorEscape "${dlg.upload.pickfile}", 0, 0, "upload.pickfile" },
108 setBackgroundColor_Widget(findChild_Widget(tabs, "tabs.buttons"), uiBackgroundSidebar_ColorId); 156 { "heading id:upload.file.name" },
109 setId_Widget(tabs, "upload.tabs"); 157 { "label id:upload.filepathlabel text:\u2014" },
110// const int bigGap = lineHeight_Text(uiLabel_FontId) * 3 / 4; 158 { "heading id:upload.file.size" },
111 /* Text input. */ { 159 { "label id:upload.filesizelabel text:\u2014" },
112 //appendTwoColumnTabPage_Widget(tabs, "${heading.upload.text}", '1', &headings, &values); 160 { "padding" },
113 iWidget *page = new_Widget(); 161 { "input id:upload.mime" },
114 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue); 162 { "label id:upload.counter text:" },
115 d->input = new_InputWidget(0); 163 { NULL }
116 setId_Widget(as_Widget(d->input), "upload.text"); 164 };
117 setFont_InputWidget(d->input, monospace_FontId); 165 initPanels_Mobile(w, NULL, (iMenuItem[]){
118 setLineLimits_InputWidget(d->input, 7, 20); 166 { "title id:heading.upload" },
119 setUseReturnKeyBehavior_InputWidget(d->input, iFalse); /* traditional text editor */ 167 { "label id:upload.info" },
120 setHint_InputWidget(d->input, "${hint.upload.text}"); 168 { "panel id:dlg.upload.text icon:0x1f5b9", 0, 0, (const void *) textItems },
121 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1)); 169 { "panel id:dlg.upload.file icon:0x1f4c1", 0, 0, (const void *) fileItems },
122 addChild_Widget(page, iClob(d->input)); 170 { "padding" },
123 appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0); 171 { "dropdown id:upload.id icon:0x1f464", 0, 0, constData_Array(makeIdentityItems_UploadWidget_(d)) },
124 } 172 { "input id:upload.token hint:hint.upload.token icon:0x1f511" },
125 /* File content. */ { 173 { NULL }
126 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values); 174 }, actions, iElemCount(actions));
127// iWidget *pad = addChild_Widget(headings, iClob(makePadding_Widget(0))); 175 d->info = findChild_Widget(w, "upload.info");
128// iWidget *hint = addChild_Widget(values, iClob(new_LabelWidget("${upload.file.drophint}", NULL))); 176 d->input = findChild_Widget(w, "upload.text");
129// pad->sizeRef = hint; 177 d->filePathLabel = findChild_Widget(w, "upload.filepathlabel");
130 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL)), frameless_WidgetFlag); 178 d->fileSizeLabel = findChild_Widget(w, "upload.filesizelabel");
131 d->filePathLabel = addChildFlags_Widget(values, iClob(new_LabelWidget(uiTextAction_ColorEscape "${upload.file.drophere}", NULL)), frameless_WidgetFlag); 179 d->mime = findChild_Widget(w, "upload.mime");
132 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL)), frameless_WidgetFlag); 180 d->token = findChild_Widget(w, "upload.token");
133 d->fileSizeLabel = addChildFlags_Widget(values, iClob(new_LabelWidget("\u2014", NULL)), frameless_WidgetFlag); 181 d->counter = findChild_Widget(w, "upload.counter");
134 d->mime = new_InputWidget(0);
135 setFixedSize_Widget(as_Widget(d->mime), init_I2(70 * gap_UI, -1));
136 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime));
137 }
138 /* Token. */ {
139 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
140 iWidget *page = makeTwoColumns_Widget(&headings, &values);
141 d->token = addTwoColumnDialogInputField_Widget(
142 headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0)));
143 setHint_InputWidget(d->token, "${hint.upload.token}");
144 setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1));
145 addChild_Widget(w, iClob(page));
146 } 182 }
147 /* Buttons. */ { 183 else {
148 addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); 184 useSheetStyle_Widget(w);
149 iWidget *buttons = 185 setFlags_Widget(w, overflowScrollable_WidgetFlag, iFalse);
150 makeDialogButtons_Widget((iMenuItem[]){ { "${upload.port}", 0, 0, "upload.setport" }, 186 addChildFlags_Widget(w,
151 { "---", 0, 0, NULL }, 187 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)),
152 { "${close}", SDLK_ESCAPE, 0, "upload.cancel" }, 188 frameless_WidgetFlag);
153 { uiTextAction_ColorEscape "${dlg.upload.send}", 189 d->info = addChildFlags_Widget(w, iClob(new_LabelWidget("", NULL)),
154 SDLK_RETURN, 190 frameless_WidgetFlag | resizeToParentWidth_WidgetFlag |
155 KMOD_PRIMARY, 191 fixedHeight_WidgetFlag);
156 "upload.accept" } }, 192 setWrap_LabelWidget(d->info, iTrue);
157 4); 193 /* Tabs for input data. */
158 setId_Widget(insertChildAfterFlags_Widget(buttons, 194 iWidget *tabs = makeTabs_Widget(w);
159 iClob(d->counter = new_LabelWidget("", NULL)), 195 /* Make the tabs support vertical expansion based on content. */ {
160 0, frameless_WidgetFlag), 196 setFlags_Widget(tabs, resizeHeightOfChildren_WidgetFlag, iFalse);
161 "upload.counter"); 197 setFlags_Widget(tabs, arrangeHeight_WidgetFlag, iTrue);
162 addChild_Widget(w, iClob(buttons)); 198 iWidget *tabPages = findChild_Widget(tabs, "tabs.pages");
199 setFlags_Widget(tabPages, resizeHeightOfChildren_WidgetFlag, iFalse);
200 setFlags_Widget(tabPages, arrangeHeight_WidgetFlag, iTrue);
201 }
202 iWidget *headings, *values;
203 setBackgroundColor_Widget(findChild_Widget(tabs, "tabs.buttons"), uiBackgroundSidebar_ColorId);
204 setId_Widget(tabs, "upload.tabs");
205 /* Text input. */ {
206 iWidget *page = new_Widget();
207 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue);
208 d->input = new_InputWidget(0);
209 setId_Widget(as_Widget(d->input), "upload.text");
210 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1));
211 addChild_Widget(page, iClob(d->input));
212 appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0);
213 }
214 /* File content. */ {
215 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values);
216 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL)), frameless_WidgetFlag);
217 d->filePathLabel = addChildFlags_Widget(values, iClob(new_LabelWidget(uiTextAction_ColorEscape "${upload.file.drophere}", NULL)), frameless_WidgetFlag);
218 addChildFlags_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL)), frameless_WidgetFlag);
219 d->fileSizeLabel = addChildFlags_Widget(values, iClob(new_LabelWidget("\u2014", NULL)), frameless_WidgetFlag);
220 d->mime = new_InputWidget(0);
221 setFixedSize_Widget(as_Widget(d->mime), init_I2(70 * gap_UI, -1));
222 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime));
223 }
224 /* Identity and Token. */ {
225 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
226 iWidget *page = makeTwoColumns_Widget(&headings, &values);
227 /* Token. */
228 d->token = addTwoColumnDialogInputField_Widget(
229 headings, values, "${upload.token}", "upload.token", iClob(new_InputWidget(0)));
230 setHint_InputWidget(d->token, "${hint.upload.token}");
231 setFixedSize_Widget(as_Widget(d->token), init_I2(50 * gap_UI, -1));
232 /* Identity. */
233 const iArray * identItems = makeIdentityItems_UploadWidget_(d);
234 const iMenuItem *items = constData_Array(identItems);
235 const size_t numItems = size_Array(identItems);
236 iLabelWidget * ident = makeMenuButton_LabelWidget("${upload.id}", items, numItems);
237 setTextCStr_LabelWidget(ident, items[findWidestLabel_MenuItem(items, numItems)].label);
238 addChild_Widget(headings, iClob(makeHeading_Widget("${upload.id}")));
239 setId_Widget(addChildFlags_Widget(values, iClob(ident), alignLeft_WidgetFlag), "upload.id");
240 addChild_Widget(w, iClob(page));
241 }
242 /* Buttons. */ {
243 addChild_Widget(w, iClob(makePadding_Widget(gap_UI)));
244 iWidget *buttons = makeDialogButtons_Widget(actions, iElemCount(actions));
245 setId_Widget(insertChildAfterFlags_Widget(buttons,
246 iClob(d->counter = new_LabelWidget("", NULL)),
247 0,
248 frameless_WidgetFlag),
249 "upload.counter");
250 addChild_Widget(w, iClob(buttons));
251 }
252 resizeToLargestPage_Widget(tabs);
253 arrange_Widget(w);
254 setFixedSize_Widget(as_Widget(d->token), init_I2(width_Widget(tabs) - left_Rect(parent_Widget(d->token)->rect), -1));
255 setFlags_Widget(as_Widget(d->token), expand_WidgetFlag, iTrue);
256 setFocus_Widget(as_Widget(d->input));
163 } 257 }
164 resizeToLargestPage_Widget(tabs); 258 setFont_InputWidget(d->input, iosevka_FontId);
165 arrange_Widget(w); 259 setUseReturnKeyBehavior_InputWidget(d->input, iFalse); /* traditional text editor */
166 setFixedSize_Widget(as_Widget(d->token), init_I2(width_Widget(tabs) - left_Rect(parent_Widget(d->token)->rect), -1)); 260 setLineLimits_InputWidget(d->input, 7, 20);
167 setFlags_Widget(as_Widget(d->token), expand_WidgetFlag, iTrue); 261 setHint_InputWidget(d->input, "${hint.upload.text}");
168 setFocus_Widget(as_Widget(d->input));
169 setBackupFileName_InputWidget(d->input, "uploadbackup.txt"); 262 setBackupFileName_InputWidget(d->input, "uploadbackup.txt");
170 updateInputMaxHeight_UploadWidget_(d); 263 updateInputMaxHeight_UploadWidget_(d);
171} 264}
172 265
173void deinit_UploadWidget(iUploadWidget *d) { 266void deinit_UploadWidget(iUploadWidget *d) {
267 releaseFile_UploadWidget_(d);
268 deinit_Block(&d->idFingerprint);
174 deinit_String(&d->filePath); 269 deinit_String(&d->filePath);
175 deinit_String(&d->url); 270 deinit_String(&d->url);
176 deinit_String(&d->originalUrl); 271 deinit_String(&d->originalUrl);
177 iRelease(d->request); 272 iRelease(d->request);
178} 273}
179 274
275static void remakeIdentityItems_UploadWidget_(iUploadWidget *d) {
276 iWidget *dropMenu = findChild_Widget(findChild_Widget(as_Widget(d), "upload.id"), "menu");
277 releaseChildren_Widget(dropMenu);
278 const iArray *items = makeIdentityItems_UploadWidget_(d);
279 makeMenuItems_Widget(dropMenu, constData_Array(items), size_Array(items));
280}
281
282static void updateIdentityDropdown_UploadWidget_(iUploadWidget *d) {
283 updateDropdownSelection_LabelWidget(
284 findChild_Widget(as_Widget(d), "upload.id"),
285 d->idMode == none_UploadIdentity ? " arg:0"
286 : d->idMode == defaultForUrl_UploadIdentity
287 ? " arg:1"
288 : format_CStr(" fp:%s", cstrCollect_String(hexEncode_Block(&d->idFingerprint))));
289}
290
180static uint16_t titanPortForUrl_(const iString *url) { 291static uint16_t titanPortForUrl_(const iString *url) {
181 uint16_t port = 0; 292 uint16_t port = 0;
182 const iString *root = collectNewRange_String(urlRoot_String(url)); 293 const iString *root = collectNewRange_String(urlRoot_String(url));
@@ -201,10 +312,13 @@ static void setUrlPort_UploadWidget_(iUploadWidget *d, const iString *url, uint1
201 appendFormat_String(&d->url, ":%u", overridePort ? overridePort : titanPortForUrl_(url)); 312 appendFormat_String(&d->url, ":%u", overridePort ? overridePort : titanPortForUrl_(url));
202 appendRange_String(&d->url, (iRangecc){ parts.path.start, constEnd_String(url) }); 313 appendRange_String(&d->url, (iRangecc){ parts.path.start, constEnd_String(url) });
203 setText_LabelWidget(d->info, &d->url); 314 setText_LabelWidget(d->info, &d->url);
315 arrange_Widget(as_Widget(d));
204} 316}
205 317
206void setUrl_UploadWidget(iUploadWidget *d, const iString *url) { 318void setUrl_UploadWidget(iUploadWidget *d, const iString *url) {
207 setUrlPort_UploadWidget_(d, url, 0); 319 setUrlPort_UploadWidget_(d, url, 0);
320 remakeIdentityItems_UploadWidget_(d);
321 updateIdentityDropdown_UploadWidget_(d);
208} 322}
209 323
210void setResponseViewer_UploadWidget(iUploadWidget *d, iDocumentWidget *doc) { 324void setResponseViewer_UploadWidget(iUploadWidget *d, iDocumentWidget *doc) {
@@ -227,13 +341,33 @@ static void requestFinished_UploadWidget_(iUploadWidget *d, iGmRequest *req) {
227 postCommand_Widget(d, "upload.request.finished reqid:%u", id_GmRequest(req)); 341 postCommand_Widget(d, "upload.request.finished reqid:%u", id_GmRequest(req));
228} 342}
229 343
344static void updateFileInfo_UploadWidget_(iUploadWidget *d) {
345 iFileInfo *info = iClob(new_FileInfo(&d->filePath));
346 if (isDirectory_FileInfo(info)) {
347 makeMessage_Widget("${heading.upload.error.file}",
348 "${upload.error.directory}",
349 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
350 clear_String(&d->filePath);
351 d->fileSize = 0;
352 return;
353 }
354 d->fileSize = size_FileInfo(info);
355#if defined (iPlatformMobile)
356 setTextCStr_LabelWidget(d->filePathLabel, cstr_Rangecc(baseName_Path(&d->filePath)));
357#else
358 setText_LabelWidget(d->filePathLabel, &d->filePath);
359#endif
360 setTextCStr_LabelWidget(d->fileSizeLabel, formatCStrs_Lang("num.bytes.n", d->fileSize));
361 setTextCStr_InputWidget(d->mime, mediaType_Path(&d->filePath));
362}
363
230static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { 364static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
231 iWidget *w = as_Widget(d); 365 iWidget *w = as_Widget(d);
232 const char *cmd = command_UserEvent(ev); 366 const char *cmd = command_UserEvent(ev);
233 if (isResize_UserEvent(ev)) { 367 if (isResize_UserEvent(ev) || equal_Command(cmd, "keyboard.changed")) {
234 updateInputMaxHeight_UploadWidget_(d); 368 updateInputMaxHeight_UploadWidget_(d);
235 } 369 }
236 if (isCommand_Widget(w, ev, "upload.cancel")) { 370 if (equal_Command(cmd, "upload.cancel")) {
237 setupSheetTransition_Mobile(w, iFalse); 371 setupSheetTransition_Mobile(w, iFalse);
238 destroy_Widget(w); 372 destroy_Widget(w);
239 return iTrue; 373 return iTrue;
@@ -254,9 +388,36 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
254 } 388 }
255 return iTrue; 389 return iTrue;
256 } 390 }
391 if (isCommand_Widget(w, ev, "upload.setid")) {
392 if (hasLabel_Command(cmd, "fp")) {
393 set_Block(&d->idFingerprint, collect_Block(hexDecode_Rangecc(range_Command(cmd, "fp"))));
394 d->idMode = dropdown_UploadIdentity;
395 }
396 else if (arg_Command(cmd)) {
397 clear_Block(&d->idFingerprint);
398 d->idMode = defaultForUrl_UploadIdentity;
399 }
400 else {
401 clear_Block(&d->idFingerprint);
402 d->idMode = none_UploadIdentity;
403 }
404 updateIdentityDropdown_UploadWidget_(d);
405 return iTrue;
406 }
257 if (isCommand_Widget(w, ev, "upload.accept")) { 407 if (isCommand_Widget(w, ev, "upload.accept")) {
258 iWidget * tabs = findChild_Widget(w, "upload.tabs"); 408 iBool isText;
259 const int tabIndex = tabPageIndex_Widget(tabs, currentTabPage_Widget(tabs)); 409 iWidget *tabs = findChild_Widget(w, "upload.tabs");
410 if (tabs) {
411 const size_t tabIndex = tabPageIndex_Widget(tabs, currentTabPage_Widget(tabs));
412 isText = (tabIndex == 0);
413 }
414 else {
415 const size_t panelIndex = currentPanelIndex_Mobile(w);
416 if (panelIndex == iInvalidPos) {
417 return iTrue;
418 }
419 isText = (currentPanelIndex_Mobile(w) == 0);
420 }
260 /* Make a GmRequest and send the data. */ 421 /* Make a GmRequest and send the data. */
261 iAssert(d->request == NULL); 422 iAssert(d->request == NULL);
262 iAssert(!isEmpty_String(&d->url)); 423 iAssert(!isEmpty_String(&d->url));
@@ -264,7 +425,21 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
264 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_); 425 setSendProgressFunc_GmRequest(d->request, updateProgress_UploadWidget_);
265 setUserData_Object(d->request, d); 426 setUserData_Object(d->request, d);
266 setUrl_GmRequest(d->request, &d->url); 427 setUrl_GmRequest(d->request, &d->url);
267 if (tabIndex == 0) { 428 switch (d->idMode) {
429 case defaultForUrl_UploadIdentity:
430 break; /* GmRequest handles it */
431 case none_UploadIdentity:
432 setIdentity_GmRequest(d->request, NULL);
433 signOut_GmCerts(certs_App(), url_GmRequest(d->request));
434 break;
435 case dropdown_UploadIdentity: {
436 iGmIdentity *ident = findIdentity_GmCerts(certs_App(), &d->idFingerprint);
437 setIdentity_GmRequest(d->request, ident);
438 signIn_GmCerts(certs_App(), ident, url_GmRequest(d->request));
439 break;
440 }
441 }
442 if (isText) {
268 /* Uploading text. */ 443 /* Uploading text. */
269 setTitanData_GmRequest(d->request, 444 setTitanData_GmRequest(d->request,
270 collectNewCStr_String("text/plain"), 445 collectNewCStr_String("text/plain"),
@@ -312,6 +487,7 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
312 d->request = NULL; /* DocumentWidget has it now. */ 487 d->request = NULL; /* DocumentWidget has it now. */
313 } 488 }
314 setupSheetTransition_Mobile(w, iFalse); 489 setupSheetTransition_Mobile(w, iFalse);
490 releaseFile_UploadWidget_(d);
315 destroy_Widget(w); 491 destroy_Widget(w);
316 return iTrue; 492 return iTrue;
317 } 493 }
@@ -321,34 +497,36 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
321 refresh_Widget(w); 497 refresh_Widget(w);
322 return iTrue; 498 return iTrue;
323 } 499 }
500 else if (isCommand_Widget(w, ev, "upload.pickfile")) {
501#if defined (iPlatformAppleMobile)
502 if (hasLabel_Command(cmd, "path")) {
503 releaseFile_UploadWidget_(d);
504 set_String(&d->filePath, collect_String(suffix_Command(cmd, "path")));
505 updateFileInfo_UploadWidget_(d);
506 }
507 else {
508 pickFile_iOS(format_CStr("upload.pickfile ptr:%p", d));
509 }
510#endif
511 return iTrue;
512 }
324 if (ev->type == SDL_DROPFILE) { 513 if (ev->type == SDL_DROPFILE) {
325 /* Switch to File tab. */ 514 /* Switch to File tab. */
326 iWidget *tabs = findChild_Widget(w, "upload.tabs"); 515 iWidget *tabs = findChild_Widget(w, "upload.tabs");
327 showTabPage_Widget(tabs, tabPage_Widget(tabs, 1)); 516 showTabPage_Widget(tabs, tabPage_Widget(tabs, 1));
517 releaseFile_UploadWidget_(d);
328 setCStr_String(&d->filePath, ev->drop.file); 518 setCStr_String(&d->filePath, ev->drop.file);
329 iFileInfo *info = iClob(new_FileInfo(&d->filePath)); 519 updateFileInfo_UploadWidget_(d);
330 if (isDirectory_FileInfo(info)) {
331 makeMessage_Widget("${heading.upload.error.file}",
332 "${upload.error.directory}",
333 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
334 clear_String(&d->filePath);
335 d->fileSize = 0;
336 return iTrue;
337 }
338 d->fileSize = size_FileInfo(info);
339 setText_LabelWidget(d->filePathLabel, &d->filePath);
340 setTextCStr_LabelWidget(d->fileSizeLabel, formatCStrs_Lang("num.bytes.n", d->fileSize));
341 setTextCStr_InputWidget(d->mime, mediaType_Path(&d->filePath));
342 return iTrue; 520 return iTrue;
343 } 521 }
344 return processEvent_Widget(w, ev); 522 return processEvent_Widget(w, ev);
345} 523}
346 524
347static void draw_UploadWidget_(const iUploadWidget *d) { 525//static void draw_UploadWidget_(const iUploadWidget *d) {
348 draw_Widget(constAs_Widget(d)); 526// draw_Widget(constAs_Widget(d));
349} 527//}
350 528
351iBeginDefineSubclass(UploadWidget, Widget) 529iBeginDefineSubclass(UploadWidget, Widget)
352 .processEvent = (iAny *) processEvent_UploadWidget_, 530 .processEvent = (iAny *) processEvent_UploadWidget_,
353 .draw = (iAny *) draw_UploadWidget_, 531 .draw = draw_Widget,
354iEndDefineSubclass(UploadWidget) 532iEndDefineSubclass(UploadWidget)