summaryrefslogtreecommitdiff
path: root/src/ui/uploadwidget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-07-17 15:36:37 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-07-17 15:36:37 +0300
commitc5463b0aec571b8d9451ddadb656a061e22e7f2f (patch)
treefdc36a94f74e9933d8d2064ebc3070c6f12530a2 /src/ui/uploadwidget.c
parent635eabab8b932ca01fc5b391cda20e23e40a6532 (diff)
Working on Titan uploads
There may be a bug in `TlsRequest` when sending out large amounts of data.
Diffstat (limited to 'src/ui/uploadwidget.c')
-rw-r--r--src/ui/uploadwidget.c110
1 files changed, 106 insertions, 4 deletions
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c
index 036571a5..968b3775 100644
--- a/src/ui/uploadwidget.c
+++ b/src/ui/uploadwidget.c
@@ -25,9 +25,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25#include "inputwidget.h" 25#include "inputwidget.h"
26#include "documentwidget.h" 26#include "documentwidget.h"
27#include "color.h" 27#include "color.h"
28#include "command.h"
28#include "gmrequest.h" 29#include "gmrequest.h"
29#include "app.h" 30#include "app.h"
30 31
32#include <the_Foundation/file.h>
33#include <the_Foundation/fileinfo.h>
34
31iDefineObjectConstruction(UploadWidget) 35iDefineObjectConstruction(UploadWidget)
32 36
33struct Impl_UploadWidget { 37struct Impl_UploadWidget {
@@ -39,6 +43,11 @@ struct Impl_UploadWidget {
39 iInputWidget * mime; 43 iInputWidget * mime;
40 iInputWidget * token; 44 iInputWidget * token;
41 iInputWidget * input; 45 iInputWidget * input;
46 iLabelWidget * filePathLabel;
47 iLabelWidget * fileSizeLabel;
48 iString filePath;
49 size_t fileSize;
50 iAtomicInt isRequestUpdated;
42}; 51};
43 52
44void init_UploadWidget(iUploadWidget *d) { 53void init_UploadWidget(iUploadWidget *d) {
@@ -49,6 +58,8 @@ void init_UploadWidget(iUploadWidget *d) {
49 init_String(&d->url); 58 init_String(&d->url);
50 d->viewer = NULL; 59 d->viewer = NULL;
51 d->request = NULL; 60 d->request = NULL;
61 init_String(&d->filePath);
62 d->fileSize = 0;
52 addChildFlags_Widget(w, 63 addChildFlags_Widget(w,
53 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)), 64 iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.upload}", NULL)),
54 frameless_WidgetFlag); 65 frameless_WidgetFlag);
@@ -64,10 +75,11 @@ void init_UploadWidget(iUploadWidget *d) {
64 iWidget *page = new_Widget(); 75 iWidget *page = new_Widget();
65 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue); 76 setFlags_Widget(page, arrangeSize_WidgetFlag, iTrue);
66 d->input = new_InputWidget(0); 77 d->input = new_InputWidget(0);
78 setHint_InputWidget(d->input, "${hint.upload.text}");
67 setEnterInsertsLF_InputWidget(d->input, iTrue); 79 setEnterInsertsLF_InputWidget(d->input, iTrue);
68 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1)); 80 setFixedSize_Widget(as_Widget(d->input), init_I2(120 * gap_UI, -1));
69 addChild_Widget(page, iClob(d->input)); 81 addChild_Widget(page, iClob(d->input));
70 appendTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0); 82 appendFramelessTabPage_Widget(tabs, iClob(page), "${heading.upload.text}", '1', 0);
71 } 83 }
72 /* File content. */ { 84 /* File content. */ {
73 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values); 85 appendTwoColumnTabPage_Widget(tabs, "${heading.upload.file}", '2', &headings, &values);
@@ -75,9 +87,9 @@ void init_UploadWidget(iUploadWidget *d) {
75// iWidget *hint = addChild_Widget(values, iClob(new_LabelWidget("${upload.file.drophint}", NULL))); 87// iWidget *hint = addChild_Widget(values, iClob(new_LabelWidget("${upload.file.drophint}", NULL)));
76// pad->sizeRef = hint; 88// pad->sizeRef = hint;
77 addChild_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL))); 89 addChild_Widget(headings, iClob(new_LabelWidget("${upload.file.name}", NULL)));
78 addChild_Widget(values, iClob(new_LabelWidget("filename.ext", NULL))); 90 d->filePathLabel = addChild_Widget(values, iClob(new_LabelWidget("${upload.file.drophere}", NULL)));
79 addChild_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL))); 91 addChild_Widget(headings, iClob(new_LabelWidget("${upload.file.size}", NULL)));
80 addChild_Widget(values, iClob(new_LabelWidget("0 KB", NULL))); 92 d->fileSizeLabel = addChild_Widget(values, iClob(new_LabelWidget("\u2014", NULL)));
81 d->mime = new_InputWidget(0); 93 d->mime = new_InputWidget(0);
82 setFixedSize_Widget(as_Widget(d->mime), init_I2(50 * gap_UI, -1)); 94 setFixedSize_Widget(as_Widget(d->mime), init_I2(50 * gap_UI, -1));
83 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime)); 95 addTwoColumnDialogInputField_Widget(headings, values, "${upload.mime}", "upload.mime", iClob(d->mime));
@@ -100,6 +112,10 @@ void init_UploadWidget(iUploadWidget *d) {
100 KMOD_PRIMARY, 112 KMOD_PRIMARY,
101 "upload.accept" } }, 113 "upload.accept" } },
102 2); 114 2);
115 setId_Widget(addChildPosFlags_Widget(buttons,
116 iClob(new_LabelWidget("0", NULL)),
117 front_WidgetAddPos, frameless_WidgetFlag),
118 "upload.pending");
103 addChild_Widget(w, iClob(buttons)); 119 addChild_Widget(w, iClob(buttons));
104 } 120 }
105 resizeToLargestPage_Widget(tabs); 121 resizeToLargestPage_Widget(tabs);
@@ -107,12 +123,16 @@ void init_UploadWidget(iUploadWidget *d) {
107} 123}
108 124
109void deinit_UploadWidget(iUploadWidget *d) { 125void deinit_UploadWidget(iUploadWidget *d) {
126 deinit_String(&d->filePath);
110 deinit_String(&d->url); 127 deinit_String(&d->url);
111 iRelease(d->request); 128 iRelease(d->request);
112} 129}
113 130
114void setUrl_UploadWidget(iUploadWidget *d, const iString *url) { 131void setUrl_UploadWidget(iUploadWidget *d, const iString *url) {
115 set_String(&d->url, url); 132 iUrl parts;
133 init_Url(&parts, url);
134 setCStr_String(&d->url, "titan");
135 appendRange_String(&d->url, (iRangecc){ parts.scheme.end, constEnd_String(url) });
116 setText_LabelWidget(d->info, &d->url); 136 setText_LabelWidget(d->info, &d->url);
117} 137}
118 138
@@ -120,6 +140,20 @@ void setResponseViewer_UploadWidget(iUploadWidget *d, iDocumentWidget *doc) {
120 d->viewer = doc; 140 d->viewer = doc;
121} 141}
122 142
143static iWidget *acceptButton_UploadWidget_(iUploadWidget *d) {
144 return lastChild_Widget(findChild_Widget(as_Widget(d), "dialogbuttons"));
145}
146
147static void requestUpdated_UploadWidget_(iUploadWidget *d, iGmRequest *req) {
148 if (!exchange_Atomic(&d->isRequestUpdated, iTrue)) {
149 postCommand_Widget(d, "upload.request.updated reqid:%u", id_GmRequest(req));
150 }
151}
152
153static void requestFinished_UploadWidget_(iUploadWidget *d, iGmRequest *req) {
154 postCommand_Widget(d, "upload.request.finished reqid:%u", id_GmRequest(req));
155}
156
123static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { 157static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
124 iWidget *w = as_Widget(d); 158 iWidget *w = as_Widget(d);
125 if (isCommand_Widget(w, ev, "upload.cancel")) { 159 if (isCommand_Widget(w, ev, "upload.cancel")) {
@@ -128,12 +162,80 @@ static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) {
128 destroy_Widget(w); 162 destroy_Widget(w);
129 return iTrue; 163 return iTrue;
130 } 164 }
165 const char *cmd = command_UserEvent(ev);
131 if (isCommand_Widget(w, ev, "upload.accept")) { 166 if (isCommand_Widget(w, ev, "upload.accept")) {
167 iWidget * tabs = findChild_Widget(w, "upload.tabs");
168 const int tabIndex = tabPageIndex_Widget(tabs, currentTabPage_Widget(tabs));
132 /* Make a GmRequest and send the data. */ 169 /* Make a GmRequest and send the data. */
170 iAssert(d->request == NULL);
171 iAssert(!isEmpty_String(&d->url));
172 d->request = new_GmRequest(certs_App());
173 setUrl_GmRequest(d->request, &d->url);
174 if (tabIndex == 0) {
175 /* Uploading text. */
176 setTitanData_GmRequest(d->request,
177 collectNewCStr_String("text/plain"),
178 utf8_String(text_InputWidget(d->input)),
179 text_InputWidget(d->token));
180 }
181 else {
182 /* Uploading a file. */
183 iFile *f = iClob(new_File(&d->filePath));
184 if (!open_File(f, readOnly_FileMode)) {
185 makeMessage_Widget("${heading.upload.error.file}",
186 "${upload.error.msg}",
187 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
188 iReleasePtr(&d->request);
189 return iTrue;
190 }
191 setTitanData_GmRequest(d->request,
192 text_InputWidget(d->mime),
193 collect_Block(readAll_File(f)),
194 text_InputWidget(d->token));
195 close_File(f);
196 }
197 iConnect(GmRequest, d->request, updated, d, requestUpdated_UploadWidget_);
198 iConnect(GmRequest, d->request, finished, d, requestFinished_UploadWidget_);
199 submit_GmRequest(d->request);
133 /* The dialog will remain open until the request finishes, showing upload progress. */ 200 /* The dialog will remain open until the request finishes, showing upload progress. */
201 setFocus_Widget(NULL);
202 setFlags_Widget(tabs, disabled_WidgetFlag, iTrue);
203 setFlags_Widget(as_Widget(d->token), disabled_WidgetFlag, iTrue);
204 setFlags_Widget(acceptButton_UploadWidget_(d), disabled_WidgetFlag, iTrue);
205 return iTrue;
206 }
207 else if (isCommand_Widget(w, ev, "upload.request.updated")) {
208 /* TODO: Upload progress update? */
209 }
210 else if (isCommand_Widget(w, ev, "upload.request.finished") &&
211 id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) {
212 if (d->viewer) {
213 takeRequest_DocumentWidget(d->viewer, d->request);
214 d->request = NULL; /* DocumentWidget has it now. */
215 }
216 setupSheetTransition_Mobile(w, iFalse);
217 destroy_Widget(w);
218 return iTrue;
134 } 219 }
135 if (ev->type == SDL_DROPFILE) { 220 if (ev->type == SDL_DROPFILE) {
136 /* Switch to File tab. */ 221 /* Switch to File tab. */
222 iWidget *tabs = findChild_Widget(w, "upload.tabs");
223 showTabPage_Widget(tabs, tabPage_Widget(tabs, 1));
224 setCStr_String(&d->filePath, ev->drop.file);
225 iFileInfo *info = iClob(new_FileInfo(&d->filePath));
226 if (isDirectory_FileInfo(info)) {
227 makeMessage_Widget("${heading.upload.error.file}",
228 "${upload.error.directory}",
229 (iMenuItem[]){ "${dlg.message.ok}", 0, 0, "message.ok" }, 1);
230 clear_String(&d->filePath);
231 d->fileSize = 0;
232 return iTrue;
233 }
234 d->fileSize = size_FileInfo(info);
235 setText_LabelWidget(d->filePathLabel, &d->filePath);
236 setTextCStr_LabelWidget(d->fileSizeLabel, formatCStrs_Lang("num.bytes.n", d->fileSize));
237 setTextCStr_InputWidget(d->mime, mediaType_Path(&d->filePath));
238 return iTrue;
137 } 239 }
138 return processEvent_Widget(w, ev); 240 return processEvent_Widget(w, ev);
139} 241}