diff --git a/Telegram/SourceFiles/basic_types.h b/Telegram/SourceFiles/basic_types.h index 3d41159e0..46057e3f0 100644 --- a/Telegram/SourceFiles/basic_types.h +++ b/Telegram/SourceFiles/basic_types.h @@ -832,6 +832,49 @@ private: }; +// This pointer is used for static non-POD variables that are allocated +// on first use by constructor and are never automatically freed. +template +class StaticNeverFreedPointer { +public: + explicit StaticNeverFreedPointer(T *p) : _p(p) { + } + StaticNeverFreedPointer(const StaticNeverFreedPointer &other) = delete; + StaticNeverFreedPointer &operator=(const StaticNeverFreedPointer &other) = delete; + + T *data() const { + return _p; + } + T *release() { + return getPointerAndReset(_p); + } + void reset(T *p = nullptr) { + delete _p; + _p = p; + } + bool isNull() const { + return data() == nullptr; + } + + void clear() { + reset(); + } + T *operator->() const { + return data(); + } + T &operator*() const { + t_assert(!isNull()); + return *data(); + } + explicit operator bool() const { + return !isNull(); + } + +private: + T *_p = nullptr; + +}; + template inline void destroyImplementation(I *&ptr) { if (ptr) { diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp index 3133d1849..2da683b68 100644 --- a/Telegram/SourceFiles/dropdown.cpp +++ b/Telegram/SourceFiles/dropdown.cpp @@ -1458,82 +1458,25 @@ void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) { } InlineItem *item = _inlineRows.at(row).items.at(col); - PhotoData *photo = item->getPhoto(); - DocumentData *document = item->getDocument(); - InlineResult *inlineResult = item->getResult(); - using Type = InlineResult::Type; - auto getShownPhoto = [photo, inlineResult]() -> PhotoData* { - if (photo) { - return photo; - } else if (inlineResult && inlineResult->type == Type::Photo) { - return inlineResult->photo; - } - return nullptr; - }; - auto getShownDocument = [document, inlineResult]() -> DocumentData* { - auto inlineResultIsFileType = [](InlineResult *inlineResult) { - return inlineResult->type == Type::Video || - inlineResult->type == Type::Audio || - inlineResult->type == Type::Sticker || - inlineResult->type == Type::File || - inlineResult->type == Type::Gif; - }; - if (document) { - return document; - } else if (inlineResult && inlineResultIsFileType(inlineResult)) { - return inlineResult->document; - } - return nullptr; - }; - auto sendInlineItem = [photo, document, inlineResult, this]() -> void { - if (photo) { + if (PhotoData *photo = item->getPhoto()) { + if (photo->medium->loaded() || photo->thumb->loaded()) { emit selected(photo); - } else if (document) { + } else if (!photo->medium->loading()) { + photo->thumb->loadEvenCancelled(); + photo->medium->loadEvenCancelled(); + } + } else if (DocumentData *document = item->getDocument()) { + if (document->loaded()) { emit selected(document); - } else if (inlineResult) { + } else if (document->loading()) { + document->cancel(); + } else { + DocumentOpenClickHandler::doOpen(document, ActionOnLoadNone); + } + } else if (InlineResult *inlineResult = item->getResult()) { + if (inlineResult->onChoose(item)) { emit selected(inlineResult, _inlineBot); } - }; - if (PhotoData *shownPhoto = getShownPhoto()) { - if (shownPhoto->medium->loaded() || shownPhoto->thumb->loaded()) { - sendInlineItem(); - } else if (!shownPhoto->medium->loading()) { - shownPhoto->thumb->loadEvenCancelled(); - shownPhoto->medium->loadEvenCancelled(); - } - } else if (DocumentData *shownDocument = getShownDocument()) { - if (!inlineResult || inlineResult->type == Type::Gif) { - if (shownDocument->loaded()) { - sendInlineItem(); - } else if (shownDocument->loading()) { - shownDocument->cancel(); - } else { - DocumentOpenClickHandler::doOpen(shownDocument, ActionOnLoadNone); - } - } else { - sendInlineItem(); - } - } else if (inlineResult) { - if (inlineResult->type == Type::Photo) { - if (inlineResult->thumb->loaded()) { - sendInlineItem(); - } else if (!inlineResult->thumb->loading()) { - inlineResult->thumb->loadEvenCancelled(); - Ui::repaintInlineItem(item); - } - } else if (inlineResult->type == Type::Gif) { - if (inlineResult->loaded()) { - sendInlineItem(); - } else if (inlineResult->loading()) { - inlineResult->cancelFile(); - Ui::repaintInlineItem(item); - } else { - inlineResult->saveFile(QString(), LoadFromCloudOrLocal, false); - Ui::repaintInlineItem(item); - } - } else { - sendInlineItem(); - } } return; } @@ -1655,12 +1598,7 @@ void StickerPanInner::hideFinish(bool completely) { photo->forget(); } if (InlineResult *result = item->getResult()) { - if (DocumentData *document = result->document) { - document->forget(); - } - if (PhotoData *photo = result->photo) { - photo->forget(); - } + result->forget(); } }; clearInlineRows(false); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 02fcb27a6..13ec2849d 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -6775,7 +6775,7 @@ void HistoryWidget::onInlineResultSend(InlineBots::Result *result, UserData *bot result->addToHistory(_history, flags, messageId, messageFromId, messageDate, messageViaBotId, replyToId()); - _history->sendRequestId = MTP::send(MTPmessages_SendInlineBotResult(MTP_flags(sendFlags), _peer->input, MTP_int(replyToId()), MTP_long(randomId), MTP_long(result->queryId), MTP_string(result->id)), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId); + _history->sendRequestId = MTP::send(MTPmessages_SendInlineBotResult(MTP_flags(sendFlags), _peer->input, MTP_int(replyToId()), MTP_long(randomId), MTP_long(result->getQueryId()), MTP_string(result->getId())), App::main()->rpcDone(&MainWidget::sentUpdatesReceived), App::main()->rpcFail(&MainWidget::sendMessageFail), 0, 0, _history->sendRequestId); App::main()->finishForwarding(_history, _broadcast.checked(), _silent.checked()); cancelReply(lastKeyboardUsed); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index dbf5e9c4c..084219491 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -38,10 +38,8 @@ FileBase::FileBase(DocumentData *document) : ItemBase(document) { DocumentData *FileBase::getShownDocument() const { if (DocumentData *result = getDocument()) { return result; - } else if (Result *result = getResult()) { - return result->document; } - return nullptr; + return getResultDocument(); } int FileBase::content_width() const { @@ -52,10 +50,8 @@ int FileBase::content_width() const { if (!document->thumb->isNull()) { return convertScale(document->thumb->width()); } - } else if (_result) { - return _result->width; } - return 0; + return getResultWidth(); } int FileBase::content_height() const { @@ -66,10 +62,8 @@ int FileBase::content_height() const { if (!document->thumb->isNull()) { return convertScale(document->thumb->height()); } - } else if (_result) { - return _result->height; } - return 0; + return getResultHeight(); } bool FileBase::content_loading() const { @@ -136,23 +130,20 @@ ImagePtr FileBase::content_thumb() const { return document->thumb; } } - if (_result->photo && !_result->photo->thumb->isNull()) { - return _result->photo->thumb; - } - return _result->thumb; + return getResultThumb(); } int FileBase::content_duration() const { - if (_result->document) { - if (_result->document->duration() > 0) { - return _result->document->duration(); - } else if (SongData *song = _result->document->song()) { + if (DocumentData *document = getShownDocument()) { + if (document->duration() > 0) { + return document->duration(); + } else if (SongData *song = document->song()) { if (song->duration) { return song->duration; } } } - return _result->duration; + return getResultDuration(); } Gif::Gif(Result *result) : FileBase(result) { @@ -354,13 +345,14 @@ void Gif::prepareThumb(int32 width, int32 height, const QSize &frame) const { } } } else { - if (!_result->thumb_url.isEmpty()) { - if (_result->thumb->loaded()) { + ImagePtr thumb = getResultThumb(); + if (!thumb->isNull()) { + if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - _thumb = _result->thumb->pixNoCache(frame.width() * cIntRetinaFactor(), frame.height() * cIntRetinaFactor(), ImagePixSmooth, width, height); + _thumb = thumb->pixNoCache(frame.width() * cIntRetinaFactor(), frame.height() * cIntRetinaFactor(), ImagePixSmooth, width, height); } } else { - _result->thumb->load(); + thumb->load(); } } } @@ -437,8 +429,11 @@ void Sticker::preload() const { } else { document->checkSticker(); } - } else if (!_result->thumb->isNull()) { - _result->thumb->load(); + } else { + ImagePtr thumb = getResultThumb(); + if (!thumb->isNull()) { + thumb->load(); + } } } @@ -506,14 +501,15 @@ void Sticker::prepareThumb() const { _thumbLoaded = true; } } else { - if (_result->thumb->loaded()) { + ImagePtr thumb = getResultThumb(); + if (thumb->loaded()) { if (!_thumbLoaded) { QSize thumbSize = getThumbSize(); - _thumb = _result->thumb->pix(thumbSize.width(), thumbSize.height()); + _thumb = thumb->pix(thumbSize.width(), thumbSize.height()); _thumbLoaded = true; } } else { - _result->thumb->load(); + thumb->load(); } } } @@ -557,10 +553,8 @@ void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int32 x, PhotoData *Photo::getShownPhoto() const { if (PhotoData *result = getPhoto()) { return result; - } else if (Result *result = getResult()) { - return result->photo; } - return nullptr; + return getResultPhoto(); } QSize Photo::countFrameSize() const { @@ -605,12 +599,13 @@ void Photo::prepareThumb(int32 width, int32 height, const QSize &frame) const { photo->medium->load(); } } else { - if (_result->thumb->loaded()) { + ImagePtr thumb = getResultThumb(); + if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - _thumb = _result->thumb->pixNoCache(frame.width() * cIntRetinaFactor(), frame.height() * cIntRetinaFactor(), ImagePixSmooth, width, height); + _thumb = thumb->pixNoCache(frame.width() * cIntRetinaFactor(), frame.height() * cIntRetinaFactor(), ImagePixSmooth, width, height); } } else { - _result->thumb->load(); + thumb->load(); } } } @@ -618,19 +613,15 @@ void Photo::prepareThumb(int32 width, int32 height, const QSize &frame) const { int Photo::content_width() const { if (PhotoData *photo = getShownPhoto()) { return photo->full->width(); - } else if (_result) { - return _result->width; } - return 0; + return getResultWidth(); } int Photo::content_height() const { if (PhotoData *photo = getShownPhoto()) { return photo->full->height(); - } else if (_result) { - return _result->height; } - return 0; + return getResultHeight(); } bool Photo::content_loaded() const { @@ -649,11 +640,9 @@ void Photo::content_forget() { } Video::Video(Result *result) : FileBase(result) +, _link(getResultContentUrlHandler()) , _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 = content_duration()) { _duration = formatDurationText(duration); } @@ -749,7 +738,7 @@ void Video::prepareThumb(int32 width, int32 height) const { } void OpenFileClickHandler::onClickImpl() const { - _result->automaticLoadGif(); + _result->openFile(); } void CancelFileClickHandler::onClickImpl() const { @@ -907,52 +896,23 @@ void File::checkAnimationFinished() { } Article::Article(Result *result, bool withThumb) : ItemBase(result) +, _url(getResultUrlHandler()) +, _link(getResultContentUrlHandler()) , _withThumb(withThumb) , _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->url.isEmpty()) { - _url = clickHandlerFromUrl(result->url); - } - if (!result->content_url.isEmpty()) { - _link = clickHandlerFromUrl(result->content_url); - } else { - LocationCoords location; - if (result->getLocationCoords(&location)) { - _link.reset(new LocationClickHandler(location)); - int32 w = st::inlineThumbSize, h = st::inlineThumbSize; - int32 zoom = 13, scale = 1; - if (cScale() == dbisTwo || cRetina()) { - scale = 2; - w /= 2; - h /= 2; - } - QString coords = qsl("%1,%2").arg(location.lat).arg(location.lon); - QString url = qsl("https://maps.googleapis.com/maps/api/staticmap?center=") + coords + qsl("&zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big|").arg(zoom).arg(w).arg(h).arg(scale) + coords + qsl("&sensor=false"); - result->thumb = ImagePtr(url); - } - } - QVector parts = _result->url.splitRef('/'); - if (!parts.isEmpty()) { - QStringRef domain = parts.at(0); - if (parts.size() > 2 && domain.endsWith(':') && parts.at(1).isEmpty()) { // http:// and others - domain = parts.at(2); - } - - parts = domain.split('@').back().split('.'); - if (parts.size() > 1) { - _letter = parts.at(parts.size() - 2).at(0).toUpper(); - } - } - if (_letter.isEmpty() && !_result->title.isEmpty()) { - _letter = _result->title.at(0).toUpper(); + LocationCoords location; + if (!_link && result->getLocationCoords(&location)) { + _link.reset(new LocationClickHandler(location)); } + _thumbLetter = getResultThumbLetter(); } void Article::initDimensions() { _maxw = st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft; int32 textWidth = _maxw - (_withThumb ? (st::inlineThumbSize + st::inlineThumbSkip) : 0); TextParseOptions titleOpts = { 0, _maxw, 2 * st::semiboldFont->height, Qt::LayoutDirectionAuto }; - _title.setText(st::semiboldFont, textOneLine(_result->title), titleOpts); + _title.setText(st::semiboldFont, textOneLine(_result->getLayoutTitle()), titleOpts); int32 titleHeight = qMin(_title.countHeight(_maxw), 2 * st::semiboldFont->height); int32 descriptionLines = (_withThumb || _url) ? 2 : 3; @@ -970,10 +930,10 @@ void Article::initDimensions() { int32 Article::resizeGetHeight(int32 width) { _width = qMin(width, _maxw); if (_url) { - _urlText = _result->url; + _urlText = getResultUrl(); _urlWidth = st::normalFont->width(_urlText); if (_urlWidth > _width - st::inlineThumbSize - st::inlineThumbSkip) { - _urlText = st::normalFont->elided(_result->url, _width - st::inlineThumbSize - st::inlineThumbSkip); + _urlText = st::normalFont->elided(_urlText, _width - st::inlineThumbSize - st::inlineThumbSkip); _urlWidth = st::normalFont->width(_urlText); } } @@ -988,15 +948,16 @@ void Article::paint(Painter &p, const QRect &clip, uint32 selection, const Paint prepareThumb(st::inlineThumbSize, st::inlineThumbSize); QRect rthumb(rtlrect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize, _width)); if (_thumb.isNull()) { - if (_result->thumb->isNull() && !_letter.isEmpty()) { - int32 index = (_letter.at(0).unicode() % 4); + ImagePtr thumb = getResultThumb(); + if (thumb->isNull() && !_thumbLetter.isEmpty()) { + int32 index = (_thumbLetter.at(0).unicode() % 4); style::color colors[] = { st::msgFileRedColor, st::msgFileYellowColor, st::msgFileGreenColor, st::msgFileBlueColor }; p.fillRect(rthumb, colors[index]); - if (!_letter.isEmpty()) { + if (!_thumbLetter.isEmpty()) { p.setFont(st::linksLetterFont); p.setPen(st::white); - p.drawText(rthumb, _letter, style::al_center); + p.drawText(rthumb, _thumbLetter, style::al_center); } } else { p.fillRect(rthumb, st::overviewPhotoBg); @@ -1047,18 +1008,17 @@ void Article::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int32 } void Article::prepareThumb(int32 width, int32 height) const { - if (_result->thumb->isNull()) { - if (_result->type == Result::Type::Contact) { - if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - _thumb = userDefPhoto(qHash(_result->id) % UserColorsCount)->pixCircled(width, height); - } + ImagePtr thumb = getResultThumb(); + if (thumb->isNull()) { + if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { + _thumb = getResultContactAvatar(width, height); } return; } - if (_result->thumb->loaded()) { + if (thumb->loaded()) { if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) { - int32 w = qMax(convertScale(_result->thumb->width()), 1), h = qMax(convertScale(_result->thumb->height()), 1); + int32 w = qMax(convertScale(thumb->width()), 1), h = qMax(convertScale(thumb->height()), 1); if (w * height > h * width) { if (height < h) { w = w * height / h; @@ -1070,10 +1030,10 @@ void Article::prepareThumb(int32 width, int32 height) const { w = width; } } - _thumb = _result->thumb->pixNoCache(w * cIntRetinaFactor(), h * cIntRetinaFactor(), ImagePixSmooth, width, height); + _thumb = thumb->pixNoCache(w * cIntRetinaFactor(), h * cIntRetinaFactor(), ImagePixSmooth, width, height); } } else { - _result->thumb->load(); + thumb->load(); } } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h index 74b5c6e48..07fe52ea4 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h @@ -313,7 +313,7 @@ private: bool _withThumb; mutable QPixmap _thumb; Text _title, _description; - QString _letter, _urlText; + QString _thumbLetter, _urlText; int32 _urlWidth; void prepareThumb(int32 width, int32 height) const; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp index 5c5049e7a..5e7af361a 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp @@ -51,12 +51,12 @@ PhotoData *ItemBase::getPhoto() const { void ItemBase::preload() const { if (_result) { - if (_result->photo) { - _result->photo->thumb->load(); - } else if (_result->document) { - _result->document->thumb->load(); - } else if (!_result->thumb->isNull()) { - _result->thumb->load(); + if (_result->_photo) { + _result->_photo->thumb->load(); + } else if (_result->_document) { + _result->_document->thumb->load(); + } else if (!_result->_thumb->isNull()) { + _result->_thumb->load(); } } else if (_doc) { _doc->thumb->load(); @@ -74,7 +74,7 @@ void ItemBase::update() { UniquePointer ItemBase::createLayout(Result *result, bool forceThumb) { using Type = Result::Type; - switch (result->type) { + switch (result->_type) { case Type::Photo: return MakeUnique(result); break; case Type::Audio: case Type::File: return MakeUnique(result); break; @@ -92,5 +92,82 @@ UniquePointer ItemBase::createLayoutGif(DocumentData *document) { return MakeUnique(document, true); } +DocumentData *ItemBase::getResultDocument() const { + return _result ? _result->_document : nullptr; +} + +PhotoData *ItemBase::getResultPhoto() const { + return _result ? _result->_photo : nullptr; +} + +int ItemBase::getResultWidth() const { + return _result ? _result->_width : 0; +} + +int ItemBase::getResultHeight() const { + return _result ? _result->_height : 0; +} + +ImagePtr ItemBase::getResultThumb() const { + if (_result) { + if (_result->_photo && !_result->_photo->thumb->isNull()) { + return _result->_photo->thumb; + } + if (!_result->_thumb->isNull()) { + return _result->_thumb; + } + return _result->_locationThumb; + } + return ImagePtr(); +} + +QPixmap ItemBase::getResultContactAvatar(int width, int height) const { + if (_result->_type == Result::Type::Contact) { + return userDefPhoto(qHash(_result->_id) % UserColorsCount)->pixCircled(width, height); + } + return QPixmap(); +} + +int ItemBase::getResultDuration() const { + return _result->_duration; +} + +QString ItemBase::getResultUrl() const { + return _result->_url; +} + +ClickHandlerPtr ItemBase::getResultUrlHandler() const { + if (!_result->_url.isEmpty()) { + return clickHandlerFromUrl(_result->_url); + } + return ClickHandlerPtr(); +} + +ClickHandlerPtr ItemBase::getResultContentUrlHandler() const { + if (!_result->_content_url.isEmpty()) { + return clickHandlerFromUrl(_result->_content_url); + } + return ClickHandlerPtr(); +} + +QString ItemBase::getResultThumbLetter() const { + QVector parts = _result->_url.splitRef('/'); + if (!parts.isEmpty()) { + QStringRef domain = parts.at(0); + if (parts.size() > 2 && domain.endsWith(':') && parts.at(1).isEmpty()) { // http:// and others + domain = parts.at(2); + } + + parts = domain.split('@').back().split('.'); + if (parts.size() > 1) { + return parts.at(parts.size() - 2).at(0).toUpper(); + } + } + if (!_result->_title.isEmpty()) { + return _result->_title.at(0).toUpper(); + } + return QString(); +} + } // namespace Layout } // namespace InlineBots diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.h index 9f1896e74..6ee18f3bf 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.h @@ -89,6 +89,18 @@ public: static UniquePointer createLayoutGif(DocumentData *document); protected: + DocumentData *getResultDocument() const; + PhotoData *getResultPhoto() const; + int getResultWidth() const; + int getResultHeight() const; + ImagePtr getResultThumb() const; + QPixmap getResultContactAvatar(int width, int height) const; + int getResultDuration() const; + QString getResultUrl() const; + ClickHandlerPtr getResultUrlHandler() const; + ClickHandlerPtr getResultContentUrlHandler() const; + QString getResultThumbLetter() const; + Result *_result = nullptr; DocumentData *_doc = nullptr; PhotoData *_photo = nullptr; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index a1c2118b0..73932f904 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -56,18 +56,12 @@ Result *getResultFromLoader(FileLoader *loader) { return ResultsByLoader->value(loader, nullptr); } -namespace { - -using StringToTypeMap = QMap; -NeverFreedPointer stringToTypeMap; - -} // namespace - -Result::Result(const Creator &creator) : queryId(creator.queryId), type(creator.type) { +Result::Result(const Creator &creator) : _queryId(creator.queryId), _type(creator.type) { } UniquePointer Result::create(uint64 queryId, const MTPBotInlineResult &mtpData) { - stringToTypeMap.createIfNull([]() -> StringToTypeMap* { + using StringToTypeMap = QMap; + StaticNeverFreedPointer stringToTypeMap{ ([]() -> StringToTypeMap* { auto result = MakeUnique(); result->insert(qsl("photo"), Result::Type::Photo); result->insert(qsl("video"), Result::Type::Video); @@ -79,8 +73,9 @@ UniquePointer Result::create(uint64 queryId, const MTPBotInlineResult &m result->insert(qsl("contact"), Result::Type::Contact); result->insert(qsl("venue"), Result::Type::Venue); return result.release(); - }); - auto getInlineResultType = [](const MTPBotInlineResult &inlineResult) -> Type { + })() }; + + auto getInlineResultType = [&stringToTypeMap](const MTPBotInlineResult &inlineResult) -> Type { QString type; switch (inlineResult.type()) { case mtpc_botInlineResult: type = qs(inlineResult.c_botInlineResult().vtype); break; @@ -98,32 +93,38 @@ UniquePointer Result::create(uint64 queryId, const MTPBotInlineResult &m switch (mtpData.type()) { case mtpc_botInlineResult: { const MTPDbotInlineResult &r(mtpData.c_botInlineResult()); - result->id = qs(r.vid); - if (r.has_title()) result->title = qs(r.vtitle); - if (r.has_description()) result->description = qs(r.vdescription); - if (r.has_url()) result->url = qs(r.vurl); - if (r.has_thumb_url()) result->thumb_url = qs(r.vthumb_url); - if (r.has_content_type()) result->content_type = qs(r.vcontent_type); - if (r.has_content_url()) result->content_url = qs(r.vcontent_url); - if (r.has_w()) result->width = r.vw.v; - if (r.has_h()) result->height = r.vh.v; - if (r.has_duration()) result->duration = r.vduration.v; - if (!result->thumb_url.isEmpty() && (result->thumb_url.startsWith(qstr("http://"), Qt::CaseInsensitive) || result->thumb_url.startsWith(qstr("https://"), Qt::CaseInsensitive))) { - result->thumb = ImagePtr(result->thumb_url); + result->_id = qs(r.vid); + if (r.has_title()) result->_title = qs(r.vtitle); + if (r.has_description()) result->_description = qs(r.vdescription); + if (r.has_url()) result->_url = qs(r.vurl); + if (r.has_thumb_url()) result->_thumb_url = qs(r.vthumb_url); + if (r.has_content_type()) result->_content_type = qs(r.vcontent_type); + if (r.has_content_url()) result->_content_url = qs(r.vcontent_url); + if (r.has_w()) result->_width = r.vw.v; + if (r.has_h()) result->_height = r.vh.v; + if (r.has_duration()) result->_duration = r.vduration.v; + if (!result->_thumb_url.isEmpty() && (result->_thumb_url.startsWith(qstr("http://"), Qt::CaseInsensitive) || result->_thumb_url.startsWith(qstr("https://"), Qt::CaseInsensitive))) { + result->_thumb = ImagePtr(result->_thumb_url); } message = &r.vsend_message; } break; case mtpc_botInlineMediaResult: { const MTPDbotInlineMediaResult &r(mtpData.c_botInlineMediaResult()); - result->id = qs(r.vid); - if (r.has_title()) result->title = qs(r.vtitle); - if (r.has_description()) result->description = qs(r.vdescription); - if (r.has_photo()) result->photo = App::feedPhoto(r.vphoto); - if (r.has_document()) result->document = App::feedDocument(r.vdocument); + result->_id = qs(r.vid); + if (r.has_title()) result->_title = qs(r.vtitle); + if (r.has_description()) result->_description = qs(r.vdescription); + if (r.has_photo()) { + result->_mtpPhoto = r.vphoto; + result->_photo = App::feedPhoto(r.vphoto); + } + if (r.has_document()) { + result->_mtpDocument = r.vdocument; + result->_document = App::feedDocument(r.vdocument); + } message = &r.vsend_message; } break; } - bool badAttachment = (result->photo && !result->photo->access) || (result->document && !result->document->access); + bool badAttachment = (result->_photo && !result->_photo->access) || (result->_document && !result->_document->access); if (!message) { return UniquePointer(); @@ -132,10 +133,10 @@ UniquePointer Result::create(uint64 queryId, const MTPBotInlineResult &m switch (message->type()) { case mtpc_botInlineMessageMediaAuto: { const MTPDbotInlineMessageMediaAuto &r(message->c_botInlineMessageMediaAuto()); - if (result->type == Type::Photo) { - result->sendData.reset(new internal::SendPhoto(result->photo, result->content_url, qs(r.vcaption))); + if (result->_type == Type::Photo) { + result->sendData.reset(new internal::SendPhoto(result->_photo, result->_content_url, qs(r.vcaption))); } else { - result->sendData.reset(new internal::SendFile(result->document, result->content_url, qs(r.vcaption))); + result->sendData.reset(new internal::SendFile(result->_document, result->_content_url, qs(r.vcaption))); } } break; @@ -176,11 +177,81 @@ UniquePointer Result::create(uint64 queryId, const MTPBotInlineResult &m if (badAttachment || !result->sendData || !result->sendData->isValid()) { return UniquePointer(); } + + LocationCoords location; + if (result->getLocationCoords(&location)) { + int32 w = st::inlineThumbSize, h = st::inlineThumbSize; + int32 zoom = 13, scale = 1; + if (cScale() == dbisTwo || cRetina()) { + scale = 2; + w /= 2; + h /= 2; + } + QString coords = qsl("%1,%2").arg(location.lat).arg(location.lon); + QString url = qsl("https://maps.googleapis.com/maps/api/staticmap?center=") + coords + qsl("&zoom=%1&size=%2x%3&maptype=roadmap&scale=%4&markers=color:red|size:big|").arg(zoom).arg(w).arg(h).arg(scale) + coords + qsl("&sensor=false"); + result->_locationThumb = ImagePtr(url); + } + return result; } +bool Result::onChoose(Layout::ItemBase *layout) { + if (_photo && _type == Type::Photo) { + if (_photo->medium->loaded() || _photo->thumb->loaded()) { + return true; + } else if (!_photo->medium->loading()) { + _photo->thumb->loadEvenCancelled(); + _photo->medium->loadEvenCancelled(); + } + } + if (_document && ( + _type == Type::Video || + _type == Type::Audio || + _type == Type::Sticker || + _type == Type::File || + _type == Type::Gif)) { + if (_type == Type::Gif) { + if (_document->loaded()) { + return true; + } else if (_document->loading()) { + _document->cancel(); + } else { + DocumentOpenClickHandler::doOpen(_document, ActionOnLoadNone); + } + } else { + return true; + } + } + if (_type == Type::Photo) { + if (_thumb->loaded()) { + return true; + } else if (!_thumb->loading()) { + _thumb->loadEvenCancelled(); + Ui::repaintInlineItem(layout); + } + } else if (_type == Type::Gif) { + if (loaded()) { + return true; + } else if (loading()) { + cancelFile(); + Ui::repaintInlineItem(layout); + } else { + saveFile(QString(), LoadFromCloudOrLocal, false); + Ui::repaintInlineItem(layout); + } + } else { + return true; + } + return false; +} + void Result::automaticLoadGif() { - if (loaded() || type != Type::Gif || (content_type != qstr("video/mp4") && content_type != "image/gif")) return; + if (loaded() || _type != Type::Gif) { + return; + } + if (_content_type != qstr("video/mp4") && _content_type != qstr("image/gif")) { + return; + } if (_loader != CancelledWebFileLoader) { // if load at least anywhere @@ -191,7 +262,7 @@ void Result::automaticLoadGif() { void Result::automaticLoadSettingsChangedGif() { if (loaded() || _loader != CancelledWebFileLoader) return; - _loader = 0; + _loader = nullptr; } void Result::saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, bool autoLoading) { @@ -199,18 +270,18 @@ void Result::saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, boo return; } - if (_loader == CancelledWebFileLoader) _loader = 0; + if (_loader == CancelledWebFileLoader) _loader = nullptr; if (_loader) { if (!_loader->setFileName(toFile)) { cancelFile(); - _loader = 0; + _loader = nullptr; } } if (_loader) { if (fromCloud == LoadFromCloudOrLocal) _loader->permitLoadFromCloud(); } else { - _loader = new webFileLoader(content_url, toFile, fromCloud, autoLoading); + _loader = new webFileLoader(_content_url, toFile, fromCloud, autoLoading); regLoader(_loader, this); _loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(inlineResultLoadProgress(FileLoader*))); @@ -219,6 +290,80 @@ void Result::saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, boo } } +void Result::openFile() { + //if (loaded()) { + // bool playVoice = data->voice() && audioPlayer() && item; + // bool playMusic = data->song() && audioPlayer() && item; + // bool playAnimation = data->isAnimation() && item && item->getMedia(); + // const FileLocation &location(data->location(true)); + // if (!location.isEmpty() || (!data->data().isEmpty() && (playVoice || playMusic || playAnimation))) { + // if (playVoice) { + // AudioMsgId playing; + // AudioPlayerState playingState = AudioPlayerStopped; + // audioPlayer()->currentState(&playing, &playingState); + // if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) { + // audioPlayer()->pauseresume(OverviewVoiceFiles); + // } else { + // AudioMsgId audio(data, item->fullId()); + // audioPlayer()->play(audio); + // if (App::main()) { + // App::main()->audioPlayProgress(audio); + // App::main()->mediaMarkRead(data); + // } + // } + // } else if (playMusic) { + // SongMsgId playing; + // AudioPlayerState playingState = AudioPlayerStopped; + // audioPlayer()->currentState(&playing, &playingState); + // if (playing.msgId == item->fullId() && !(playingState & AudioPlayerStoppedMask) && playingState != AudioPlayerFinishing) { + // audioPlayer()->pauseresume(OverviewFiles); + // } else { + // SongMsgId song(data, item->fullId()); + // audioPlayer()->play(song); + // if (App::main()) App::main()->documentPlayProgress(song); + // } + // } else if (data->voice() || data->isVideo()) { + // psOpenFile(location.name()); + // if (App::main()) App::main()->mediaMarkRead(data); + // } else if (data->size < MediaViewImageSizeLimit) { + // if (!data->data().isEmpty() && playAnimation) { + // if (action == ActionOnLoadPlayInline && item->getMedia()) { + // item->getMedia()->playInline(item); + // } else { + // App::wnd()->showDocument(data, item); + // } + // } else if (location.accessEnable()) { + // if (item && (data->isAnimation() || QImageReader(location.name()).canRead())) { + // if (action == ActionOnLoadPlayInline && item->getMedia()) { + // item->getMedia()->playInline(item); + // } else { + // App::wnd()->showDocument(data, item); + // } + // } else { + // psOpenFile(location.name()); + // } + // location.accessDisable(); + // } else { + // psOpenFile(location.name()); + // } + // } else { + // psOpenFile(location.name()); + // } + // return; + // } + //} + + //QString filename = documentSaveFilename(data); + //if (filename.isEmpty()) return; + //if (!data->saveToCache()) { + // filename = documentSaveFilename(data); + // if (filename.isEmpty()) return; + //} + + //saveFile() + //data->save(filename, action, item ? item->fullId() : FullMsgId()); +} + void Result::cancelFile() { if (!loading()) return; @@ -254,7 +399,7 @@ bool Result::loaded() const { _loader->deleteLater(); _loader->stop(); - _loader = 0; + _loader = nullptr; } } return !_data.isEmpty(); @@ -265,8 +410,14 @@ bool Result::displayLoading() const { } void Result::forget() { - thumb->forget(); + _thumb->forget(); _data.clear(); + if (_document) { + _document->forget(); + } + if (_photo) { + _photo->forget(); + } } float64 Result::progress() const { @@ -274,10 +425,10 @@ float64 Result::progress() const { } bool Result::hasThumbDisplay() const { - if (!thumb->isNull()) { + if (!_thumb->isNull()) { return true; } - if (type == Type::Contact) { + if (_type == Type::Contact) { return true; } if (sendData->hasLocationCoords()) { diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h index 1c21aba48..4f3fe830e 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h @@ -42,18 +42,6 @@ private: struct Creator; public: - enum class Type { - Unknown, - Photo, - Video, - Audio, - Sticker, - File, - Gif, - Article, - Contact, - Venue, - }; // Constructor is public only for MakeUnique<>() to work. // You should use create() static method instead. @@ -62,22 +50,21 @@ public: Result(const Result &other) = delete; Result &operator=(const Result &other) = delete; - uint64 queryId; - QString id; - Type type; - DocumentData *document = nullptr; - PhotoData *photo = nullptr; - QString title, description, url, thumb_url; - QString content_type, content_url; - int width = 0; - int height = 0; - int duration = 0; + uint64 getQueryId() const { + return _queryId; + } + QString getId() const { + return _id; + } - ImagePtr thumb; + // This is real SendClickHandler::onClick implementation for the specified + // inline bot result. If it returns true you need to send this result. + bool onChoose(Layout::ItemBase *layout); void automaticLoadGif(); void automaticLoadSettingsChangedGif(); void saveFile(const QString &toFile, LoadFromCloudSetting fromCloud, bool autoLoading); + void openFile(); void cancelFile(); QByteArray data() const; @@ -99,11 +86,43 @@ public: ~Result(); private: + enum class Type { + Unknown, + Photo, + Video, + Audio, + Sticker, + File, + Gif, + Article, + Contact, + Venue, + }; + + friend class internal::SendData; + friend class Layout::ItemBase; struct Creator { uint64 queryId; Type type; }; + uint64 _queryId = 0; + QString _id; + Type _type = Type::Unknown; + QString _title, _description, _url, _thumb_url; + QString _content_type, _content_url; + int _width = 0; + int _height = 0; + int _duration = 0; + + mutable MTPDocument _mtpDocument = MTP_documentEmpty(MTP_long(0)); + DocumentData *_document = nullptr; + + mutable MTPPhoto _mtpPhoto = MTP_photoEmpty(MTP_long(0)); + PhotoData *_photo = nullptr; + + ImagePtr _thumb, _locationThumb; + UniquePointer sendData; QByteArray _data; diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp index 9de282491..9e4fd6216 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.cpp @@ -28,11 +28,59 @@ namespace InlineBots { namespace internal { QString SendData::getLayoutTitle(const Result *owner) const { - return owner->title; + return owner->_title; } QString SendData::getLayoutDescription(const Result *owner) const { - return owner->description; + return owner->_description; +} + +ImagePtr SendData::getResultThumb(const Result *owner) const { + return owner->_thumb; +} + +int SendData::getResultWidth(const Result *owner) const { + return owner->_width; +} + +int SendData::getResultHeight(const Result *owner) const { + return owner->_height; +} + +QString SendData::getResultMime(const Result *owner) const { + return owner->_content_type; +} + +QVector SendData::prepareResultAttributes(const Result *owner) const { + QVector result; + int duration = owner->_duration; + QSize dimensions(owner->_width, owner->_height); + using Type = Result::Type; + if (owner->_type == Type::Gif) { + const char *filename = (owner->_content_type == qstr("video/mp4") ? "animation.gif.mp4" : "animation.gif"); + result.push_back(MTP_documentAttributeFilename(MTP_string(filename))); + result.push_back(MTP_documentAttributeAnimated()); + result.push_back(MTP_documentAttributeVideo(MTP_int(owner->_duration), MTP_int(owner->_width), MTP_int(owner->_height))); + } else if (owner->_type == Type::Video) { + result.push_back(MTP_documentAttributeVideo(MTP_int(owner->_duration), MTP_int(owner->_width), MTP_int(owner->_height))); + } + return result; +} + +void SendData::setResultDocument(const Result *owner, const MTPDocument &document) const { + owner->_mtpDocument = document; +} + +void SendData::setResultPhoto(const Result *owner, const MTPPhoto &photo) const { + owner->_mtpPhoto = photo; +} + +MTPDocument SendData::getResultDocument(const Result *owner) const { + return owner->_mtpDocument; +} + +MTPPhoto SendData::getResultPhoto(const Result *owner) const { + return owner->_mtpPhoto; } SendData::SentMTPMessageFields SendText::getSentMessageFields(const Result*) const { @@ -61,13 +109,14 @@ SendData::SentMTPMessageFields SendContact::getSentMessageFields(const Result*) } QString SendContact::getLayoutDescription(const Result *owner) const { - return App::formatPhone(_phoneNumber) + '\n' + owner->description; + return App::formatPhone(_phoneNumber) + '\n' + SendData::getLayoutDescription(owner); } SendData::SentMTPMessageFields SendPhoto::getSentMessageFields(const Result *owner) const { SentMTPMessageFields result; - QImage fileThumb(owner->thumb->pix().toImage()); + ImagePtr resultThumb = getResultThumb(owner); + QImage fileThumb(resultThumb->pix().toImage()); QVector photoSizes; @@ -75,13 +124,13 @@ SendData::SentMTPMessageFields SendPhoto::getSentMessageFields(const Result *own ImagePtr thumbPtr = ImagePtr(thumb, "JPG"); photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0))); - QSize medium = resizeKeepAspect(owner->width, owner->height, 320, 320); + QSize medium = resizeKeepAspect(getResultWidth(owner), getResultHeight(owner), 320, 320); photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0))); - photoSizes.push_back(MTP_photoSize(MTP_string("x"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(owner->width), MTP_int(owner->height), MTP_int(0))); + photoSizes.push_back(MTP_photoSize(MTP_string("x"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(getResultWidth(owner)), MTP_int(getResultHeight(owner)), MTP_int(0))); uint64 photoId = rand_value(); - PhotoData *ph = App::photoSet(photoId, 0, 0, unixtime(), thumbPtr, ImagePtr(medium.width(), medium.height()), ImagePtr(owner->width, owner->height)); + PhotoData *ph = App::photoSet(photoId, 0, 0, unixtime(), thumbPtr, ImagePtr(medium.width(), medium.height()), ImagePtr(getResultWidth(owner), getResultHeight(owner))); MTPPhoto photo = MTP_photo(MTP_long(photoId), MTP_long(0), MTP_int(ph->date), MTP_vector(photoSizes)); result.media = MTP_messageMediaPhoto(photo, MTP_string(_caption)); @@ -89,13 +138,14 @@ SendData::SentMTPMessageFields SendPhoto::getSentMessageFields(const Result *own return result; } -SendData::SentMTPMessageFields SendFile::getSentMessageFields(const Result *owner) const { - SentMTPMessageFields result; +void SendFile::prepareDocument(const Result *owner) const { + if (getResultDocument(owner).type() != mtpc_documentEmpty) return; + ImagePtr resultThumb = getResultThumb(owner); MTPPhotoSize thumbSize; QPixmap thumb; - int32 tw = owner->thumb->width(), th = owner->thumb->height(); - if (tw > 0 && th > 0 && tw < 20 * th && th < 20 * tw && owner->thumb->loaded()) { + int32 tw = resultThumb->width(), th = resultThumb->height(); + if (tw > 0 && th > 0 && tw < 20 * th && th < 20 * tw && resultThumb->loaded()) { if (tw > th) { if (tw > 90) { th = th * 90 / tw; @@ -106,41 +156,34 @@ SendData::SentMTPMessageFields SendFile::getSentMessageFields(const Result *owne th = 90; } thumbSize = MTP_photoSize(MTP_string(""), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(tw), MTP_int(th), MTP_int(0)); - thumb = owner->thumb->pixNoCache(tw, th, ImagePixSmooth); + thumb = resultThumb->pixNoCache(tw, th, ImagePixSmooth); } else { tw = th = 0; thumbSize = MTP_photoSizeEmpty(MTP_string("")); } uint64 docId = rand_value(); - QVector attributes; - int duration = getSentDuration(owner); - QSize dimensions = getSentDimensions(owner); - using Type = Result::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(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)); + QVector attributes = prepareResultAttributes(owner); + MTPDocument document = MTP_document(MTP_long(docId), MTP_long(0), MTP_int(unixtime()), MTP_string(getResultMime(owner)), MTP_int(owner->data().size()), thumbSize, MTP_int(MTP::maindc()), MTP_vector(attributes)); if (tw > 0 && th > 0) { App::feedDocument(document, thumb); } - Local::writeStickerImage(mediaKey(DocumentFileLocation, MTP::maindc(), docId), owner->data()); + if (!owner->data().isEmpty()) { + Local::writeStickerImage(mediaKey(DocumentFileLocation, MTP::maindc(), docId), owner->data()); + } + setResultDocument(owner, document); +} +SendData::SentMTPMessageFields SendFile::getSentMessageFields(const Result *owner) const { + SentMTPMessageFields result; + + prepareDocument(owner); + + MTPDocument document = getResultDocument(owner); result.media = MTP_messageMediaDocument(document, MTP_string(_caption)); return result; } -int SendFile::getSentDuration(const Result *owner) const { - return (_document && _document->duration()) ? _document->duration() : owner->duration; -} -QSize SendFile::getSentDimensions(const Result *owner) const { - return (!_document || _document->dimensions.isEmpty()) ? QSize(owner->width, owner->height) : _document->dimensions; -} - } // namespace internal } // namespace InlineBots diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h index 7c70b0a84..7ce652f39 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h +++ b/Telegram/SourceFiles/inline_bots/inline_bot_send_data.h @@ -67,6 +67,20 @@ public: virtual QString getLayoutTitle(const Result *owner) const; virtual QString getLayoutDescription(const Result *owner) const; +protected: + + ImagePtr getResultThumb(const Result *owner) const; + int getResultWidth(const Result *owner) const; + int getResultHeight(const Result *owner) const; + QString getResultMime(const Result *owner) const; + QVector prepareResultAttributes(const Result *owner) const; + + void setResultDocument(const Result *owner, const MTPDocument &document) const; + void setResultPhoto(const Result *owner, const MTPPhoto &photo) const; + + MTPDocument getResultDocument(const Result *owner) const; + MTPPhoto getResultPhoto(const Result *owner) const; + }; // Plain text message. @@ -221,12 +235,11 @@ public: SentMTPMessageFields getSentMessageFields(const Result *owner) const override; private: + void prepareDocument(const Result *owner) const; + DocumentData *_document; QString _url, _caption; - int getSentDuration(const Result *owner) const; - QSize getSentDimensions(const Result *owner) const; - }; } // namespace internal