diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 6898b7f18..52821a4e7 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -123,6 +123,8 @@ void SendFilesBox::prepareSingleFileLayout() { image = Images::prepareOpaque(std::move(image)); _preview = App::pixmapFromImageInPlace(std::move(image)); _preview.setDevicePixelRatio(cRetinaFactor()); + + prepareGifPreview(); } } if (_preview.isNull()) { @@ -130,6 +132,49 @@ void SendFilesBox::prepareSingleFileLayout() { } } +void SendFilesBox::prepareGifPreview() { + auto createGifPreview = [this] { + if (!_information) { + return false; + } + if (auto video = base::get_if(&_information->media)) { + return video->isGifv; + } + // Plain old .gif animation. + return _animated; + }; + if (createGifPreview()) { + _gifPreview = Media::Clip::MakeReader(FileLocation(_files.front()), QByteArray(), [this](Media::Clip::Notification notification) { + clipCallback(notification); + }); + if (_gifPreview) _gifPreview->setAutoplay(); + } +} + +void SendFilesBox::clipCallback(Media::Clip::Notification notification) { + using namespace Media::Clip; + switch (notification) { + case NotificationReinit: { + if (_gifPreview && _gifPreview->state() == State::Error) { + _gifPreview.setBad(); + } + + if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) { + auto s = QSize(_previewWidth, _previewHeight); + _gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None); + } + + update(); + } break; + + case NotificationRepaint: { + if (_gifPreview && !_gifPreview->currentDisplayed()) { + update(); + } + } break; + } +} + void SendFilesBox::prepareDocumentLayout() { auto filepath = _files.front(); if (filepath.isEmpty()) { @@ -283,8 +328,14 @@ void SendFilesBox::paintEvent(QPaintEvent *e) { if (_previewLeft + _previewWidth < width() - st::boxPhotoPadding.right()) { p.fillRect(_previewLeft + _previewWidth, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _previewLeft - _previewWidth, _previewHeight, st::confirmBg); } - p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), _preview); - if (_animated) { + if (_gifPreview && _gifPreview->started()) { + auto s = QSize(_previewWidth, _previewHeight); + auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None, getms()); + p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), frame); + } else { + p.drawPixmap(_previewLeft, st::boxPhotoPadding.top(), _preview); + } + if (_animated && !_gifPreview) { 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); @@ -400,9 +451,9 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg) QSize dimensions; ImagePtr image; QString caption; - DocumentData *doc = 0; - if (HistoryMedia *media = msg->getMedia()) { - HistoryMediaType t = media->type(); + DocumentData *doc = nullptr; + if (auto media = msg->getMedia()) { + auto t = media->type(); switch (t) { case MediaTypeGif: { _animated = true; @@ -480,6 +531,7 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg) } } _thumb = image->pixNoCache(maxW * cIntRetinaFactor(), maxH * cIntRetinaFactor(), Images::Option::Smooth | Images::Option::Blurred, maxW, maxH); + prepareGifPreview(doc); } else { maxW = dimensions.width(); maxH = dimensions.height(); @@ -520,6 +572,42 @@ EditCaptionBox::EditCaptionBox(QWidget*, HistoryItem *msg) } } +void EditCaptionBox::prepareGifPreview(DocumentData *document) { + auto createGifPreview = [document] { + return (document && document->isAnimation()); + }; + if (createGifPreview()) { + _gifPreview = Media::Clip::MakeReader(document->location(), document->data(), [this](Media::Clip::Notification notification) { + clipCallback(notification); + }); + if (_gifPreview) _gifPreview->setAutoplay(); + } +} + +void EditCaptionBox::clipCallback(Media::Clip::Notification notification) { + using namespace Media::Clip; + switch (notification) { + case NotificationReinit: { + if (_gifPreview && _gifPreview->state() == State::Error) { + _gifPreview.setBad(); + } + + if (_gifPreview && _gifPreview->ready() && !_gifPreview->started()) { + auto s = QSize(_thumbw, _thumbh); + _gifPreview->start(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None); + } + + update(); + } break; + + case NotificationRepaint: { + if (_gifPreview && !_gifPreview->currentDisplayed()) { + update(); + } + } break; + } +} + bool EditCaptionBox::canEdit(HistoryItem *message) { if (auto media = message->getMedia()) { switch (media->type()) { @@ -580,8 +668,14 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) { if (_thumbx + _thumbw < width() - st::boxPhotoPadding.right()) { p.fillRect(_thumbx + _thumbw, st::boxPhotoPadding.top(), width() - st::boxPhotoPadding.right() - _thumbx - _thumbw, _thumbh, st::confirmBg); } - p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb); - if (_animated) { + if (_gifPreview && _gifPreview->started()) { + auto s = QSize(_thumbw, _thumbh); + auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, ImageRoundCorner::None, getms()); + p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), frame); + } else { + p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), _thumb); + } + if (_animated && !_gifPreview) { QRect inner(_thumbx + (_thumbw - st::msgFileSize) / 2, st::boxPhotoPadding.top() + (_thumbh - st::msgFileSize) / 2, st::msgFileSize, st::msgFileSize); p.setPen(Qt::NoPen); p.setBrush(st::msgDateImgBg); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 0f1fe50f4..51fe070cd 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -66,6 +66,8 @@ private: void prepareSingleFileLayout(); void prepareDocumentLayout(); void tryToReadSingleFile(); + void prepareGifPreview(); + void clipCallback(Media::Clip::Notification notification); void updateTitleText(); void updateBoxSize(); @@ -84,6 +86,7 @@ private: int _previewLeft = 0; int _previewWidth = 0; int _previewHeight = 0; + Media::Clip::ReaderPointer _gifPreview; QPixmap _fileThumb; Text _nameText; @@ -131,6 +134,8 @@ protected: private: void updateBoxSize(); + void prepareGifPreview(DocumentData *document); + void clipCallback(Media::Clip::Notification notification); void saveDone(const MTPUpdates &updates); bool saveFail(const RPCError &error); @@ -141,6 +146,7 @@ private: bool _doc = false; QPixmap _thumb; + Media::Clip::ReaderPointer _gifPreview; object_ptr _field = { nullptr };