From a2fc7f691502a9b30effef02ecb0c4c826f43dfb Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 4 Apr 2016 11:21:14 +0400 Subject: [PATCH] Improved files support in inline bot results. --- Telegram/SourceFiles/dropdown.cpp | 4 +- Telegram/SourceFiles/layout.cpp | 117 ++++++++++++++++++++++++++++-- Telegram/SourceFiles/layout.h | 25 +------ Telegram/SourceFiles/structs.cpp | 13 +++- Telegram/SourceFiles/structs.h | 3 + Telegram/Telegram.vcxproj | 2 +- Telegram/Telegram.vcxproj.filters | 6 +- 7 files changed, 136 insertions(+), 34 deletions(-) diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index 71862c055..78fe10ba3 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -1798,10 +1798,10 @@ LayoutInlineItem *StickerPanInner::layoutPrepareInlineResult(InlineResult *resul using Type = InlineResult::Type; switch (result->type) { case Type::Photo: layout = new LayoutInlinePhoto(result); break; + case Type::Audio: + case Type::File: layout = new LayoutInlineFile(result); break; case Type::Video: layout = new LayoutInlineVideo(result); break; case Type::Sticker: layout = new LayoutInlineSticker(result); break; - case Type::Audio: - case Type::File: //layout = new LayoutInlineFile(result); break; case Type::Gif: layout = new LayoutInlineGif(result); break; case Type::Article: case Type::Contact: diff --git a/Telegram/SourceFiles/layout.cpp b/Telegram/SourceFiles/layout.cpp index a9f8dd8aa..f9b9b9295 100644 --- a/Telegram/SourceFiles/layout.cpp +++ b/Telegram/SourceFiles/layout.cpp @@ -1469,6 +1469,31 @@ QByteArray LayoutInlineAbstractFile::content_data() const { return _result->data(); } +ImagePtr LayoutInlineAbstractFile::content_thumb() const { + if (DocumentData *document = getShownDocument()) { + if (!document->thumb->isNull()) { + return document->thumb; + } + } + if (_result->photo && !_result->photo->thumb->isNull()) { + return _result->photo->thumb; + } + return _result->thumb; +} + +int LayoutInlineAbstractFile::content_duration() const { + if (_result->document) { + if (_result->document->duration() > 0) { + return _result->document->duration(); + } else if (SongData *song = _result->document->song()) { + if (song->duration) { + return song->duration; + } + } + } + return _result->duration; +} + LayoutInlineGif::LayoutInlineGif(InlineResult *result) : LayoutInlineAbstractFile(result) { } @@ -1955,19 +1980,19 @@ void LayoutInlinePhoto::content_forget() { } } -LayoutInlineVideo::LayoutInlineVideo(InlineResult *result) : LayoutInlineItem(result) +LayoutInlineVideo::LayoutInlineVideo(InlineResult *result) : LayoutInlineAbstractFile(result) , _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) , _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) { if (!result->content_url.isEmpty()) { _link = clickHandlerFromUrl(result->content_url); } - if (int duration = getDuration()) { + if (int duration = content_duration()) { _duration = formatDurationText(duration); } } void LayoutInlineVideo::initDimensions() { - bool withThumb = !getThumb()->isNull(); + bool withThumb = !content_thumb()->isNull(); _maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft; int32 textWidth = _maxw - (withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0); @@ -1988,7 +2013,7 @@ void LayoutInlineVideo::initDimensions() { void LayoutInlineVideo::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { int32 left = st::inlineThumbSize + st::inlineThumbSkip; - bool withThumb = !getThumb()->isNull(); + bool withThumb = !content_thumb()->isNull(); if (withThumb) { prepareThumb(st::inlineThumbSize, st::inlineThumbSize); if (_thumb.isNull()) { @@ -2035,7 +2060,7 @@ void LayoutInlineVideo::getState(ClickHandlerPtr &link, HistoryCursorState &curs } void LayoutInlineVideo::prepareThumb(int32 width, int32 height) const { - ImagePtr thumb = getThumb(); + ImagePtr thumb = content_thumb(); if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { int32 w = qMax(convertScale(thumb->width()), 1), h = qMax(convertScale(thumb->height()), 1); @@ -2057,6 +2082,88 @@ void LayoutInlineVideo::prepareThumb(int32 width, int32 height) const { } } +LayoutInlineFile::LayoutInlineFile(InlineResult *result) : LayoutInlineAbstractFile(result) +, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::msgFileSize - st::inlineThumbSkip) +, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::msgFileSize - st::inlineThumbSkip) { +} + +void LayoutInlineFile::initDimensions() { + _maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft; + int32 textWidth = _maxw - (st::msgFileSize + st::inlineThumbSkip); + TextParseOptions titleOpts = { 0, _maxw, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto }; + _title.setText(st::semiboldFont, textOneLine(_result->sendData->getLayoutTitle(_result)), titleOpts); + int32 titleHeight = qMin(_title.countHeight(_maxw), 2 * st::semiboldFont->height); + + int32 descriptionLines = 1; + + TextParseOptions descriptionOpts = { TextParseMultiline, _maxw, descriptionLines * st::normalFont->height, Qt::LayoutDirectionAuto }; + _description.setText(st::normalFont, _result->sendData->getLayoutDescription(_result), descriptionOpts); + int32 descriptionHeight = qMin(_description.countHeight(_maxw), descriptionLines * st::normalFont->height); + + _minh = st::msgFileSize; + _minh += st::inlineRowMargin * 2 + st::inlineRowBorder; +} + +void LayoutInlineFile::paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const { + int32 left = st::msgFileSize + st::inlineThumbSkip; + + QRect iconCircle = rtlrect(0, st::inlineRowMargin, st::msgFileSize, st::msgFileSize, _width); + p.setPen(Qt::NoPen); + //if (isThumbAnimation(ms)) { + // float64 over = _animation->a_thumbOver.current(); + // p.setBrush(style::interpolate(outbg ? st::msgFileOutBg : st::msgFileInBg, outbg ? st::msgFileOutBgOver : st::msgFileInBgOver, over)); + //} else { + bool over = ClickHandler::showAsActive(_send/*_data->loading() ? _cancell : _savel*/); + p.setBrush((over ? st::msgFileInBgOver : st::msgFileInBg)); + //} + + p.setRenderHint(QPainter::HighQualityAntialiasing); + p.drawEllipse(iconCircle); + p.setRenderHint(QPainter::HighQualityAntialiasing, false); + + style::sprite icon; + if (bool showPause = false) { + icon = st::msgFileInPause; + //} else if (radial || _data->loading()) { + // icon = st::msgFileInCancel; + //} else if (loaded) { + // if (_data->song() || _data->voice()) { + // icon = outbg ? (selected ? st::msgFileOutPlaySelected : st::msgFileOutPlay) : (selected ? st::msgFileInPlaySelected : st::msgFileInPlay); + // } else if (_data->isImage()) { + // icon = outbg ? (selected ? st::msgFileOutImageSelected : st::msgFileOutImage) : (selected ? st::msgFileInImageSelected : st::msgFileInImage); + // } else { + // icon = outbg ? (selected ? st::msgFileOutFileSelected : st::msgFileOutFile) : (selected ? st::msgFileInFileSelected : st::msgFileInFile); + // } + } else { + icon = st::msgFileInDownload; + } + p.drawSpriteCenter(iconCircle, icon); + + p.setPen(st::black); + _title.drawLeftElided(p, left, st::inlineRowMargin, _width - left, _width, 2); + int32 titleHeight = qMin(_title.countHeight(_width - left), st::semiboldFont->height * 2); + + p.setPen(st::inlineDescriptionFg); + int32 descriptionLines = 1; + _description.drawLeftElided(p, left, st::inlineRowMargin + titleHeight, _width - left, _width, descriptionLines); + + const InlinePaintContext *ctx = context->toInlinePaintContext(); + t_assert(ctx != nullptr); + if (!ctx->lastRow) { + p.fillRect(rtlrect(left, _height - st::inlineRowBorder, _width - left, st::inlineRowBorder, _width), st::inlineRowBorderFg); + } +} + +void LayoutInlineFile::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const { + if (x >= 0 && x < st::msgFileSize && y >= st::inlineRowMargin && y < st::inlineRowMargin + st::msgFileSize) { + return; + } + if (x >= st::msgFileSize + st::inlineThumbSkip && x < _width && y >= 0 && y < _height) { + link = _send; + return; + } +} + LayoutInlineArticle::LayoutInlineArticle(InlineResult *result, bool withThumb) : LayoutInlineItem(result) , _withThumb(withThumb) , _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) diff --git a/Telegram/SourceFiles/layout.h b/Telegram/SourceFiles/layout.h index 52fb1ec72..047478824 100644 --- a/Telegram/SourceFiles/layout.h +++ b/Telegram/SourceFiles/layout.h @@ -552,7 +552,8 @@ protected: void content_forget(); FileLocation content_location() const; QByteArray content_data() const; - + ImagePtr content_thumb() const; + int content_duration() const; }; class DeleteSavedGifClickHandler : public LeftButtonClickHandler { @@ -709,7 +710,7 @@ private: }; -class LayoutInlineVideo : public LayoutInlineItem { +class LayoutInlineVideo : public LayoutInlineAbstractFile { public: LayoutInlineVideo(InlineResult *result); @@ -720,20 +721,6 @@ public: private: - ImagePtr getThumb() const { - if (_result->document && !_result->document->thumb->isNull()) { - return _result->document->thumb; - } else if (_result->photo && !_result->photo->thumb->isNull()) { - return _result->photo->thumb; - } - return _result->thumb; - } - int getDuration() const { - if (_result->document && _result->document->duration() > 0) { - return _result->document->duration(); - } - return _result->duration; - } ClickHandlerPtr _link; mutable QPixmap _thumb; @@ -750,19 +737,13 @@ public: LayoutInlineFile(InlineResult *result); void initDimensions() override; - int32 resizeGetHeight(int32 width) override; void paint(Painter &p, const QRect &clip, uint32 selection, const PaintContext *context) const override; void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int32 x, int32 y) const override; private: - mutable QPixmap _thumb; Text _title, _description; - QString _letter, _urlText; - int32 _urlWidth; - - void prepareThumb(int32 width, int32 height) const; }; diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index e1dfb2f49..9d403a63e 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -1529,11 +1529,15 @@ InlineResultSendData::SentMTPMessageFields InlineResultSendFile::getSentMessageF uint64 docId = rand_value(); QVector attributes; + int duration = getSentDuration(owner); + QSize dimensions = getSentDimensions(owner); using Type = InlineResult::Type; if (owner->type == Type::Gif) { attributes.push_back(MTP_documentAttributeFilename(MTP_string((owner->content_type == qstr("video/mp4") ? "animation.gif.mp4" : "animation.gif")))); attributes.push_back(MTP_documentAttributeAnimated()); - attributes.push_back(MTP_documentAttributeVideo(MTP_int(owner->duration), MTP_int(owner->width), MTP_int(owner->height))); + attributes.push_back(MTP_documentAttributeVideo(MTP_int(duration), MTP_int(dimensions.width()), MTP_int(dimensions.height()))); + } else if (owner->type == Type::Video) { + attributes.push_back(MTP_documentAttributeVideo(MTP_int(duration), MTP_int(dimensions.width()), MTP_int(dimensions.height()))); } MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(owner->content_type), MTP_int(owner->data().size()), thumbSize, MTP_int(MTP::maindc()), MTP_vector(attributes)); if (tw > 0 && th > 0) { @@ -1546,6 +1550,13 @@ InlineResultSendData::SentMTPMessageFields InlineResultSendFile::getSentMessageF return result; } +int InlineResultSendFile::getSentDuration(InlineResult *owner) const { + return (_document && _document->duration()) ? _document->duration() : owner->duration; +} +QSize InlineResultSendFile::getSentDimensions(InlineResult *owner) const { + return (!_document || _document->dimensions.isEmpty()) ? QSize(owner->width, owner->height) : _document->dimensions; +} + void InlineResult::automaticLoadGif() { if (loaded() || type != Type::Gif || (content_type != qstr("video/mp4") && content_type != "image/gif")) return; diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index 7998d9342..310659540 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -1440,6 +1440,9 @@ private: DocumentData *_document; QString _url, _caption; + int getSentDuration(InlineResult *owner) const; + QSize getSentDimensions(InlineResult *owner) const; + }; class InlineResult { diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj index 9b228370b..8e57d2278 100644 --- a/Telegram/Telegram.vcxproj +++ b/Telegram/Telegram.vcxproj @@ -1203,6 +1203,7 @@ .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fstdafx.h" "-f../../SourceFiles/basic_types.h" -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG -D_SCL_SECURE_NO_WARNINGS "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\openssl\Release\include" "-I.\..\..\Libraries\ffmpeg" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I.\..\..\Libraries\breakpad\src" "-I.\ThirdParty\minizip" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.5.1\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.5.1\QtGui" + $(QTDIR)\bin\moc.exe;%(FullPath) @@ -2203,7 +2204,6 @@ - Moc%27ing sysbuttons.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters index 542d18246..5fb4039ba 100644 --- a/Telegram/Telegram.vcxproj.filters +++ b/Telegram/Telegram.vcxproj.filters @@ -986,9 +986,6 @@ Generated Files - - Source Files - Source Files @@ -1067,6 +1064,9 @@ mtproto + + gui +