diff --git a/Telegram/Resources/export_html/css/style.css b/Telegram/Resources/export_html/css/style.css
index 05ae10c12..4fa6823d5 100644
--- a/Telegram/Resources/export_html/css/style.css
+++ b/Telegram/Resources/export_html/css/style.css
@@ -56,6 +56,7 @@ pre {
}
.page_header {
position: fixed;
+ z-index: 10;
background-color: #ffffff;
width: 100%;
border-bottom: 1px solid #e3e6e8;
@@ -126,7 +127,8 @@ pre {
}
.color_green,
.userpic2,
-.media_call.success .fill {
+.media_call.success .fill,
+.media_photo .fill {
background-color: #64bf47;
}
.color_yellow,
@@ -152,7 +154,8 @@ pre {
}
.color_sea,
.userpic7,
-.media_location .fill {
+.media_location .fill,
+.media_video .fill {
background-color: #47bcd1;
}
.color_orange,
@@ -313,6 +316,63 @@ a.block_link:hover {
padding-top: 4px;
font-size: 13px;
}
+.default .video_file_wrap,
+.default .animated_wrap {
+ position: relative;
+}
+.default .video_file,
+.default .animated,
+.default .photo,
+.default .sticker {
+ display: block;
+}
+.video_duration {
+ background: rgba(0, 0, 0, .4);
+ padding: 0px 5px;
+ position: absolute;
+ z-index: 2;
+ border-radius: 2px;
+ right: 3px;
+ bottom: 3px;
+ color: #ffffff;
+ font-size: 11px;
+}
+.video_play_bg {
+ background: rgba(0, 0, 0, .4);
+ width: 40px;
+ height: 40px;
+ line-height: 0;
+ position: absolute;
+ z-index: 2;
+ border-radius: 50%;
+ overflow: hidden;
+ margin: -20px auto 0 -20px;
+ top: 50%;
+ left: 50%;
+ pointer-events: none;
+}
+.video_play {
+ position: absolute;
+ display: inline-block;
+ top: 50%;
+ left: 50%;
+ margin-left: -5px;
+ margin-top: -9px;
+ z-index: 1;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-width: 9px 0 9px 14px;
+ border-color: transparent transparent transparent #fff;
+}
+.gif_play {
+ font-weight: 700;
+ color: #FFF;
+ display: block;
+ line-height: 40px;
+ font-size: 13px;
+ text-align: center;
+}
.pagination {
text-align: center;
padding: 20px;
@@ -349,32 +409,38 @@ a.block_link:hover {
.page_header a.content {
background-image: url(../images/back.png);
}
-.media_call .thumb {
+.media_call .fill {
background-image: url(../images/media_call.png)
}
-.media_contact .thumb {
+.media_contact .fill {
background-image: url(../images/media_contact.png)
}
-.media_file .thumb {
+.media_file .fill {
background-image: url(../images/media_file.png)
}
-.media_game .thumb {
+.media_game .fill {
background-image: url(../images/media_game.png)
}
-.media_live_location .thumb,
-.media_location .thumb,
-.media_venue .thumb {
+.media_live_location .fill,
+.media_location .fill,
+.media_venue .fill {
background-image: url(../images/media_location.png)
}
-.media_audio_file .thumb {
+.media_audio_file .fill {
background-image: url(../images/media_music.png)
}
-.media_invoice .thumb {
+.media_invoice .fill {
background-image: url(../images/media_shop.png)
}
-.media_voice_message .thumb {
+.media_voice_message .fill {
background-image: url(../images/media_voice.png)
}
+.media_photo .fill {
+ background-image: url(../images/media_photo.png)
+}
+.media_video .fill {
+ background-image: url(../images/media_video.png)
+}
@media only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) {
.section.calls {
@@ -433,4 +499,10 @@ a.block_link:hover {
.media_voice_message .fill {
background-image: url(../images/media_voice@2x.png)
}
+.media_photo .fill {
+ background-image: url(../images/media_photo@2x.png)
+}
+.media_video .fill {
+ background-image: url(../images/media_video@2x.png)
+}
}
diff --git a/Telegram/Resources/export_html/images/media_photo.png b/Telegram/Resources/export_html/images/media_photo.png
new file mode 100644
index 000000000..d22938767
Binary files /dev/null and b/Telegram/Resources/export_html/images/media_photo.png differ
diff --git a/Telegram/Resources/export_html/images/media_photo@2x.png b/Telegram/Resources/export_html/images/media_photo@2x.png
new file mode 100644
index 000000000..e46794fe2
Binary files /dev/null and b/Telegram/Resources/export_html/images/media_photo@2x.png differ
diff --git a/Telegram/Resources/export_html/images/media_video.png b/Telegram/Resources/export_html/images/media_video.png
new file mode 100644
index 000000000..b0a132a15
Binary files /dev/null and b/Telegram/Resources/export_html/images/media_video.png differ
diff --git a/Telegram/Resources/export_html/images/media_video@2x.png b/Telegram/Resources/export_html/images/media_video@2x.png
new file mode 100644
index 000000000..2b554b028
Binary files /dev/null and b/Telegram/Resources/export_html/images/media_video@2x.png differ
diff --git a/Telegram/Resources/qrc/telegram.qrc b/Telegram/Resources/qrc/telegram.qrc
index 00763851f..15fcbb130 100644
--- a/Telegram/Resources/qrc/telegram.qrc
+++ b/Telegram/Resources/qrc/telegram.qrc
@@ -15,8 +15,12 @@
../export_html/images/media_location@2x.png
../export_html/images/media_music.png
../export_html/images/media_music@2x.png
+ ../export_html/images/media_photo.png
+ ../export_html/images/media_photo@2x.png
../export_html/images/media_shop.png
../export_html/images/media_shop@2x.png
+ ../export_html/images/media_video.png
+ ../export_html/images/media_video@2x.png
../export_html/images/media_voice.png
../export_html/images/media_voice@2x.png
../export_html/images/section_calls.png
diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp
index 949530e5d..539adfb51 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.cpp
+++ b/Telegram/SourceFiles/export/data/export_data_types.cpp
@@ -501,41 +501,66 @@ UserpicsSlice ParseUserpicsSlice(
return result;
}
-QString WriteImageThumb(
+std::pair WriteImageThumb(
const QString &basePath,
const QString &largePath,
- int width,
- int height,
+ Fn convertSize,
+ base::optional format,
+ base::optional quality,
const QString &postfix) {
if (largePath.isEmpty()) {
- return QString();
+ return {};
}
const auto path = basePath + largePath;
QImageReader reader(path);
if (!reader.canRead()) {
- return QString();
+ return {};
}
const auto size = reader.size();
if (size.isEmpty()
|| size.width() >= kMaxImageSize
|| size.height() >= kMaxImageSize) {
- return QString();
+ return {};
}
auto image = reader.read();
if (image.isNull()) {
- return QString();
+ return {};
}
- const auto format = reader.format();
+ const auto finalSize = convertSize(image.size());
+ if (finalSize.isEmpty()) {
+ return {};
+ }
+ image = std::move(image).scaled(
+ finalSize,
+ Qt::IgnoreAspectRatio,
+ Qt::SmoothTransformation);
+ const auto finalFormat = format ? *format : reader.format();
+ const auto finalQuality = quality ? *quality : reader.quality();
const auto lastSlash = largePath.lastIndexOf('/');
const auto firstDot = largePath.indexOf('.', lastSlash + 1);
const auto thumb = (firstDot >= 0)
? largePath.mid(0, firstDot) + postfix + largePath.mid(firstDot)
: largePath + postfix;
const auto result = Output::File::PrepareRelativePath(basePath, thumb);
- if (!image.save(basePath + result, reader.format(), reader.quality())) {
- return QString();
+ if (!image.save(basePath + result, finalFormat, finalQuality)) {
+ return {};
}
- return result;
+ return { result, finalSize };
+}
+
+QString WriteImageThumb(
+ const QString &basePath,
+ const QString &largePath,
+ int width,
+ int height,
+ const QString &postfix) {
+ return WriteImageThumb(
+ basePath,
+ largePath,
+ [=](QSize size) { return QSize(width, height); },
+ base::none,
+ base::none,
+ postfix).first;
}
ContactInfo ParseContactInfo(const MTPUser &data) {
@@ -780,7 +805,7 @@ Media ParseMedia(
auto result = Media();
data.match([&](const MTPDmessageMediaPhoto &data) {
- result.content = data.has_photo()
+ auto photo = data.has_photo()
? ParsePhoto(
data.vphoto,
folder + "photos/"
@@ -788,7 +813,9 @@ Media ParseMedia(
: Photo();
if (data.has_ttl_seconds()) {
result.ttl = data.vttl_seconds.v;
+ photo.image.file = File();
}
+ result.content = photo;
}, [&](const MTPDmessageMediaGeo &data) {
result.content = ParseGeoPoint(data.vgeo);
}, [&](const MTPDmessageMediaContact &data) {
@@ -796,12 +823,14 @@ Media ParseMedia(
}, [&](const MTPDmessageMediaUnsupported &data) {
result.content = UnsupportedMedia();
}, [&](const MTPDmessageMediaDocument &data) {
- result.content = data.has_document()
+ auto document = data.has_document()
? ParseDocument(context, data.vdocument, folder)
: Document();
if (data.has_ttl_seconds()) {
result.ttl = data.vttl_seconds.v;
+ document.file = File();
}
+ result.content = document;
}, [&](const MTPDmessageMediaWebPage &data) {
// Ignore web pages.
}, [&](const MTPDmessageMediaVenue &data) {
@@ -1053,6 +1082,10 @@ Message ParseMessage(
context,
data.vmedia,
mediaFolder);
+ if (result.media.ttl && !data.is_out()) {
+ result.media.file() = File();
+ result.media.thumb().file = File();
+ }
context.botId = 0;
}
result.text = ParseText(
diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h
index d14dc0ddd..840eb457f 100644
--- a/Telegram/SourceFiles/export/data/export_data_types.h
+++ b/Telegram/SourceFiles/export/data/export_data_types.h
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/optional.h"
#include "base/variant.h"
+#include
#include
#include
@@ -82,6 +83,14 @@ struct Image {
File file;
};
+std::pair WriteImageThumb(
+ const QString &basePath,
+ const QString &largePath,
+ Fn convertSize,
+ base::optional format = base::none,
+ base::optional quality = base::none,
+ const QString &postfix = "_thumb");
+
QString WriteImageThumb(
const QString &basePath,
const QString &largePath,
diff --git a/Telegram/SourceFiles/export/export_api_wrap.cpp b/Telegram/SourceFiles/export/export_api_wrap.cpp
index 148fe2472..3ccd8b62e 100644
--- a/Telegram/SourceFiles/export/export_api_wrap.cpp
+++ b/Telegram/SourceFiles/export/export_api_wrap.cpp
@@ -1096,6 +1096,11 @@ void ApiWrap::appendChatsSlice(
auto filtered = ranges::view::all(
info.list
) | ranges::view::filter([&](const Data::DialogInfo &info) {
+#ifdef _DEBUG
+ return (info.name == "Anta");
+#else
+#error "test"
+#endif
return (types & SettingsFromDialogsType(info.type)) != 0;
});
auto &list = to.info.list;
@@ -1365,10 +1370,12 @@ bool ApiWrap::processFileLoad(
return Type::Photo;
}) : Type(0);
+ const auto limit = _settings->media.sizeLimit;
if ((_settings->media.types & type) != type) {
file.skipReason = SkipReason::FileType;
return true;
- } else if (file.size >= _settings->media.sizeLimit) {
+ } else if ((message ? message->file().size : file.size) >= limit) {
+ // Don't load thumbs for large files that we skip.
file.skipReason = SkipReason::FileSize;
return true;
}
diff --git a/Telegram/SourceFiles/export/export_pch.h b/Telegram/SourceFiles/export/export_pch.h
index 8a0835457..8c420524a 100644
--- a/Telegram/SourceFiles/export/export_pch.h
+++ b/Telegram/SourceFiles/export/export_pch.h
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include
#include
#include
+#include
#include
#include
#include
diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp
index 3836e46aa..4bde5fa31 100644
--- a/Telegram/SourceFiles/export/output/export_output_html.cpp
+++ b/Telegram/SourceFiles/export/output/export_output_html.cpp
@@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "export/data/export_data_types.h"
#include "core/utils.h"
+#include
#include
#include
@@ -28,6 +29,14 @@ constexpr auto kServiceMessagePhotoSize = 60;
constexpr auto kHistoryUserpicSize = 42;
constexpr auto kSavedMessagesColorIndex = 3;
constexpr auto kJoinWithinSeconds = 900;
+constexpr auto kPhotoMaxWidth = 520;
+constexpr auto kPhotoMaxHeight = 520;
+constexpr auto kPhotoMinWidth = 80;
+constexpr auto kPhotoMinHeight = 80;
+constexpr auto kStickerMaxWidth = 384;
+constexpr auto kStickerMaxHeight = 384;
+constexpr auto kStickerMinWidth = 80;
+constexpr auto kStickerMinHeight = 80;
const auto kLineBreak = QByteArrayLiteral("
");
@@ -41,6 +50,50 @@ bool IsGlobalLink(const QString &link) {
|| link.startsWith(qstr("https://"), Qt::CaseInsensitive);
}
+QByteArray NoFileDescription(Data::File::SkipReason reason) {
+ using SkipReason = Data::File::SkipReason;
+ switch (reason) {
+ case SkipReason::Unavailable:
+ return "Unavailable, please try again later.";
+ case SkipReason::FileSize:
+ return "Exceeds maximum size, "
+ "change data exporting settings to download.";
+ case SkipReason::FileType:
+ return "Not included, "
+ "change data exporting settings to download.";
+ case SkipReason::None:
+ return "";
+ }
+ Unexpected("Skip reason in NoFileDescription.");
+}
+
+auto CalculateThumbSize(
+ int maxWidth,
+ int maxHeight,
+ int minWidth,
+ int minHeight,
+ bool expandForRetina = false) {
+ return [=](QSize largeSize) {
+ const auto multiplier = (expandForRetina ? 2 : 1);
+ const auto checkWidth = largeSize.width() * multiplier;
+ const auto checkHeight = largeSize.height() * multiplier;
+ const auto smallSize = (checkWidth > maxWidth
+ || checkHeight > maxHeight)
+ ? largeSize.scaled(
+ maxWidth,
+ maxHeight,
+ Qt::KeepAspectRatio)
+ : largeSize;
+ const auto retinaSize = QSize(
+ smallSize.width() & ~0x01,
+ smallSize.height() & ~0x01);
+ return (retinaSize.width() < kPhotoMinWidth
+ || retinaSize.height() < kPhotoMinHeight)
+ ? QSize()
+ : retinaSize;
+ };
+}
+
QByteArray SerializeString(const QByteArray &value) {
const auto size = value.size();
const auto begin = value.data();
@@ -517,11 +570,6 @@ public:
const QString &basePath,
const PeersMap &peers,
const QString &internalLinksDomain);
- [[nodiscard]] QByteArray pushMedia(
- const Data::Message &message,
- const QString &basePath,
- const PeersMap &peers,
- const QString &internalLinksDomain);
[[nodiscard]] Result writeBlock(const QByteArray &block);
@@ -554,6 +602,24 @@ private:
const QString &basePath,
const PeersMap &peers,
const QString &internalLinksDomain) const;
+ [[nodiscard]] QByteArray pushMedia(
+ const Data::Message &message,
+ const QString &basePath,
+ const PeersMap &peers,
+ const QString &internalLinksDomain);
+ [[nodiscard]] QByteArray pushGenericMedia(const MediaData &data);
+ [[nodiscard]] QByteArray pushStickerMedia(
+ const Data::Document &data,
+ const QString &basePath);
+ [[nodiscard]] QByteArray pushAnimatedMedia(
+ const Data::Document &data,
+ const QString &basePath);
+ [[nodiscard]] QByteArray pushVideoFileMedia(
+ const Data::Document &data,
+ const QString &basePath);
+ [[nodiscard]] QByteArray pushPhotoMedia(
+ const Data::Photo &data,
+ const QString &basePath);
File _file;
bool _closed = false;
@@ -1137,9 +1203,29 @@ QByteArray HtmlWriter::Wrap::pushMedia(
basePath,
peers,
internalLinksDomain);
- if (data.classes.isEmpty()) {
- return QByteArray();
+ if (!data.classes.isEmpty()) {
+ return pushGenericMedia(data);
}
+ const auto &content = message.media.content;
+ if (const auto document = base::get_if(&content)) {
+ Assert(!message.media.ttl);
+ if (document->isSticker) {
+ return pushStickerMedia(*document, basePath);
+ } else if (document->isAnimated) {
+ return pushAnimatedMedia(*document, basePath);
+ } else if (document->isVideoFile) {
+ return pushVideoFileMedia(*document, basePath);
+ }
+ Unexpected("Non generic document in HtmlWriter::Wrap::pushMedia.");
+ } else if (const auto photo = base::get_if(&content)) {
+ Assert(!message.media.ttl);
+ return pushPhotoMedia(*photo, basePath);
+ }
+ Assert(!content.has_value());
+ return QByteArray();
+}
+
+QByteArray HtmlWriter::Wrap::pushGenericMedia(const MediaData &data) {
auto result = pushDiv("media_wrap clearfix");
if (data.link.isEmpty()) {
result.append(pushDiv("media clearfix pull_left " + data.classes));
@@ -1189,6 +1275,222 @@ QByteArray HtmlWriter::Wrap::pushMedia(
return result;
}
+QByteArray HtmlWriter::Wrap::pushStickerMedia(
+ const Data::Document &data,
+ const QString &basePath) {
+ using namespace Data;
+
+ const auto [thumb, size] = WriteImageThumb(
+ basePath,
+ data.file.relativePath,
+ CalculateThumbSize(
+ kStickerMaxWidth,
+ kStickerMaxHeight,
+ kStickerMinWidth,
+ kStickerMinHeight),
+ "PNG",
+ -1);
+ if (thumb.isEmpty()) {
+ auto generic = MediaData();
+ generic.title = "Sticker";
+ generic.status = data.stickerEmoji;
+ if (data.file.relativePath.isEmpty()) {
+ generic.status += ", " + FormatFileSize(data.file.size);
+ } else {
+ generic.link = data.file.relativePath;
+ }
+ generic.description = NoFileDescription(data.file.skipReason);
+ generic.classes = "media_photo";
+ return pushGenericMedia(generic);
+ }
+ auto result = pushDiv("media_wrap clearfix");
+ result.append(pushTag("a", {
+ { "class", "sticker_wrap clearfix pull_left" },
+ {
+ "href",
+ relativePath(data.file.relativePath).toUtf8()
+ }
+ }));
+ const auto sizeStyle = "width: "
+ + NumberToString(size.width() / 2)
+ + "px; height: "
+ + NumberToString(size.height() / 2)
+ + "px";
+ result.append(pushTag("img", {
+ { "class", "sticker" },
+ { "style", sizeStyle },
+ { "src", relativePath(thumb).toUtf8() },
+ { "empty", "" }
+ }));
+ result.append(popTag());
+ result.append(popTag());
+ return result;
+}
+
+QByteArray HtmlWriter::Wrap::pushAnimatedMedia(
+ const Data::Document &data,
+ const QString &basePath) {
+ using namespace Data;
+
+ auto size = QSize(data.width, data.height);
+ auto thumbSize = CalculateThumbSize(
+ kPhotoMaxWidth,
+ kPhotoMaxHeight,
+ kPhotoMinWidth,
+ kPhotoMinHeight,
+ true)(size);
+ if (data.thumb.file.relativePath.isEmpty()
+ || data.file.relativePath.isEmpty()
+ || !thumbSize.width()
+ || !thumbSize.height()) {
+ auto generic = MediaData();
+ generic.title = "Animation";
+ generic.status = FormatFileSize(data.file.size);
+ generic.link = data.file.relativePath;
+ generic.description = NoFileDescription(data.file.skipReason);
+ generic.classes = "media_video";
+ return pushGenericMedia(generic);
+ }
+ auto result = pushDiv("media_wrap clearfix");
+ result.append(pushTag("a", {
+ { "class", "animated_wrap clearfix pull_left" },
+ {
+ "href",
+ relativePath(data.file.relativePath).toUtf8()
+ }
+ }));
+ result.append(pushDiv("video_play_bg"));
+ result.append(pushDiv("gif_play"));
+ result.append("GIF");
+ result.append(popTag());
+ result.append(popTag());
+ const auto sizeStyle = "width: "
+ + NumberToString(thumbSize.width() / 2)
+ + "px; height: "
+ + NumberToString(thumbSize.height() / 2)
+ + "px";
+ result.append(pushTag("img", {
+ { "class", "animated" },
+ { "style", sizeStyle },
+ { "src", relativePath(data.thumb.file.relativePath).toUtf8() },
+ { "empty", "" }
+ }));
+ result.append(popTag());
+ result.append(popTag());
+ return result;
+}
+
+QByteArray HtmlWriter::Wrap::pushVideoFileMedia(
+ const Data::Document &data,
+ const QString &basePath) {
+ using namespace Data;
+
+ auto size = QSize(data.width, data.height);
+ auto thumbSize = CalculateThumbSize(
+ kPhotoMaxWidth,
+ kPhotoMaxHeight,
+ kPhotoMinWidth,
+ kPhotoMinHeight,
+ true)(size);
+ if (data.thumb.file.relativePath.isEmpty()
+ || data.file.relativePath.isEmpty()
+ || !thumbSize.width()
+ || !thumbSize.height()) {
+ auto generic = MediaData();
+ generic.title = "Video file";
+ generic.status = FormatDuration(data.duration);
+ if (data.file.relativePath.isEmpty()) {
+ generic.status += ", " + FormatFileSize(data.file.size);
+ } else {
+ generic.link = data.file.relativePath;
+ }
+ generic.description = NoFileDescription(data.file.skipReason);
+ generic.classes = "media_video";
+ return pushGenericMedia(generic);
+ }
+ auto result = pushDiv("media_wrap clearfix");
+ result.append(pushTag("a", {
+ { "class", "video_file_wrap clearfix pull_left" },
+ {
+ "href",
+ relativePath(data.file.relativePath).toUtf8()
+ }
+ }));
+ result.append(pushDiv("video_play_bg"));
+ result.append(pushDiv("video_play"));
+ result.append(popTag());
+ result.append(popTag());
+ result.append(pushDiv("video_duration"));
+ result.append(FormatDuration(data.duration));
+ result.append(popTag());
+ const auto sizeStyle = "width: "
+ + NumberToString(thumbSize.width() / 2)
+ + "px; height: "
+ + NumberToString(thumbSize.height() / 2)
+ + "px";
+ result.append(pushTag("img", {
+ { "class", "video_file" },
+ { "style", sizeStyle },
+ { "src", relativePath(data.thumb.file.relativePath).toUtf8() },
+ { "empty", "" }
+ }));
+ result.append(popTag());
+ result.append(popTag());
+ return result;
+}
+
+QByteArray HtmlWriter::Wrap::pushPhotoMedia(
+ const Data::Photo &data,
+ const QString &basePath) {
+ using namespace Data;
+
+ const auto [thumb, size] = WriteImageThumb(
+ basePath,
+ data.image.file.relativePath,
+ CalculateThumbSize(
+ kPhotoMaxWidth,
+ kPhotoMaxHeight,
+ kPhotoMinWidth,
+ kPhotoMinHeight));
+ if (thumb.isEmpty()) {
+ auto generic = MediaData();
+ generic.title = "Photo";
+ generic.status = NumberToString(data.image.width)
+ + "x"
+ + NumberToString(data.image.height);
+ if (data.image.file.relativePath.isEmpty()) {
+ generic.status += ", " + FormatFileSize(data.image.file.size);
+ } else {
+ generic.link = data.image.file.relativePath;
+ }
+ generic.description = NoFileDescription(data.image.file.skipReason);
+ generic.classes = "media_photo";
+ return pushGenericMedia(generic);
+ }
+ auto result = pushDiv("media_wrap clearfix");
+ result.append(pushTag("a", {
+ { "class", "photo_wrap clearfix pull_left" },
+ {
+ "href",
+ relativePath(data.image.file.relativePath).toUtf8()
+ }
+ }));
+ const auto sizeStyle = "width: "
+ + NumberToString(size.width() / 2)
+ + "px; height: "
+ + NumberToString(size.height() / 2)
+ + "px";
+ result.append(pushTag("img", {
+ { "class", "photo" },
+ { "style", sizeStyle },
+ { "src", relativePath(thumb).toUtf8() },
+ { "empty", "" }
+ }));
+ result.append(popTag());
+ result.append(popTag());
+ return result;
+}
+
MediaData HtmlWriter::Wrap::prepareMediaData(
const Data::Message &message,
const QString &basePath,
@@ -1222,50 +1524,64 @@ MediaData HtmlWriter::Wrap::prepareMediaData(
return result;
}
- message.media.content.match([&](const Photo &photo) {
- // #TODO export: photo + self destruct (ttl)
- result.title = "Photo";
- result.status = NumberToString(photo.image.width)
- + "x"
- + NumberToString(photo.image.height);
- result.classes = "media_file"; // #TODO export
- result.link = photo.image.file.relativePath;
+ message.media.content.match([&](const Photo &data) {
+ if (message.media.ttl) {
+ result.title = "Self-destructing photo";
+ result.status = data.id
+ ? "Please view it on your mobile"
+ : "Expired";
+ result.classes = "media_photo";
+ return;
+ }
+ // At least try to pushPhotoMedia.
}, [&](const Document &data) {
- // #TODO export: sticker + thumb (video, video message) + self destruct (ttl)
+ if (message.media.ttl) {
+ result.title = "Self-destructing video";
+ result.status = data.id
+ ? "Please view it on your mobile"
+ : "Expired";
+ result.classes = "media_video";
+ return;
+ }
+ const auto hasFile = !data.file.relativePath.isEmpty();
result.link = data.file.relativePath;
+ result.description = NoFileDescription(data.file.skipReason);
if (data.isSticker) {
- result.title = "Sticker";
- result.status = data.stickerEmoji;
- result.classes = "media_file"; // #TODO export
+ // At least try to pushStickerMedia.
} else if (data.isVideoMessage) {
result.title = "Video message";
result.status = FormatDuration(data.duration);
+ if (!hasFile) {
+ result.status += ", " + FormatFileSize(data.file.size);
+ }
result.thumb = data.thumb.file.relativePath;
- result.classes = "media_file";
+ result.classes = "media_video";
} else if (data.isVoiceMessage) {
result.title = "Voice message";
result.status = FormatDuration(data.duration);
+ if (!hasFile) {
+ result.status += ", " + FormatFileSize(data.file.size);
+ }
result.classes = "media_voice_message";
} else if (data.isAnimated) {
- result.title = "Animation";
- result.status = FormatFileSize(data.duration);
- result.classes = "media_file"; // #TODO export
+ // At least try to pushAnimatedMedia.
} else if (data.isVideoFile) {
- result.title = "Video file";
- result.status = FormatDuration(data.duration);
- result.classes = "media_file"; // #TODO export
+ // At least try to pushVideoFileMedia.
} else if (data.isAudioFile) {
result.title = (data.songPerformer.isEmpty()
|| data.songTitle.isEmpty())
? QByteArray("Audio file")
: data.songPerformer + " \xe2\x80\x93 " + data.songTitle;
result.status = FormatDuration(data.duration);
+ if (!hasFile) {
+ result.status += ", " + FormatFileSize(data.file.size);
+ }
result.classes = "media_audio_file";
} else {
result.title = data.name.isEmpty()
? QByteArray("File")
: data.name;
- result.status = FormatFileSize(data.duration);
+ result.status = FormatFileSize(data.file.size);
result.classes = "media_file";
}
}, [&](const SharedContact &data) {
@@ -1434,7 +1750,9 @@ Result HtmlWriter::start(
"images/media_game.png",
"images/media_location.png",
"images/media_music.png",
+ "images/media_photo.png",
"images/media_shop.png",
+ "images/media_video.png",
"images/media_voice.png",
"images/section_calls.png",
"images/section_chats.png",