diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-12-30 09:25:33 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-12-30 09:25:33 +0200 |
commit | 084da73bd33bea50a811f72b15117be967a5f674 (patch) | |
tree | 40e060232f9f14419035586a6379a34349375920 /src/ui/documentwidget.c | |
parent | 0e5047069b5782b39620af8a5fd31d57ba9809e5 (diff) |
DocumentWidget: Inlining "image/*" responses
Image responses get inlined on gemtext pages.
It would make sense to use this mechanism for all media since the MIME type is ultimately what matters in determining the appropriate presentation. The file extensions shouldn't matter.
IssueID #373
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index cbd32066..f9efdd28 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -20,8 +20,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | 21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ |
22 | 22 | ||
23 | /* TODO: This file is a little (!) too large. DocumentWidget could be split into | 23 | /* TODO: Move DocumentView into a source file of its own. Consider cleaning up the network |
24 | a couple of smaller objects. One for rendering the document, for instance. */ | 24 | request handling. */ |
25 | 25 | ||
26 | #include "documentwidget.h" | 26 | #include "documentwidget.h" |
27 | 27 | ||
@@ -297,6 +297,7 @@ struct Impl_DocumentWidget { | |||
297 | /* Network request: */ | 297 | /* Network request: */ |
298 | enum iRequestState state; | 298 | enum iRequestState state; |
299 | iGmRequest * request; | 299 | iGmRequest * request; |
300 | iGmLinkId requestLinkId; /* ID of the link that initiated the current request */ | ||
300 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ | 301 | iAtomicInt isRequestUpdated; /* request has new content, need to parse it */ |
301 | int certFlags; | 302 | int certFlags; |
302 | iBlock * certFingerprint; | 303 | iBlock * certFingerprint; |
@@ -1079,9 +1080,9 @@ static size_t visibleLinkOrdinal_DocumentView_(const iDocumentView *d, iGmLinkId | |||
1079 | } | 1080 | } |
1080 | 1081 | ||
1081 | static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) { | 1082 | static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) { |
1082 | d->foundMark = iNullRange; | 1083 | d->foundMark = iNullRange; |
1083 | d->selectMark = iNullRange; | 1084 | d->selectMark = iNullRange; |
1084 | d->contextLink = NULL; | 1085 | d->contextLink = NULL; |
1085 | documentRunsInvalidated_DocumentView_(&d->view); | 1086 | documentRunsInvalidated_DocumentView_(&d->view); |
1086 | } | 1087 | } |
1087 | 1088 | ||
@@ -2136,6 +2137,7 @@ static void updateBanner_DocumentWidget_(iDocumentWidget *d) { | |||
2136 | static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) { | 2137 | static void documentWasChanged_DocumentWidget_(iDocumentWidget *d) { |
2137 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); | 2138 | iChangeFlags(d->flags, selecting_DocumentWidgetFlag, iFalse); |
2138 | setFlags_Widget(as_Widget(d), touchDrag_WidgetFlag, iFalse); | 2139 | setFlags_Widget(as_Widget(d), touchDrag_WidgetFlag, iFalse); |
2140 | d->requestLinkId = 0; | ||
2139 | updateVisitedLinks_GmDocument(d->view.doc); | 2141 | updateVisitedLinks_GmDocument(d->view.doc); |
2140 | documentRunsInvalidated_DocumentWidget_(d); | 2142 | documentRunsInvalidated_DocumentWidget_(d); |
2141 | updateWindowTitle_DocumentWidget_(d); | 2143 | updateWindowTitle_DocumentWidget_(d); |
@@ -2746,11 +2748,8 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) { | |||
2746 | "document.request.started doc:%p url:%s", | 2748 | "document.request.started doc:%p url:%s", |
2747 | d, | 2749 | d, |
2748 | cstr_String(d->mod.url)); | 2750 | cstr_String(d->mod.url)); |
2749 | clear_ObjectList(d->media); | ||
2750 | d->certFlags = 0; | ||
2751 | setLinkNumberMode_DocumentWidget_(d, iFalse); | 2751 | setLinkNumberMode_DocumentWidget_(d, iFalse); |
2752 | d->flags &= ~drawDownloadCounter_DocumentWidgetFlag; | 2752 | d->flags &= ~drawDownloadCounter_DocumentWidgetFlag; |
2753 | d->flags &= ~fromCache_DocumentWidgetFlag; | ||
2754 | d->state = fetching_RequestState; | 2753 | d->state = fetching_RequestState; |
2755 | set_Atomic(&d->isRequestUpdated, iFalse); | 2754 | set_Atomic(&d->isRequestUpdated, iFalse); |
2756 | d->request = new_GmRequest(certs_App()); | 2755 | d->request = new_GmRequest(certs_App()); |
@@ -3043,6 +3042,14 @@ static const char *humanReadableStatusCode_(enum iGmStatusCode code) { | |||
3043 | return format_CStr("%d ", code); | 3042 | return format_CStr("%d ", code); |
3044 | } | 3043 | } |
3045 | 3044 | ||
3045 | static void setUrl_DocumentWidget_(iDocumentWidget *d, const iString *url) { | ||
3046 | url = canonicalUrl_String(url); | ||
3047 | if (!equal_String(d->mod.url, url)) { | ||
3048 | d->flags |= urlChanged_DocumentWidgetFlag; | ||
3049 | set_String(d->mod.url, url); | ||
3050 | } | ||
3051 | } | ||
3052 | |||
3046 | static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | 3053 | static void checkResponse_DocumentWidget_(iDocumentWidget *d) { |
3047 | if (!d->request) { | 3054 | if (!d->request) { |
3048 | return; | 3055 | return; |
@@ -3053,8 +3060,35 @@ static void checkResponse_DocumentWidget_(iDocumentWidget *d) { | |||
3053 | } | 3060 | } |
3054 | iGmResponse *resp = lockResponse_GmRequest(d->request); | 3061 | iGmResponse *resp = lockResponse_GmRequest(d->request); |
3055 | if (d->state == fetching_RequestState) { | 3062 | if (d->state == fetching_RequestState) { |
3063 | /* Under certain conditions, inline any image response into the current document. */ | ||
3064 | if (d->requestLinkId && | ||
3065 | isSuccess_GmStatusCode(d->sourceStatus) && | ||
3066 | startsWithCase_String(&d->sourceMime, "text/gemini") && | ||
3067 | isSuccess_GmStatusCode(statusCode) && | ||
3068 | startsWithCase_String(&resp->meta, "image/")) { | ||
3069 | /* This request is turned into a new media request in the current document. */ | ||
3070 | iDisconnect(GmRequest, d->request, updated, d, requestUpdated_DocumentWidget_); | ||
3071 | iDisconnect(GmRequest, d->request, finished, d, requestFinished_DocumentWidget_); | ||
3072 | iMediaRequest *mr = newReused_MediaRequest(d, d->requestLinkId, d->request); | ||
3073 | unlockResponse_GmRequest(d->request); | ||
3074 | d->request = NULL; /* ownership moved */ | ||
3075 | postCommand_Widget(d, "document.request.cancelled doc:%p", d); | ||
3076 | pushBack_ObjectList(d->media, mr); | ||
3077 | iRelease(mr); | ||
3078 | /* Reset the fetch state, returning to the originating page. */ | ||
3079 | d->state = ready_RequestState; | ||
3080 | if (equal_String(&mostRecentUrl_History(d->mod.history)->url, url_GmRequest(mr->req))) { | ||
3081 | undo_History(d->mod.history); | ||
3082 | } | ||
3083 | setUrl_DocumentWidget_(d, url_GmDocument(d->view.doc)); | ||
3084 | updateFetchProgress_DocumentWidget_(d); | ||
3085 | postCommand_Widget(d, "media.updated link:%u request:%p", d->requestLinkId, mr); | ||
3086 | return; | ||
3087 | } | ||
3088 | /* Get ready for the incoming new document. */ | ||
3056 | d->state = receivedPartialResponse_RequestState; | 3089 | d->state = receivedPartialResponse_RequestState; |
3057 | d->flags &= ~fromCache_DocumentWidgetFlag; | 3090 | d->flags &= ~fromCache_DocumentWidgetFlag; |
3091 | clear_ObjectList(d->media); | ||
3058 | updateTrust_DocumentWidget_(d, resp); | 3092 | updateTrust_DocumentWidget_(d, resp); |
3059 | if (isSuccess_GmStatusCode(statusCode)) { | 3093 | if (isSuccess_GmStatusCode(statusCode)) { |
3060 | clear_Banner(d->banner); | 3094 | clear_Banner(d->banner); |
@@ -3441,14 +3475,6 @@ static iWidget *swipeParent_DocumentWidget_(iDocumentWidget *d) { | |||
3441 | return findChild_Widget(as_Widget(d)->root->widget, "doctabs"); | 3475 | return findChild_Widget(as_Widget(d)->root->widget, "doctabs"); |
3442 | } | 3476 | } |
3443 | 3477 | ||
3444 | static void setUrl_DocumentWidget_(iDocumentWidget *d, const iString *url) { | ||
3445 | url = canonicalUrl_String(url); | ||
3446 | if (!equal_String(d->mod.url, url)) { | ||
3447 | d->flags |= urlChanged_DocumentWidgetFlag; | ||
3448 | set_String(d->mod.url, url); | ||
3449 | } | ||
3450 | } | ||
3451 | |||
3452 | static void setupSwipeOverlay_DocumentWidget_(iDocumentWidget *d, iWidget *overlay) { | 3478 | static void setupSwipeOverlay_DocumentWidget_(iDocumentWidget *d, iWidget *overlay) { |
3453 | iWidget *w = as_Widget(d); | 3479 | iWidget *w = as_Widget(d); |
3454 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); | 3480 | iWidget *swipeParent = swipeParent_DocumentWidget_(d); |
@@ -4598,6 +4624,7 @@ static void interactingWithLink_DocumentWidget_(iDocumentWidget *d, iGmLinkId id | |||
4598 | clear_String(&d->linePrecedingLink); | 4624 | clear_String(&d->linePrecedingLink); |
4599 | return; | 4625 | return; |
4600 | } | 4626 | } |
4627 | d->requestLinkId = id; | ||
4601 | const char *start = range_String(source_GmDocument(d->view.doc)).start; | 4628 | const char *start = range_String(source_GmDocument(d->view.doc)).start; |
4602 | /* Find the preceding line. This is offered as a prefill option for a possible input query. */ | 4629 | /* Find the preceding line. This is offered as a prefill option for a possible input query. */ |
4603 | while (loc.start > start && *loc.start != '\n') { | 4630 | while (loc.start > start && *loc.start != '\n') { |
@@ -5526,6 +5553,7 @@ void init_DocumentWidget(iDocumentWidget *d) { | |||
5526 | d->state = blank_RequestState; | 5553 | d->state = blank_RequestState; |
5527 | d->titleUser = new_String(); | 5554 | d->titleUser = new_String(); |
5528 | d->request = NULL; | 5555 | d->request = NULL; |
5556 | d->requestLinkId = 0; | ||
5529 | d->isRequestUpdated = iFalse; | 5557 | d->isRequestUpdated = iFalse; |
5530 | d->media = new_ObjectList(); | 5558 | d->media = new_ObjectList(); |
5531 | d->banner = new_Banner(); | 5559 | d->banner = new_Banner(); |