summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-24 15:37:48 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-24 15:37:48 +0300
commit15a10da4e82c688b0cb1e266f4aebd477c979dce (patch)
treee6fef2fc87be5e03a26f554063b52695d4db2aba /src/ui
parent90717c77b29c4a8ca0c3f49e9b4670b6fcbbe9d9 (diff)
Gempub cover page; cleanup
Use MIME hooks to generate a Gempub cover page with a preloaded cover image. This required applying MIME filtering to "file://" requests as well. Todo: More cleanup, add a gempub.c.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/documentwidget.c68
1 files changed, 63 insertions, 5 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 9b414b63..11baf9ee 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -54,6 +54,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
54# include "ios.h" 54# include "ios.h"
55#endif 55#endif
56 56
57#include <the_Foundation/archive.h>
57#include <the_Foundation/file.h> 58#include <the_Foundation/file.h>
58#include <the_Foundation/fileinfo.h> 59#include <the_Foundation/fileinfo.h>
59#include <the_Foundation/objectlist.h> 60#include <the_Foundation/objectlist.h>
@@ -1038,6 +1039,22 @@ static void updateFetchProgress_DocumentWidget_(iDocumentWidget *d) {
1038 } 1039 }
1039} 1040}
1040 1041
1042static const char *zipPageHeading_(const iRangecc mime) {
1043 if (equalCase_Rangecc(mime, "application/gpub+zip")) {
1044 return book_Icon " Gempub Book";
1045 }
1046 iRangecc type = iNullRange;
1047 nextSplit_Rangecc(mime, "/", &type); /* skip the part before the slash */
1048 nextSplit_Rangecc(mime, "/", &type);
1049 if (startsWithCase_Rangecc(type, "x-")) {
1050 type.start += 2;
1051 }
1052 iString *heading = upper_String(collectNewRange_String(type));
1053 appendCStr_String(heading, " Archive");
1054 prependCStr_String(heading, folder_Icon " ");
1055 return cstrCollect_String(heading);
1056}
1057
1041static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response, 1058static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response,
1042 const iBool isInitialUpdate) { 1059 const iBool isInitialUpdate) {
1043 if (d->state == ready_RequestState) { 1060 if (d->state == ready_RequestState) {
@@ -1078,13 +1095,16 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1078 docFormat = plainText_GmDocumentFormat; 1095 docFormat = plainText_GmDocumentFormat;
1079 setRange_String(&d->sourceMime, param); 1096 setRange_String(&d->sourceMime, param);
1080 } 1097 }
1081 else if (equal_Rangecc(param, "application/zip")) { 1098 else if (equal_Rangecc(param, "application/zip") ||
1099 (startsWith_Rangecc(param, "application/") &&
1100 endsWithCase_Rangecc(param, "+zip"))) {
1082 docFormat = gemini_GmDocumentFormat; 1101 docFormat = gemini_GmDocumentFormat;
1083 setRange_String(&d->sourceMime, param); 1102 setRange_String(&d->sourceMime, param);
1084 iString *key = collectNew_String(); 1103 iString *key = collectNew_String();
1085 toString_Sym(SDLK_s, KMOD_PRIMARY, key); 1104 toString_Sym(SDLK_s, KMOD_PRIMARY, key);
1086 format_String(&str, "# " folder_Icon " ZIP Archive\n" 1105 format_String(&str, "# %s\n"
1087 "%s is a ZIP archive.\n\n%s\n\n", 1106 "%s is a compressed archive.\n\n%s\n\n",
1107 zipPageHeading_(param),
1088 cstr_Rangecc(baseName_Path(d->mod.url)), 1108 cstr_Rangecc(baseName_Path(d->mod.url)),
1089 format_CStr(cstr_Lang("error.unsupported.suggestsave"), 1109 format_CStr(cstr_Lang("error.unsupported.suggestsave"),
1090 cstr_String(key), 1110 cstr_String(key),
@@ -1101,6 +1121,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1101 /* Make a simple document with an image or audio player. */ 1121 /* Make a simple document with an image or audio player. */
1102 docFormat = gemini_GmDocumentFormat; 1122 docFormat = gemini_GmDocumentFormat;
1103 setRange_String(&d->sourceMime, param); 1123 setRange_String(&d->sourceMime, param);
1124 const iGmLinkId imgLinkId = 1; /* there's only the one link */
1104 if ((isAudio && isInitialUpdate) || (!isAudio && isRequestFinished)) { 1125 if ((isAudio && isInitialUpdate) || (!isAudio && isRequestFinished)) {
1105 const char *linkTitle = 1126 const char *linkTitle =
1106 startsWith_String(mimeStr, "image/") ? "Image" : "Audio"; 1127 startsWith_String(mimeStr, "image/") ? "Image" : "Audio";
@@ -1112,7 +1133,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1112 } 1133 }
1113 format_String(&str, "=> %s %s\n", cstr_String(d->mod.url), linkTitle); 1134 format_String(&str, "=> %s %s\n", cstr_String(d->mod.url), linkTitle);
1114 setData_Media(media_GmDocument(d->doc), 1135 setData_Media(media_GmDocument(d->doc),
1115 1, 1136 imgLinkId,
1116 mimeStr, 1137 mimeStr,
1117 &response->body, 1138 &response->body,
1118 !isRequestFinished ? partialData_MediaFlag : 0); 1139 !isRequestFinished ? partialData_MediaFlag : 0);
@@ -1121,7 +1142,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1121 else if (isAudio && !isInitialUpdate) { 1142 else if (isAudio && !isInitialUpdate) {
1122 /* Update the audio content. */ 1143 /* Update the audio content. */
1123 setData_Media(media_GmDocument(d->doc), 1144 setData_Media(media_GmDocument(d->doc),
1124 1, 1145 imgLinkId,
1125 mimeStr, 1146 mimeStr,
1126 &response->body, 1147 &response->body,
1127 !isRequestFinished ? partialData_MediaFlag : 0); 1148 !isRequestFinished ? partialData_MediaFlag : 0);
@@ -1157,6 +1178,43 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
1157 if (setSource) { 1178 if (setSource) {
1158 setSource_DocumentWidget(d, &str); 1179 setSource_DocumentWidget(d, &str);
1159 } 1180 }
1181 if (isRequestFinished) {
1182 /* Gempub: Preload cover image. */ {
1183 /* TODO: move to a gempub.c along with other related code */
1184 iString *localPath = localFilePathFromUrl_String(d->mod.url);
1185 if (localPath) {
1186 if (!iCmpStr(mediaTypeFromPath_String(localPath), "application/gpub+zip")) {
1187 iArchive *arch = iClob(new_Archive());
1188 if (openFile_Archive(arch, localPath)) {
1189 iBool haveImage = iFalse;
1190 for (size_t linkId = 1; ; linkId++) {
1191 const iString *linkUrl = linkUrl_GmDocument(d->doc, linkId);
1192 if (!linkUrl) break;
1193 if (findLinkImage_Media(media_GmDocument(d->doc), linkId)) {
1194 continue; /* got this already */
1195 }
1196 if (linkFlags_GmDocument(d->doc, linkId) & imageFileExtension_GmLinkFlag) {
1197 iString *imgEntryPath = collect_String(localFilePathFromUrl_String(linkUrl));
1198 remove_Block(&imgEntryPath->chars, 0, size_String(localPath) + 1 /* slash, too */);
1199 setData_Media(media_GmDocument(d->doc),
1200 linkId,
1201 collectNewCStr_String(mediaTypeFromPath_String(linkUrl)),
1202 data_Archive(arch, imgEntryPath),
1203 0);
1204 haveImage = iTrue;
1205 }
1206 }
1207 if (haveImage) {
1208 redoLayout_GmDocument(d->doc);
1209 updateVisible_DocumentWidget_(d);
1210 invalidate_DocumentWidget_(d);
1211 }
1212 }
1213 }
1214 delete_String(localPath);
1215 }
1216 }
1217 }
1160 deinit_String(&str); 1218 deinit_String(&str);
1161 } 1219 }
1162} 1220}