diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-18 08:15:08 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-18 08:15:08 +0300 |
commit | 3fb04c28f22475814708f69022eae5220d542108 (patch) | |
tree | 92d8827f9666a38fcb0d90127a6d978512ec5b77 /src/ui/documentwidget.c | |
parent | 917b425c7ed9dbcc6a029260af0b820dd132e35c (diff) |
DocumentWidget: Unsupported content downloads
Don't try to show a document while a long download is progressing, especially if we don't have any way to present the document format.
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 78 |
1 files changed, 53 insertions, 25 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index a1992967..cf2dc5da 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -228,6 +228,7 @@ enum iDocumentWidgetFlag { | |||
228 | otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */ | 228 | otherRootByDefault_DocumentWidgetFlag = iBit(12), /* links open to other root by default */ |
229 | urlChanged_DocumentWidgetFlag = iBit(13), | 229 | urlChanged_DocumentWidgetFlag = iBit(13), |
230 | openedFromSidebar_DocumentWidgetFlag = iBit(14), | 230 | openedFromSidebar_DocumentWidgetFlag = iBit(14), |
231 | drawDownloadCounter_DocumentWidgetFlag = iBit(15), | ||
231 | }; | 232 | }; |
232 | 233 | ||
233 | enum iDocumentLinkOrdinalMode { | 234 | enum iDocumentLinkOrdinalMode { |
@@ -275,7 +276,7 @@ struct Impl_DocumentWidget { | |||
275 | enum iGmStatusCode sourceStatus; | 276 | enum iGmStatusCode sourceStatus; |
276 | iString sourceHeader; | 277 | iString sourceHeader; |
277 | iString sourceMime; | 278 | iString sourceMime; |
278 | iBlock sourceContent; /* original content as received, for saving */ | 279 | iBlock sourceContent; /* original content as received, for saving; set on request finish */ |
279 | iTime sourceTime; | 280 | iTime sourceTime; |
280 | iGempub * sourceGempub; /* NULL unless the page is Gempub content */ | 281 | iGempub * sourceGempub; /* NULL unless the page is Gempub content */ |
281 | iGmDocument * doc; | 282 | iGmDocument * doc; |
@@ -1458,7 +1459,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1458 | clear_String(&d->sourceMime); | 1459 | clear_String(&d->sourceMime); |
1459 | d->sourceTime = response->when; | 1460 | d->sourceTime = response->when; |
1460 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag; | 1461 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag; |
1461 | initBlock_String(&str, &response->body); | 1462 | initBlock_String(&str, &response->body); /* Note: Body may be megabytes in size. */ |
1462 | if (isSuccess_GmStatusCode(statusCode)) { | 1463 | if (isSuccess_GmStatusCode(statusCode)) { |
1463 | /* Check the MIME type. */ | 1464 | /* Check the MIME type. */ |
1464 | iRangecc charset = range_CStr("utf-8"); | 1465 | iRangecc charset = range_CStr("utf-8"); |
@@ -1470,6 +1471,12 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1470 | while (nextSplit_Rangecc(mime, ";", &seg)) { | 1471 | while (nextSplit_Rangecc(mime, ";", &seg)) { |
1471 | iRangecc param = seg; | 1472 | iRangecc param = seg; |
1472 | trim_Rangecc(¶m); | 1473 | trim_Rangecc(¶m); |
1474 | /* Detect fontpacks even if the server doesn't use the right media type. */ | ||
1475 | if (isRequestFinished && equal_Rangecc(param, "application/octet-stream")) { | ||
1476 | if (detect_FontPack(&d->sourceContent)) { | ||
1477 | param = range_CStr(mimeType_FontPack); | ||
1478 | } | ||
1479 | } | ||
1473 | if (equal_Rangecc(param, "text/gemini")) { | 1480 | if (equal_Rangecc(param, "text/gemini")) { |
1474 | docFormat = gemini_SourceFormat; | 1481 | docFormat = gemini_SourceFormat; |
1475 | setRange_String(&d->sourceMime, param); | 1482 | setRange_String(&d->sourceMime, param); |
@@ -1485,9 +1492,11 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1485 | docFormat = plainText_SourceFormat; | 1492 | docFormat = plainText_SourceFormat; |
1486 | setRange_String(&d->sourceMime, param); | 1493 | setRange_String(&d->sourceMime, param); |
1487 | } | 1494 | } |
1488 | else if (equal_Rangecc(param, "application/zip") || | 1495 | else if (isRequestFinished && |
1496 | (equal_Rangecc(param, "application/zip") || | ||
1489 | (startsWith_Rangecc(param, "application/") && | 1497 | (startsWith_Rangecc(param, "application/") && |
1490 | endsWithCase_Rangecc(param, "+zip"))) { | 1498 | endsWithCase_Rangecc(param, "+zip")))) { |
1499 | clear_String(&str); | ||
1491 | docFormat = gemini_SourceFormat; | 1500 | docFormat = gemini_SourceFormat; |
1492 | setRange_String(&d->sourceMime, param); | 1501 | setRange_String(&d->sourceMime, param); |
1493 | iString *key = collectNew_String(); | 1502 | iString *key = collectNew_String(); |
@@ -1496,23 +1505,21 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1496 | appendFormat_String(&str, | 1505 | appendFormat_String(&str, |
1497 | cstr_Lang("doc.archive"), | 1506 | cstr_Lang("doc.archive"), |
1498 | cstr_Rangecc(baseName_Path(d->mod.url))); | 1507 | cstr_Rangecc(baseName_Path(d->mod.url))); |
1499 | if (isRequestFinished) { | 1508 | if (equal_Rangecc(param, mimeType_FontPack)) { |
1500 | if (equal_Rangecc(param, mimeType_FontPack)) { | 1509 | /* Show some information about fontpacks, and set up footer actions. */ |
1501 | /* Show some information about fontpacks, and set up footer actions. */ | 1510 | iArchive *zip = iClob(new_Archive()); |
1502 | iArchive *zip = iClob(new_Archive()); | 1511 | if (openData_Archive(zip, &d->sourceContent)) { |
1503 | if (openData_Archive(zip, &d->sourceContent)) { | 1512 | iFontPack *fp = new_FontPack(); |
1504 | iFontPack *fp = new_FontPack(); | 1513 | setUrl_FontPack(fp, d->mod.url); |
1505 | setUrl_FontPack(fp, d->mod.url); | 1514 | setStandalone_FontPack(fp, iTrue); |
1506 | setStandalone_FontPack(fp, iTrue); | 1515 | if (loadArchive_FontPack(fp, zip)) { |
1507 | if (loadArchive_FontPack(fp, zip)) { | 1516 | appendFormat_String(&str, "\n\n%s", |
1508 | appendFormat_String(&str, "\n\n%s", | 1517 | cstrCollect_String(infoText_FontPack(fp))); |
1509 | cstrCollect_String(infoText_FontPack(fp))); | ||
1510 | } | ||
1511 | const iArray *actions = actions_FontPack(fp); | ||
1512 | makeFooterButtons_DocumentWidget_(d, constData_Array(actions), | ||
1513 | size_Array(actions)); | ||
1514 | delete_FontPack(fp); | ||
1515 | } | 1518 | } |
1519 | const iArray *actions = actions_FontPack(fp); | ||
1520 | makeFooterButtons_DocumentWidget_(d, constData_Array(actions), | ||
1521 | size_Array(actions)); | ||
1522 | delete_FontPack(fp); | ||
1516 | } | 1523 | } |
1517 | } | 1524 | } |
1518 | appendCStr_String(&str, "\n\n"); | 1525 | appendCStr_String(&str, "\n\n"); |
@@ -1534,6 +1541,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1534 | startsWith_Rangecc(param, "audio/")) { | 1541 | startsWith_Rangecc(param, "audio/")) { |
1535 | const iBool isAudio = startsWith_Rangecc(param, "audio/"); | 1542 | const iBool isAudio = startsWith_Rangecc(param, "audio/"); |
1536 | /* Make a simple document with an image or audio player. */ | 1543 | /* Make a simple document with an image or audio player. */ |
1544 | clear_String(&str); | ||
1537 | docFormat = gemini_SourceFormat; | 1545 | docFormat = gemini_SourceFormat; |
1538 | setRange_String(&d->sourceMime, param); | 1546 | setRange_String(&d->sourceMime, param); |
1539 | const iGmLinkId imgLinkId = 1; /* there's only the one link */ | 1547 | const iGmLinkId imgLinkId = 1; /* there's only the one link */ |
@@ -1583,7 +1591,13 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, | |||
1583 | } | 1591 | } |
1584 | } | 1592 | } |
1585 | if (docFormat == undefined_SourceFormat) { | 1593 | if (docFormat == undefined_SourceFormat) { |
1586 | showErrorPage_DocumentWidget_(d, unsupportedMimeType_GmStatusCode, &response->meta); | 1594 | if (isRequestFinished) { |
1595 | d->flags &= ~drawDownloadCounter_DocumentWidgetFlag; | ||
1596 | showErrorPage_DocumentWidget_(d, unsupportedMimeType_GmStatusCode, &response->meta); | ||
1597 | deinit_String(&str); | ||
1598 | return; | ||
1599 | } | ||
1600 | d->flags |= drawDownloadCounter_DocumentWidgetFlag; | ||
1587 | deinit_String(&str); | 1601 | deinit_String(&str); |
1588 | return; | 1602 | return; |
1589 | } | 1603 | } |
@@ -1617,6 +1631,7 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) { | |||
1617 | clear_ObjectList(d->media); | 1631 | clear_ObjectList(d->media); |
1618 | d->certFlags = 0; | 1632 | d->certFlags = 0; |
1619 | setLinkNumberMode_DocumentWidget_(d, iFalse); | 1633 | setLinkNumberMode_DocumentWidget_(d, iFalse); |
1634 | d->flags &= ~drawDownloadCounter_DocumentWidgetFlag; | ||
1620 | d->state = fetching_RequestState; | 1635 | d->state = fetching_RequestState; |
1621 | set_Atomic(&d->isRequestUpdated, iFalse); | 1636 | set_Atomic(&d->isRequestUpdated, iFalse); |
1622 | d->request = new_GmRequest(certs_App()); | 1637 | d->request = new_GmRequest(certs_App()); |
@@ -1712,7 +1727,7 @@ static void updateFromCachedResponse_DocumentWidget_(iDocumentWidget *d, float n | |||
1712 | moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */ | 1727 | moveSpan_SmoothScroll(&d->scrollY, 0, 0); /* clamp position to new max */ |
1713 | cacheDocumentGlyphs_DocumentWidget_(d); | 1728 | cacheDocumentGlyphs_DocumentWidget_(d); |
1714 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; | 1729 | d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag | updateSideBuf_DrawBufsFlag; |
1715 | d->flags &= ~urlChanged_DocumentWidgetFlag; | 1730 | d->flags &= ~(urlChanged_DocumentWidgetFlag | drawDownloadCounter_DocumentWidgetFlag); |
1716 | postCommandf_Root( | 1731 | postCommandf_Root( |
1717 | as_Widget(d)->root, "document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); | 1732 | as_Widget(d)->root, "document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); |
1718 | } | 1733 | } |
@@ -2831,8 +2846,8 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2831 | } | 2846 | } |
2832 | else if (equalWidget_Command(cmd, w, "document.request.updated") && | 2847 | else if (equalWidget_Command(cmd, w, "document.request.updated") && |
2833 | id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) { | 2848 | id_GmRequest(d->request) == argU32Label_Command(cmd, "reqid")) { |
2834 | set_Block(&d->sourceContent, &lockResponse_GmRequest(d->request)->body); | 2849 | // set_Block(&d->sourceContent, &lockResponse_GmRequest(d->request)->body); |
2835 | unlockResponse_GmRequest(d->request); | 2850 | // unlockResponse_GmRequest(d->request); |
2836 | if (document_App() == d) { | 2851 | if (document_App() == d) { |
2837 | updateFetchProgress_DocumentWidget_(d); | 2852 | updateFetchProgress_DocumentWidget_(d); |
2838 | } | 2853 | } |
@@ -2855,7 +2870,9 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2855 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { | 2870 | if (category_GmStatusCode(status_GmRequest(d->request)) == categorySuccess_GmStatusCode) { |
2856 | init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y); /* TODO: unless user already scrolled! */ | 2871 | init_Anim(&d->scrollY.pos, d->initNormScrollY * size_GmDocument(d->doc).y); /* TODO: unless user already scrolled! */ |
2857 | } | 2872 | } |
2858 | d->flags &= ~urlChanged_DocumentWidgetFlag; | 2873 | iChangeFlags(d->flags, |
2874 | urlChanged_DocumentWidgetFlag | drawDownloadCounter_DocumentWidgetFlag, | ||
2875 | iFalse); | ||
2859 | d->state = ready_RequestState; | 2876 | d->state = ready_RequestState; |
2860 | postProcessRequestContent_DocumentWidget_(d, iFalse); | 2877 | postProcessRequestContent_DocumentWidget_(d, iFalse); |
2861 | /* The response may be cached. */ | 2878 | /* The response may be cached. */ |
@@ -4959,6 +4976,15 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4959 | drawHLine_Paint(&ctx.paint, topLeft_Rect(bounds), width_Rect(bounds), uiSeparator_ColorId); | 4976 | drawHLine_Paint(&ctx.paint, topLeft_Rect(bounds), width_Rect(bounds), uiSeparator_ColorId); |
4960 | } | 4977 | } |
4961 | drawChildren_Widget(w); | 4978 | drawChildren_Widget(w); |
4979 | if (d->flags & drawDownloadCounter_DocumentWidgetFlag && isRequestOngoing_DocumentWidget(d)) { | ||
4980 | const int font = uiLabelLarge_FontId; | ||
4981 | const iInt2 sevenSegWidth = measureRange_Text(font, range_CStr("\U0001fbf0")).advance; | ||
4982 | drawSevenSegmentBytes_MediaUI(font, | ||
4983 | add_I2(mid_Rect(docBounds), | ||
4984 | init_I2(sevenSegWidth.x * 4.5f, -sevenSegWidth.y / 2)), | ||
4985 | uiTextStrong_ColorId, uiTextDim_ColorId, | ||
4986 | bodySize_GmRequest(d->request)); | ||
4987 | } | ||
4962 | /* Alt text. */ | 4988 | /* Alt text. */ |
4963 | const float altTextOpacity = value_Anim(&d->altTextOpacity) * 6 - 5; | 4989 | const float altTextOpacity = value_Anim(&d->altTextOpacity) * 6 - 5; |
4964 | if (d->hoverAltPre && altTextOpacity > 0) { | 4990 | if (d->hoverAltPre && altTextOpacity > 0) { |
@@ -5175,6 +5201,7 @@ void updateSize_DocumentWidget(iDocumentWidget *d) { | |||
5175 | invalidate_DocumentWidget_(d); | 5201 | invalidate_DocumentWidget_(d); |
5176 | } | 5202 | } |
5177 | 5203 | ||
5204 | #if 0 | ||
5178 | iBool findCachedContent_DocumentWidget(const iDocumentWidget *d, const iString *url, | 5205 | iBool findCachedContent_DocumentWidget(const iDocumentWidget *d, const iString *url, |
5179 | iString *mime_out, iBlock *data_out) { | 5206 | iString *mime_out, iBlock *data_out) { |
5180 | if (equal_String(d->mod.url, url) && !isRequestOngoing_DocumentWidget(d)) { | 5207 | if (equal_String(d->mod.url, url) && !isRequestOngoing_DocumentWidget(d)) { |
@@ -5196,6 +5223,7 @@ iBool findCachedContent_DocumentWidget(const iDocumentWidget *d, const iString * | |||
5196 | } | 5223 | } |
5197 | return iFalse; | 5224 | return iFalse; |
5198 | } | 5225 | } |
5226 | #endif | ||
5199 | 5227 | ||
5200 | iBeginDefineSubclass(DocumentWidget, Widget) | 5228 | iBeginDefineSubclass(DocumentWidget, Widget) |
5201 | .processEvent = (iAny *) processEvent_DocumentWidget_, | 5229 | .processEvent = (iAny *) processEvent_DocumentWidget_, |