diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-17 15:36:37 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-07-17 15:36:37 +0300 |
commit | c5463b0aec571b8d9451ddadb656a061e22e7f2f (patch) | |
tree | fdc36a94f74e9933d8d2064ebc3070c6f12530a2 /src | |
parent | 635eabab8b932ca01fc5b391cda20e23e40a6532 (diff) |
Working on Titan uploads
There may be a bug in `TlsRequest` when sending out large amounts of data.
Diffstat (limited to 'src')
-rw-r--r-- | src/gmrequest.c | 10 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 63 | ||||
-rw-r--r-- | src/ui/documentwidget.h | 3 | ||||
-rw-r--r-- | src/ui/keys.c | 1 | ||||
-rw-r--r-- | src/ui/root.c | 1 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 110 | ||||
-rw-r--r-- | src/ui/util.c | 15 | ||||
-rw-r--r-- | src/ui/util.h | 4 |
8 files changed, 185 insertions, 22 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c index 2471f311..cd193627 100644 --- a/src/gmrequest.c +++ b/src/gmrequest.c | |||
@@ -629,7 +629,7 @@ void submit_GmRequest(iGmRequest *d) { | |||
629 | iGmResponse *resp = d->resp; | 629 | iGmResponse *resp = d->resp; |
630 | clear_GmResponse(resp); | 630 | clear_GmResponse(resp); |
631 | #if !defined (NDEBUG) | 631 | #if !defined (NDEBUG) |
632 | printf("[GmRequest] URL: %s\n", cstr_String(&d->url)); | 632 | printf("[GmRequest] URL: %s\n", cstr_String(&d->url)); fflush(stdout); |
633 | #endif | 633 | #endif |
634 | iUrl url; | 634 | iUrl url; |
635 | init_Url(&url, &d->url); | 635 | init_Url(&url, &d->url); |
@@ -901,10 +901,11 @@ void submit_GmRequest(iGmRequest *d) { | |||
901 | /* Titan requests can have an arbitrary payload. */ | 901 | /* Titan requests can have an arbitrary payload. */ |
902 | if (isTitan_GmRequest_(d)) { | 902 | if (isTitan_GmRequest_(d)) { |
903 | iBlock content; | 903 | iBlock content; |
904 | initCopy_Block(&content, utf8_String(&d->url)); | 904 | init_Block(&content, 0); |
905 | if (d->titan) { | 905 | if (d->titan) { |
906 | printf_Block(&content, | 906 | printf_Block(&content, |
907 | ";mime=%s;size=%zu", | 907 | "%s;mime=%s;size=%zu", |
908 | cstr_String(&d->url), | ||
908 | cstr_String(&d->titan->mime), | 909 | cstr_String(&d->titan->mime), |
909 | size_Block(&d->titan->data)); | 910 | size_Block(&d->titan->data)); |
910 | if (!isEmpty_String(&d->titan->token)) { | 911 | if (!isEmpty_String(&d->titan->token)) { |
@@ -917,7 +918,8 @@ void submit_GmRequest(iGmRequest *d) { | |||
917 | } | 918 | } |
918 | else { | 919 | else { |
919 | /* Empty data. */ | 920 | /* Empty data. */ |
920 | appendCStr_Block(&content, ";mime=application/octet-stream;size=0\r\n"); | 921 | printf_Block( |
922 | &content, "%s;mime=application/octet-stream;size=0\r\n", cstr_String(&d->url)); | ||
921 | } | 923 | } |
922 | setContent_TlsRequest(d->req, &content); | 924 | setContent_TlsRequest(d->req, &content); |
923 | deinit_Block(&content); | 925 | deinit_Block(&content); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 8072a025..0c4dee89 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -48,6 +48,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
48 | #include "scrollwidget.h" | 48 | #include "scrollwidget.h" |
49 | #include "touch.h" | 49 | #include "touch.h" |
50 | #include "translation.h" | 50 | #include "translation.h" |
51 | #include "uploadwidget.h" | ||
51 | #include "util.h" | 52 | #include "util.h" |
52 | #include "visbuf.h" | 53 | #include "visbuf.h" |
53 | #include "visited.h" | 54 | #include "visited.h" |
@@ -2426,6 +2427,24 @@ static iBool handleSwipe_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | |||
2426 | return iFalse; | 2427 | return iFalse; |
2427 | } | 2428 | } |
2428 | 2429 | ||
2430 | static iBool cancelRequest_DocumentWidget_(iDocumentWidget *d, iBool postBack) { | ||
2431 | if (d->request) { | ||
2432 | iWidget *w = as_Widget(d); | ||
2433 | postCommandf_Root(w->root, | ||
2434 | "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); | ||
2435 | iReleasePtr(&d->request); | ||
2436 | if (d->state != ready_RequestState) { | ||
2437 | d->state = ready_RequestState; | ||
2438 | if (postBack) { | ||
2439 | postCommand_Root(w->root, "navigate.back"); | ||
2440 | } | ||
2441 | } | ||
2442 | updateFetchProgress_DocumentWidget_(d); | ||
2443 | return iTrue; | ||
2444 | } | ||
2445 | return iFalse; | ||
2446 | } | ||
2447 | |||
2429 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { | 2448 | static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) { |
2430 | iWidget *w = as_Widget(d); | 2449 | iWidget *w = as_Widget(d); |
2431 | if (equal_Command(cmd, "document.openurls.changed")) { | 2450 | if (equal_Command(cmd, "document.openurls.changed")) { |
@@ -2792,6 +2811,18 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2792 | } | 2811 | } |
2793 | return wasHandled; | 2812 | return wasHandled; |
2794 | } | 2813 | } |
2814 | else if (equal_Command(cmd, "document.upload") && d == document_App()) { | ||
2815 | if (equalCase_Rangecc(urlScheme_String(d->mod.url), "gemini") || | ||
2816 | equalCase_Rangecc(urlScheme_String(d->mod.url), "titan")) { | ||
2817 | iUploadWidget *upload = new_UploadWidget(); | ||
2818 | setUrl_UploadWidget(upload, d->mod.url); | ||
2819 | setResponseViewer_UploadWidget(upload, d); | ||
2820 | addChild_Widget(get_Root()->widget, iClob(upload)); | ||
2821 | finalizeSheet_Mobile(as_Widget(upload)); | ||
2822 | postRefresh_App(); | ||
2823 | } | ||
2824 | return iTrue; | ||
2825 | } | ||
2795 | else if (equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.finished")) { | 2826 | else if (equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.finished")) { |
2796 | return handleMediaCommand_DocumentWidget_(d, cmd); | 2827 | return handleMediaCommand_DocumentWidget_(d, cmd); |
2797 | } | 2828 | } |
@@ -2812,15 +2843,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2812 | return iFalse; | 2843 | return iFalse; |
2813 | } | 2844 | } |
2814 | else if (equal_Command(cmd, "document.stop") && document_App() == d) { | 2845 | else if (equal_Command(cmd, "document.stop") && document_App() == d) { |
2815 | if (d->request) { | 2846 | if (cancelRequest_DocumentWidget_(d, iTrue /* navigate back */)) { |
2816 | postCommandf_Root(w->root, | ||
2817 | "document.request.cancelled doc:%p url:%s", d, cstr_String(d->mod.url)); | ||
2818 | iReleasePtr(&d->request); | ||
2819 | if (d->state != ready_RequestState) { | ||
2820 | d->state = ready_RequestState; | ||
2821 | postCommand_Root(w->root, "navigate.back"); | ||
2822 | } | ||
2823 | updateFetchProgress_DocumentWidget_(d); | ||
2824 | return iTrue; | 2847 | return iTrue; |
2825 | } | 2848 | } |
2826 | } | 2849 | } |
@@ -3613,6 +3636,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3613 | { "---", 0, 0, NULL }, | 3636 | { "---", 0, 0, NULL }, |
3614 | { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, | 3637 | { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, |
3615 | { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, | 3638 | { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, |
3639 | { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" }, | ||
3616 | { "---", 0, 0, NULL }, | 3640 | { "---", 0, 0, NULL }, |
3617 | { "${menu.page.copyurl}", 0, 0, "document.copylink" } }, | 3641 | { "${menu.page.copyurl}", 0, 0, "document.copylink" } }, |
3618 | 15); | 3642 | 15); |
@@ -3642,6 +3666,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
3642 | } | 3666 | } |
3643 | d->menu = makeMenu_Widget(w, data_Array(&items), size_Array(&items)); | 3667 | d->menu = makeMenu_Widget(w, data_Array(&items), size_Array(&items)); |
3644 | deinit_Array(&items); | 3668 | deinit_Array(&items); |
3669 | setMenuItemDisabled_Widget( | ||
3670 | d->menu, | ||
3671 | "document.upload", | ||
3672 | !equalCase_Rangecc(urlScheme_String(d->mod.url), "gemini") && | ||
3673 | !equalCase_Rangecc(urlScheme_String(d->mod.url), "titan")); | ||
3645 | } | 3674 | } |
3646 | processContextMenuEvent_Widget(d->menu, ev, {}); | 3675 | processContextMenuEvent_Widget(d->menu, ev, {}); |
3647 | } | 3676 | } |
@@ -5004,6 +5033,22 @@ iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) { | |||
5004 | return d->request != NULL; | 5033 | return d->request != NULL; |
5005 | } | 5034 | } |
5006 | 5035 | ||
5036 | void takeRequest_DocumentWidget(iDocumentWidget *d, iGmRequest *finishedRequest) { | ||
5037 | cancelRequest_DocumentWidget_(d, iFalse /* don't post anything */); | ||
5038 | const iString *url = url_GmRequest(finishedRequest); | ||
5039 | |||
5040 | add_History(d->mod.history, url); | ||
5041 | setUrl_DocumentWidget_(d, url); | ||
5042 | d->state = fetching_RequestState; | ||
5043 | iAssert(d->request == NULL); | ||
5044 | d->request = finishedRequest; | ||
5045 | postCommand_Widget(d, | ||
5046 | "document.request.finished doc:%p reqid:%u request:%p", | ||
5047 | d, | ||
5048 | id_GmRequest(d->request), | ||
5049 | d->request); | ||
5050 | } | ||
5051 | |||
5007 | void updateSize_DocumentWidget(iDocumentWidget *d) { | 5052 | void updateSize_DocumentWidget(iDocumentWidget *d) { |
5008 | updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, iFalse); | 5053 | updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, iFalse); |
5009 | resetWideRuns_DocumentWidget_(d); | 5054 | resetWideRuns_DocumentWidget_(d); |
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index 1921b25a..cc09c72d 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h | |||
@@ -26,6 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
26 | #include <the_Foundation/stream.h> | 26 | #include <the_Foundation/stream.h> |
27 | 27 | ||
28 | iDeclareType(GmDocument) | 28 | iDeclareType(GmDocument) |
29 | iDeclareType(GmRequest) | ||
29 | iDeclareType(History) | 30 | iDeclareType(History) |
30 | 31 | ||
31 | iDeclareWidgetClass(DocumentWidget) | 32 | iDeclareWidgetClass(DocumentWidget) |
@@ -58,4 +59,6 @@ void setRedirectCount_DocumentWidget (iDocumentWidget *, int count); | |||
58 | void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText); | 59 | void setSource_DocumentWidget (iDocumentWidget *, const iString *sourceText); |
59 | void setOpenedFromSidebar_DocumentWidget(iDocumentWidget *, iBool fromSidebar); | 60 | void setOpenedFromSidebar_DocumentWidget(iDocumentWidget *, iBool fromSidebar); |
60 | 61 | ||
62 | void takeRequest_DocumentWidget (iDocumentWidget *, iGmRequest *finishedRequest); /* ownership given */ | ||
63 | |||
61 | void updateSize_DocumentWidget (iDocumentWidget *); | 64 | void updateSize_DocumentWidget (iDocumentWidget *); |
diff --git a/src/ui/keys.c b/src/ui/keys.c index 5fcfbea2..6de30f57 100644 --- a/src/ui/keys.c +++ b/src/ui/keys.c | |||
@@ -238,6 +238,7 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] = | |||
238 | { 99, { "${keys.split.item} ${menu.split.vertical} 2:1", SDLK_r, 0, "ui.split arg:2 axis:1", }, noDirectTrigger_BindFlag }, | 238 | { 99, { "${keys.split.item} ${menu.split.vertical} 2:1", SDLK_r, 0, "ui.split arg:2 axis:1", }, noDirectTrigger_BindFlag }, |
239 | { 100,{ "${keys.hoverurl}", '/', KMOD_PRIMARY, "prefs.hoverlink.toggle" }, 0 }, | 239 | { 100,{ "${keys.hoverurl}", '/', KMOD_PRIMARY, "prefs.hoverlink.toggle" }, 0 }, |
240 | { 110,{ "${menu.save.downloads}", SDLK_s, KMOD_PRIMARY, "document.save" }, 0 }, | 240 | { 110,{ "${menu.save.downloads}", SDLK_s, KMOD_PRIMARY, "document.save" }, 0 }, |
241 | { 120,{ "${keys.upload}", SDLK_u, KMOD_PRIMARY, "document.upload" }, 0 }, | ||
241 | /* The following cannot currently be changed (built-in duplicates). */ | 242 | /* The following cannot currently be changed (built-in duplicates). */ |
242 | #if defined (iPlatformApple) | 243 | #if defined (iPlatformApple) |
243 | { 1002, { NULL, SDLK_LEFTBRACKET, KMOD_PRIMARY, "navigate.back" }, 0 }, | 244 | { 1002, { NULL, SDLK_LEFTBRACKET, KMOD_PRIMARY, "navigate.back" }, 0 }, |
diff --git a/src/ui/root.c b/src/ui/root.c index c78c9632..91077019 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -1161,6 +1161,7 @@ void createUserInterface_Root(iRoot *d) { | |||
1161 | { star_Icon " ${menu.page.subscribe}", subscribeToPage_KeyModifier, "feeds.subscribe" }, | 1161 | { star_Icon " ${menu.page.subscribe}", subscribeToPage_KeyModifier, "feeds.subscribe" }, |
1162 | { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, | 1162 | { book_Icon " ${menu.page.import}", 0, 0, "bookmark.links confirm:1" }, |
1163 | { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, | 1163 | { globe_Icon " ${menu.page.translate}", 0, 0, "document.translate" }, |
1164 | { upload_Icon " ${menu.page.upload}", 0, 0, "document.upload" }, | ||
1164 | { "---", 0, 0, NULL }, | 1165 | { "---", 0, 0, NULL }, |
1165 | { "${menu.page.copyurl}", 0, 0, "document.copylink" }, | 1166 | { "${menu.page.copyurl}", 0, 0, "document.copylink" }, |
1166 | { "${menu.page.copysource}", 'c', KMOD_PRIMARY, "copy" }, | 1167 | { "${menu.page.copysource}", 'c', KMOD_PRIMARY, "copy" }, |
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 | |||
31 | iDefineObjectConstruction(UploadWidget) | 35 | iDefineObjectConstruction(UploadWidget) |
32 | 36 | ||
33 | struct Impl_UploadWidget { | 37 | struct 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 | ||
44 | void init_UploadWidget(iUploadWidget *d) { | 53 | void 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 | ||
109 | void deinit_UploadWidget(iUploadWidget *d) { | 125 | void 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 | ||
114 | void setUrl_UploadWidget(iUploadWidget *d, const iString *url) { | 131 | void 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 | ||
143 | static iWidget *acceptButton_UploadWidget_(iUploadWidget *d) { | ||
144 | return lastChild_Widget(findChild_Widget(as_Widget(d), "dialogbuttons")); | ||
145 | } | ||
146 | |||
147 | static 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 | |||
153 | static void requestFinished_UploadWidget_(iUploadWidget *d, iGmRequest *req) { | ||
154 | postCommand_Widget(d, "upload.request.finished reqid:%u", id_GmRequest(req)); | ||
155 | } | ||
156 | |||
123 | static iBool processEvent_UploadWidget_(iUploadWidget *d, const SDL_Event *ev) { | 157 | static 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 | } |
diff --git a/src/ui/util.c b/src/ui/util.c index 6bc358de..da7a69b4 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -864,6 +864,13 @@ iLabelWidget *findMenuItem_Widget(iWidget *menu, const char *command) { | |||
864 | return NULL; | 864 | return NULL; |
865 | } | 865 | } |
866 | 866 | ||
867 | void setMenuItemDisabled_Widget(iWidget *menu, const char *command, iBool disable) { | ||
868 | iLabelWidget *item = findMenuItem_Widget(menu, command); | ||
869 | if (item) { | ||
870 | setFlags_Widget(as_Widget(item), disabled_WidgetFlag, disable); | ||
871 | } | ||
872 | } | ||
873 | |||
867 | int checkContextMenu_Widget(iWidget *menu, const SDL_Event *ev) { | 874 | int checkContextMenu_Widget(iWidget *menu, const SDL_Event *ev) { |
868 | if (menu && ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT) { | 875 | if (menu && ev->type == SDL_MOUSEBUTTONDOWN && ev->button.button == SDL_BUTTON_RIGHT) { |
869 | if (isVisible_Widget(menu)) { | 876 | if (isVisible_Widget(menu)) { |
@@ -1428,8 +1435,8 @@ iWidget *makeToggle_Widget(const char *id) { | |||
1428 | return toggle; | 1435 | return toggle; |
1429 | } | 1436 | } |
1430 | 1437 | ||
1431 | static void appendFramelessTabPage_(iWidget *tabs, iWidget *page, const char *title, int shortcut, | 1438 | void appendFramelessTabPage_Widget(iWidget *tabs, iWidget *page, const char *title, int shortcut, |
1432 | int kmods) { | 1439 | int kmods) { |
1433 | appendTabPage_Widget(tabs, page, title, shortcut, kmods); | 1440 | appendTabPage_Widget(tabs, page, title, shortcut, kmods); |
1434 | setFlags_Widget( | 1441 | setFlags_Widget( |
1435 | (iWidget *) back_ObjectList(children_Widget(findChild_Widget(tabs, "tabs.buttons"))), | 1442 | (iWidget *) back_ObjectList(children_Widget(findChild_Widget(tabs, "tabs.buttons"))), |
@@ -1461,7 +1468,7 @@ iWidget *appendTwoColumnTabPage_Widget(iWidget *tabs, const char *title, int sho | |||
1461 | *values = addChildFlags_Widget( | 1468 | *values = addChildFlags_Widget( |
1462 | columns, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); | 1469 | columns, iClob(new_Widget()), arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag); |
1463 | addChildFlags_Widget(page, iClob(new_Widget()), expand_WidgetFlag); | 1470 | addChildFlags_Widget(page, iClob(new_Widget()), expand_WidgetFlag); |
1464 | appendFramelessTabPage_(tabs, iClob(page), title, shortcut, shortcut ? KMOD_PRIMARY : 0); | 1471 | appendFramelessTabPage_Widget(tabs, iClob(page), title, shortcut, shortcut ? KMOD_PRIMARY : 0); |
1465 | return page; | 1472 | return page; |
1466 | } | 1473 | } |
1467 | 1474 | ||
@@ -1888,7 +1895,7 @@ iWidget *makePreferences_Widget(void) { | |||
1888 | /* Keybindings. */ | 1895 | /* Keybindings. */ |
1889 | if (deviceType_App() == desktop_AppDeviceType) { | 1896 | if (deviceType_App() == desktop_AppDeviceType) { |
1890 | iBindingsWidget *bind = new_BindingsWidget(); | 1897 | iBindingsWidget *bind = new_BindingsWidget(); |
1891 | appendFramelessTabPage_(tabs, iClob(bind), "${heading.prefs.keys}", '7', KMOD_PRIMARY); | 1898 | appendFramelessTabPage_Widget(tabs, iClob(bind), "${heading.prefs.keys}", '7', KMOD_PRIMARY); |
1892 | } | 1899 | } |
1893 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); | 1900 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); |
1894 | updatePreferencesLayout_Widget(dlg); | 1901 | updatePreferencesLayout_Widget(dlg); |
diff --git a/src/ui/util.h b/src/ui/util.h index 5b02a4b3..021f72d1 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -226,7 +226,8 @@ void openMenu_Widget (iWidget *, iInt2 windowCoord); | |||
226 | void openMenuFlags_Widget(iWidget *, iInt2 windowCoord, iBool postCommands); | 226 | void openMenuFlags_Widget(iWidget *, iInt2 windowCoord, iBool postCommands); |
227 | void closeMenu_Widget (iWidget *); | 227 | void closeMenu_Widget (iWidget *); |
228 | 228 | ||
229 | iLabelWidget * findMenuItem_Widget (iWidget *menu, const char *command); | 229 | iLabelWidget * findMenuItem_Widget (iWidget *menu, const char *command); |
230 | void setMenuItemDisabled_Widget (iWidget *menu, const char *command, iBool disable); | ||
230 | 231 | ||
231 | int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ | 232 | int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */ |
232 | 233 | ||
@@ -242,6 +243,7 @@ iLabelWidget * makeMenuButton_LabelWidget (const char *label, const iMenuItem | |||
242 | 243 | ||
243 | iWidget * makeTabs_Widget (iWidget *parent); | 244 | iWidget * makeTabs_Widget (iWidget *parent); |
244 | void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); | 245 | void appendTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); |
246 | void appendFramelessTabPage_Widget(iWidget *tabs, iWidget *page, const char *title, int shortcut, int kmods); | ||
245 | iWidget * appendTwoColumnTabPage_Widget(iWidget *tabs, const char *title, int shortcut, iWidget **headings, | 247 | iWidget * appendTwoColumnTabPage_Widget(iWidget *tabs, const char *title, int shortcut, iWidget **headings, |
246 | iWidget **values); | 248 | iWidget **values); |
247 | void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); | 249 | void prependTabPage_Widget (iWidget *tabs, iWidget *page, const char *label, int key, int kmods); |