diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-24 15:37:48 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-24 15:37:48 +0300 |
commit | 15a10da4e82c688b0cb1e266f4aebd477c979dce (patch) | |
tree | e6fef2fc87be5e03a26f554063b52695d4db2aba /src/ui | |
parent | 90717c77b29c4a8ca0c3f49e9b4670b6fcbbe9d9 (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.c | 68 |
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 | ||
1042 | static 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 | |||
1041 | static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse *response, | 1058 | static 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 | } |