Show animated previews for GIFs in SendFilesBox.

This commit is contained in:
John Preston 2017-03-10 17:43:26 +03:00
parent a1b53c660e
commit 6c00b7efde
2 changed files with 107 additions and 7 deletions

View file

@ -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<FileLoadTask::Video>(&_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);

View file

@ -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<Ui::InputArea> _field = { nullptr };