diff options
-rw-r--r-- | src/ui/documentwidget.c | 78 | ||||
-rw-r--r-- | src/ui/documentwidget.h | 4 | ||||
-rw-r--r-- | src/ui/mediaui.c | 11 | ||||
-rw-r--r-- | src/ui/mediaui.h | 2 |
4 files changed, 63 insertions, 32 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_, |
diff --git a/src/ui/documentwidget.h b/src/ui/documentwidget.h index 9bfab57a..2df3392b 100644 --- a/src/ui/documentwidget.h +++ b/src/ui/documentwidget.h | |||
@@ -48,8 +48,8 @@ const iString * bookmarkTitle_DocumentWidget (const iDocumentWidget *); | |||
48 | const iString * feedTitle_DocumentWidget (const iDocumentWidget *); | 48 | const iString * feedTitle_DocumentWidget (const iDocumentWidget *); |
49 | int documentWidth_DocumentWidget (const iDocumentWidget *); | 49 | int documentWidth_DocumentWidget (const iDocumentWidget *); |
50 | 50 | ||
51 | iBool findCachedContent_DocumentWidget(const iDocumentWidget *, const iString *url, | 51 | //iBool findCachedContent_DocumentWidget(const iDocumentWidget *, const iString *url, |
52 | iString *mime_out, iBlock *data_out); | 52 | // iString *mime_out, iBlock *data_out); |
53 | 53 | ||
54 | enum iDocumentWidgetSetUrlFlags { | 54 | enum iDocumentWidgetSetUrlFlags { |
55 | useCachedContentIfAvailable_DocumentWidgetSetUrlFlag = iBit(1), | 55 | useCachedContentIfAvailable_DocumentWidgetSetUrlFlag = iBit(1), |
diff --git a/src/ui/mediaui.c b/src/ui/mediaui.c index d85d0df9..4f2499b0 100644 --- a/src/ui/mediaui.c +++ b/src/ui/mediaui.c | |||
@@ -198,7 +198,7 @@ void draw_PlayerUI(iPlayerUI *d, iPaint *p) { | |||
198 | 198 | ||
199 | /*----------------------------------------------------------------------------------------------*/ | 199 | /*----------------------------------------------------------------------------------------------*/ |
200 | 200 | ||
201 | static void drawSevenSegmentBytes_(iInt2 pos, int color, size_t numBytes) { | 201 | void drawSevenSegmentBytes_MediaUI(int font, iInt2 pos, int majorColor, int minorColor, size_t numBytes) { |
202 | iString digits; | 202 | iString digits; |
203 | init_String(&digits); | 203 | init_String(&digits); |
204 | if (numBytes == 0) { | 204 | if (numBytes == 0) { |
@@ -221,12 +221,11 @@ static void drawSevenSegmentBytes_(iInt2 pos, int color, size_t numBytes) { | |||
221 | magnitude++; | 221 | magnitude++; |
222 | } | 222 | } |
223 | if (magnitude > 6) { | 223 | if (magnitude > 6) { |
224 | prependCStr_String(&digits, uiTextStrong_ColorEscape); | 224 | prependCStr_String(&digits, escape_Color(majorColor)); |
225 | } | 225 | } |
226 | } | 226 | } |
227 | const int font = uiLabel_FontId; | ||
228 | const iInt2 dims = measureRange_Text(font, range_String(&digits)).bounds.size; | 227 | const iInt2 dims = measureRange_Text(font, range_String(&digits)).bounds.size; |
229 | drawRange_Text(font, addX_I2(pos, -dims.x), color, range_String(&digits)); | 228 | drawRange_Text(font, addX_I2(pos, -dims.x), minorColor, range_String(&digits)); |
230 | deinit_String(&digits); | 229 | deinit_String(&digits); |
231 | } | 230 | } |
232 | 231 | ||
@@ -267,7 +266,9 @@ void draw_DownloadUI(const iDownloadUI *d, iPaint *p) { | |||
267 | isFinished ? uiTextAction_ColorId : uiTextDim_ColorId, | 266 | isFinished ? uiTextAction_ColorId : uiTextDim_ColorId, |
268 | cstr_Lang(isFinished ? "media.download.complete" : "media.download.warnclose")); | 267 | cstr_Lang(isFinished ? "media.download.complete" : "media.download.warnclose")); |
269 | const int x2 = right_Rect(rect); | 268 | const int x2 = right_Rect(rect); |
270 | drawSevenSegmentBytes_(init_I2(x2, y1), uiTextDim_ColorId, info.numBytes); | 269 | drawSevenSegmentBytes_MediaUI(uiLabel_FontId, init_I2(x2, y1), |
270 | uiTextStrong_ColorId, uiTextDim_ColorId, | ||
271 | info.numBytes); | ||
271 | const iInt2 pos = init_I2(x2, y2); | 272 | const iInt2 pos = init_I2(x2, y2); |
272 | if (bytesPerSecond > 0) { | 273 | if (bytesPerSecond > 0) { |
273 | drawAlign_Text(uiLabel_FontId, pos, uiTextDim_ColorId, right_Alignment, | 274 | drawAlign_Text(uiLabel_FontId, pos, uiTextDim_ColorId, right_Alignment, |
diff --git a/src/ui/mediaui.h b/src/ui/mediaui.h index 3d51e4c9..15c6e2ce 100644 --- a/src/ui/mediaui.h +++ b/src/ui/mediaui.h | |||
@@ -31,6 +31,8 @@ iDeclareType(Paint) | |||
31 | iDeclareType(Player) | 31 | iDeclareType(Player) |
32 | iDeclareType(PlayerUI) | 32 | iDeclareType(PlayerUI) |
33 | 33 | ||
34 | void drawSevenSegmentBytes_MediaUI (int font, iInt2 pos, int majorColor, int minorColor, size_t numBytes); | ||
35 | |||
34 | struct Impl_PlayerUI { | 36 | struct Impl_PlayerUI { |
35 | const iPlayer *player; | 37 | const iPlayer *player; |
36 | iRect bounds; | 38 | iRect bounds; |