mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 09:41:41 -05:00
Fix sending of .tgs stickers.
This commit is contained in:
parent
da48a78f7c
commit
7034df49e9
5 changed files with 72 additions and 39 deletions
|
@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/grouped_layout.h"
|
||||
#include "ui/text_options.h"
|
||||
#include "ui/special_buttons.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "data/data_document.h"
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "window/window_session_controller.h"
|
||||
|
@ -41,6 +42,7 @@ constexpr auto kMinPreviewWidth = 20;
|
|||
constexpr auto kShrinkDuration = crl::time(150);
|
||||
constexpr auto kDragDuration = crl::time(200);
|
||||
const auto kStickerMimeString = qstr("image/webp");
|
||||
const auto kAnimatedStickerMimeString = qstr("application/x-tgsticker");
|
||||
|
||||
class SingleMediaPreview : public Ui::RpWidget {
|
||||
public:
|
||||
|
@ -82,6 +84,7 @@ private:
|
|||
int _previewWidth = 0;
|
||||
int _previewHeight = 0;
|
||||
Media::Clip::ReaderPointer _gifPreview;
|
||||
std::unique_ptr<Lottie::SinglePlayer> _lottiePreview;
|
||||
|
||||
};
|
||||
|
||||
|
@ -590,7 +593,8 @@ SingleMediaPreview *SingleMediaPreview::Create(
|
|||
preview.height())) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto sticker = (file.information->filemime == kStickerMimeString);
|
||||
const auto sticker = (file.information->filemime == kStickerMimeString)
|
||||
|| (file.information->filemime == kAnimatedStickerMimeString);
|
||||
return Ui::CreateChild<SingleMediaPreview>(
|
||||
parent,
|
||||
controller,
|
||||
|
@ -627,7 +631,7 @@ void SingleMediaPreview::preparePreview(
|
|||
const QString &animatedPreviewPath) {
|
||||
auto maxW = 0;
|
||||
auto maxH = 0;
|
||||
if (_animated) {
|
||||
if (_animated && !_sticker) {
|
||||
auto limitW = st::sendMediaPreviewSize;
|
||||
auto limitH = st::confirmMaxHeight;
|
||||
maxW = qMax(preview.width(), 1);
|
||||
|
@ -683,7 +687,17 @@ void SingleMediaPreview::preparePreview(
|
|||
|
||||
void SingleMediaPreview::prepareAnimatedPreview(
|
||||
const QString &animatedPreviewPath) {
|
||||
if (!animatedPreviewPath.isEmpty()) {
|
||||
if (_sticker && _animated) {
|
||||
const auto box = QSize(_previewWidth, _previewHeight)
|
||||
* cIntRetinaFactor();
|
||||
_lottiePreview = std::make_unique<Lottie::SinglePlayer>(
|
||||
Lottie::ReadContent(QByteArray(), animatedPreviewPath),
|
||||
Lottie::FrameRequest{ box });
|
||||
_lottiePreview->updates(
|
||||
) | rpl::start_with_next([=] {
|
||||
update();
|
||||
}, lifetime());
|
||||
} else if (!animatedPreviewPath.isEmpty()) {
|
||||
auto callback = [=](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
};
|
||||
|
@ -734,10 +748,21 @@ void SingleMediaPreview::paintEvent(QPaintEvent *e) {
|
|||
auto paused = _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Layer);
|
||||
auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, RectPart::None, paused ? 0 : crl::now());
|
||||
p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), frame);
|
||||
} else if (_lottiePreview && _lottiePreview->ready()) {
|
||||
const auto frame = _lottiePreview->frame();
|
||||
const auto size = frame.size() / cIntRetinaFactor();
|
||||
p.drawImage(
|
||||
QRect(
|
||||
_previewLeft + (_previewWidth - size.width()) / 2,
|
||||
st::boxPhotoPadding.top() + (_previewHeight - size.height()) / 2,
|
||||
size.width(),
|
||||
size.height()),
|
||||
frame);
|
||||
_lottiePreview->markFrameShown();
|
||||
} else {
|
||||
p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), _preview);
|
||||
}
|
||||
if (_animated && !_gifPreview) {
|
||||
if (_animated && !_gifPreview && !_lottiePreview) {
|
||||
auto inner = QRect(_previewLeft + (_previewWidth - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_previewHeight - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(st::msgDateImgBg);
|
||||
|
|
|
@ -18,6 +18,7 @@ MimeType::MimeType(Known type) : _type(type) {
|
|||
QStringList MimeType::globPatterns() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return QStringList(qsl("*.webp"));
|
||||
case Known::Tgs: return QStringList(qsl("*.tgs"));
|
||||
case Known::TDesktopTheme: return QStringList(qsl("*.tdesktop-theme"));
|
||||
case Known::TDesktopPalette: return QStringList(qsl("*.tdesktop-palette"));
|
||||
default: break;
|
||||
|
@ -28,6 +29,7 @@ QStringList MimeType::globPatterns() const {
|
|||
QString MimeType::filterString() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("WebP image (*.webp)");
|
||||
case Known::Tgs: return qsl("Telegram sticker (*.tgs)");
|
||||
case Known::TDesktopTheme: return qsl("Theme files (*.tdesktop-theme)");
|
||||
case Known::TDesktopPalette: return qsl("Palette files (*.tdesktop-palette)");
|
||||
default: break;
|
||||
|
@ -38,6 +40,7 @@ QString MimeType::filterString() const {
|
|||
QString MimeType::name() const {
|
||||
switch (_type) {
|
||||
case Known::WebP: return qsl("image/webp");
|
||||
case Known::Tgs: return qsl("application/x-tgsticker");
|
||||
case Known::TDesktopTheme: return qsl("application/x-tdesktop-theme");
|
||||
case Known::TDesktopPalette: return qsl("application/x-tdesktop-palette");
|
||||
default: break;
|
||||
|
@ -48,6 +51,8 @@ QString MimeType::name() const {
|
|||
MimeType MimeTypeForName(const QString &mime) {
|
||||
if (mime == qstr("image/webp")) {
|
||||
return MimeType(MimeType::Known::WebP);
|
||||
} else if (mime == qstr("application/x-tgsticker")) {
|
||||
return MimeType(MimeType::Known::Tgs);
|
||||
} else if (mime == qstr("application/x-tdesktop-theme")) {
|
||||
return MimeType(MimeType::Known::TDesktopTheme);
|
||||
} else if (mime == qstr("application/x-tdesktop-palette")) {
|
||||
|
@ -62,6 +67,8 @@ MimeType MimeTypeForFile(const QFileInfo &file) {
|
|||
QString path = file.absoluteFilePath();
|
||||
if (path.endsWith(qstr(".webp"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::WebP);
|
||||
} else if (path.endsWith(qstr(".tgs"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::Tgs);
|
||||
} else if (path.endsWith(qstr(".tdesktop-theme"), Qt::CaseInsensitive)) {
|
||||
return MimeType(MimeType::Known::TDesktopTheme);
|
||||
} else if (path.endsWith(qstr(".tdesktop-palette"), Qt::CaseInsensitive)) {
|
||||
|
|
|
@ -20,6 +20,7 @@ public:
|
|||
TDesktopTheme,
|
||||
TDesktopPalette,
|
||||
WebP,
|
||||
Tgs,
|
||||
};
|
||||
|
||||
explicit MimeType(const QMimeType &type);
|
||||
|
|
|
@ -78,13 +78,8 @@ PreparedFileThumbnail PrepareFileThumbnail(QImage &&original) {
|
|||
PreparedFileThumbnail PrepareAnimatedStickerThumbnail(
|
||||
const QString &file,
|
||||
const QByteArray &bytes) {
|
||||
return PrepareFileThumbnail(Lottie::ReadThumbnail([&] {
|
||||
if (!bytes.isEmpty()) {
|
||||
return bytes;
|
||||
}
|
||||
auto f = QFile(file);
|
||||
return f.open(QIODevice::ReadOnly) ? f.readAll() : QByteArray();
|
||||
}()));
|
||||
return PrepareFileThumbnail(
|
||||
Lottie::ReadThumbnail(Lottie::ReadContent(bytes, file)));
|
||||
}
|
||||
|
||||
bool FileThumbnailUploadRequired(const QString &filemime, int32 filesize) {
|
||||
|
@ -683,14 +678,23 @@ bool FileLoadTask::CheckForImage(
|
|||
const QByteArray &content,
|
||||
std::unique_ptr<FileMediaInformation> &result) {
|
||||
auto animated = false;
|
||||
auto image = ([&filepath, &content, &animated] {
|
||||
auto image = [&] {
|
||||
if (filepath.endsWith(qstr(".tgs"), Qt::CaseInsensitive)) {
|
||||
auto image = Lottie::ReadThumbnail(
|
||||
Lottie::ReadContent(content, filepath));
|
||||
if (!image.isNull()) {
|
||||
animated = true;
|
||||
result->filemime = qstr("application/x-tgsticker");
|
||||
}
|
||||
return image;
|
||||
}
|
||||
if (!content.isEmpty()) {
|
||||
return App::readImage(content, nullptr, false, &animated);
|
||||
} else if (!filepath.isEmpty()) {
|
||||
return App::readImage(filepath, nullptr, false, &animated);
|
||||
}
|
||||
return QImage();
|
||||
})();
|
||||
}();
|
||||
return FillImageInformation(std::move(image), animated, result);
|
||||
}
|
||||
|
||||
|
@ -712,6 +716,7 @@ bool FileLoadTask::FillImageInformation(
|
|||
|
||||
void FileLoadTask::process() {
|
||||
const auto stickerMime = qsl("image/webp");
|
||||
const auto animatedStickerMime = qsl("application/x-tgsticker");
|
||||
|
||||
_result = std::make_shared<FileLoadResult>(
|
||||
id(),
|
||||
|
@ -754,7 +759,7 @@ void FileLoadTask::process() {
|
|||
if (auto image = base::get_if<FileMediaInformation::Image>(
|
||||
&_information->media)) {
|
||||
fullimage = base::take(image->data);
|
||||
if (auto opaque = (filemime != stickerMime)) {
|
||||
if (filemime != stickerMime && filemime != animatedStickerMime) {
|
||||
fullimage = Images::prepareOpaque(std::move(fullimage));
|
||||
}
|
||||
isAnimation = image->animated;
|
||||
|
@ -773,7 +778,7 @@ void FileLoadTask::process() {
|
|||
}
|
||||
const auto mimeType = Core::MimeTypeForData(_content);
|
||||
filemime = mimeType.name();
|
||||
if (filemime != stickerMime) {
|
||||
if (filemime != stickerMime && filemime != animatedStickerMime) {
|
||||
fullimage = Images::prepareOpaque(std::move(fullimage));
|
||||
}
|
||||
if (filemime == "image/jpeg") {
|
||||
|
@ -830,10 +835,6 @@ void FileLoadTask::process() {
|
|||
QByteArray goodThumbnailBytes;
|
||||
|
||||
QVector<MTPDocumentAttribute> attributes(1, MTP_documentAttributeFilename(MTP_string(filename)));
|
||||
const auto checkAnimatedSticker = filename.endsWith(qstr(".tgs"), Qt::CaseInsensitive);
|
||||
if (checkAnimatedSticker) {
|
||||
filemime = "application/x-tgsticker";
|
||||
}
|
||||
|
||||
auto thumbnail = PreparedFileThumbnail();
|
||||
|
||||
|
@ -872,8 +873,6 @@ void FileLoadTask::process() {
|
|||
}
|
||||
|
||||
thumbnail = PrepareFileThumbnail(std::move(video->thumbnail));
|
||||
} else if (checkAnimatedSticker) {
|
||||
thumbnail = PrepareAnimatedStickerThumbnail(_filepath, _content);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -882,7 +881,20 @@ void FileLoadTask::process() {
|
|||
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
|
||||
|
||||
if (ValidateThumbDimensions(w, h)) {
|
||||
if (isAnimation) {
|
||||
isSticker = (filemime == stickerMime
|
||||
|| filemime == animatedStickerMime)
|
||||
&& (w > 0)
|
||||
&& (h > 0)
|
||||
&& (w <= StickerMaxSize)
|
||||
&& (h <= StickerMaxSize)
|
||||
&& (filesize < Storage::kMaxStickerInMemory);
|
||||
if (isSticker) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(
|
||||
MTP_flags(0),
|
||||
MTP_string(QString()),
|
||||
MTP_inputStickerSetEmpty(),
|
||||
MTPMaskCoords()));
|
||||
} else if (isAnimation) {
|
||||
attributes.push_back(MTP_documentAttributeAnimated());
|
||||
} else if (_type != SendMediaType::File) {
|
||||
auto thumb = (w > 100 || h > 100) ? fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
|
||||
|
@ -915,21 +927,6 @@ void FileLoadTask::process() {
|
|||
filesize = _result->filesize = filedata.size();
|
||||
}
|
||||
}
|
||||
|
||||
isSticker = !isAnimation
|
||||
&& (filemime == stickerMime)
|
||||
&& (w > 0)
|
||||
&& (h > 0)
|
||||
&& (w <= StickerMaxSize)
|
||||
&& (h <= StickerMaxSize)
|
||||
&& (filesize < Storage::kMaxStickerInMemory);
|
||||
if (isSticker) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(
|
||||
MTP_flags(0),
|
||||
MTP_string(QString()),
|
||||
MTP_inputStickerSetEmpty(),
|
||||
MTPMaskCoords()));
|
||||
}
|
||||
thumbnail = PrepareFileThumbnail(std::move(fullimage));
|
||||
}
|
||||
}
|
||||
|
@ -937,7 +934,7 @@ void FileLoadTask::process() {
|
|||
std::move(thumbnail),
|
||||
filemime,
|
||||
filesize,
|
||||
isSticker || checkAnimatedSticker);
|
||||
isSticker);
|
||||
|
||||
if (_type == SendMediaType::Photo && photo.type() == mtpc_photoEmpty) {
|
||||
_type = SendMediaType::File;
|
||||
|
|
|
@ -316,7 +316,10 @@ bool PreparedList::canAddCaption(bool isAlbum, bool compressImages) const {
|
|||
if (files.empty() || compressImages) {
|
||||
return false;
|
||||
}
|
||||
return (files.front().mime == qstr("image/webp"));
|
||||
return (files.front().mime == qstr("image/webp"))
|
||||
|| files.front().path.endsWith(
|
||||
qstr(".tgs"),
|
||||
Qt::CaseInsensitive);
|
||||
};
|
||||
return isAlbum || (files.size() == 1 && !isSticker());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue