| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | /*
 | 
					
						
							|  |  |  | This file is part of Telegram Desktop, | 
					
						
							| 
									
										
										
										
											2018-01-03 13:23:14 +03:00
										 |  |  | the official desktop application for the Telegram messaging service. | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-03 13:23:14 +03:00
										 |  |  | For license and copyright information please follow this link: | 
					
						
							|  |  |  | https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | */ | 
					
						
							|  |  |  | #include "inline_bots/inline_bot_layout_item.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:49:16 +03:00
										 |  |  | #include "data/data_photo.h"
 | 
					
						
							|  |  |  | #include "data/data_document.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-04 15:09:48 +04:00
										 |  |  | #include "data/data_peer.h"
 | 
					
						
							| 
									
										
										
										
											2019-12-05 11:32:33 +03:00
										 |  |  | #include "data/data_file_origin.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-10 17:18:51 +04:00
										 |  |  | #include "data/data_document_media.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-13 00:31:28 +03:00
										 |  |  | #include "core/click_handler_types.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | #include "inline_bots/inline_bot_result.h"
 | 
					
						
							|  |  |  | #include "inline_bots/inline_bot_layout_internal.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-04 13:23:56 +03:00
										 |  |  | #include "storage/localstorage.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | #include "mainwidget.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-23 13:44:42 +04:00
										 |  |  | #include "ui/image/image.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-05 12:43:18 +04:00
										 |  |  | #include "ui/empty_userpic.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace InlineBots { | 
					
						
							|  |  |  | namespace Layout { | 
					
						
							| 
									
										
										
										
											2019-01-04 15:09:48 +04:00
										 |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NeverFreedPointer<DocumentItems> documentItemsMap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | void ItemBase::setPosition(int32 position) { | 
					
						
							|  |  |  | 	_position = position; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int32 ItemBase::position() const { | 
					
						
							|  |  |  | 	return _position; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Result *ItemBase::getResult() const { | 
					
						
							|  |  |  | 	return _result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DocumentData *ItemBase::getDocument() const { | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | 	return _document; | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PhotoData *ItemBase::getPhoto() const { | 
					
						
							|  |  |  | 	return _photo; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 19:32:05 +04:00
										 |  |  | DocumentData *ItemBase::getPreviewDocument() const { | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | 	if (_document) { | 
					
						
							|  |  |  | 		return _document; | 
					
						
							| 
									
										
										
										
											2020-04-10 17:18:51 +04:00
										 |  |  | 	} else if (_result) { | 
					
						
							|  |  |  | 		return _result->_document; | 
					
						
							| 
									
										
										
										
											2016-04-06 19:32:05 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | PhotoData *ItemBase::getPreviewPhoto() const { | 
					
						
							|  |  |  | 	if (_photo) { | 
					
						
							|  |  |  | 		return _photo; | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | 	} else if (_result) { | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 		return _result->_photo; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | void ItemBase::preload() const { | 
					
						
							| 
									
										
										
										
											2018-07-14 00:25:47 +03:00
										 |  |  | 	const auto origin = fileOrigin(); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	if (_result) { | 
					
						
							| 
									
										
										
										
											2020-05-26 14:13:32 +04:00
										 |  |  | 		if (const auto photo = _result->_photo) { | 
					
						
							|  |  |  | 			if (photo->hasExact(Data::PhotoSize::Thumbnail)) { | 
					
						
							|  |  |  | 				photo->load(Data::PhotoSize::Thumbnail, origin); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else if (const auto document = _result->_document) { | 
					
						
							|  |  |  | 			document->loadThumbnail(origin); | 
					
						
							| 
									
										
										
										
											2020-05-27 18:31:39 +04:00
										 |  |  | 		} else if (auto &thumb = _result->_thumbnail; !thumb.empty()) { | 
					
						
							| 
									
										
										
										
											2020-05-28 17:51:18 +04:00
										 |  |  | 			thumb.load(_result->_session, origin); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | 	} else if (_document) { | 
					
						
							|  |  |  | 		_document->loadThumbnail(origin); | 
					
						
							| 
									
										
										
										
											2020-05-26 14:13:32 +04:00
										 |  |  | 	} else if (_photo && _photo->hasExact(Data::PhotoSize::Thumbnail)) { | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | 		_photo->load(Data::PhotoSize::Thumbnail, origin); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-01 21:44:54 +04:00
										 |  |  | void ItemBase::update() const { | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	if (_position >= 0) { | 
					
						
							| 
									
										
										
										
											2017-03-27 21:11:51 +03:00
										 |  |  | 		context()->inlineItemRepaint(this); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 21:11:51 +03:00
										 |  |  | void ItemBase::layoutChanged() { | 
					
						
							|  |  |  | 	if (_position >= 0) { | 
					
						
							|  |  |  | 		context()->inlineItemLayoutChanged(this); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | std::unique_ptr<ItemBase> ItemBase::createLayout( | 
					
						
							|  |  |  | 		not_null<Context*> context, | 
					
						
							|  |  |  | 		not_null<Result*> result, | 
					
						
							|  |  |  | 		bool forceThumb) { | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	using Type = Result::Type; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	switch (result->_type) { | 
					
						
							| 
									
										
										
										
											2018-06-28 15:15:47 +01:00
										 |  |  | 	case Type::Photo: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Photo>(context, result); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	case Type::Audio: | 
					
						
							| 
									
										
										
										
											2018-06-28 15:15:47 +01:00
										 |  |  | 	case Type::File: | 
					
						
							|  |  |  | 		return std::make_unique<internal::File>(context, result); | 
					
						
							|  |  |  | 	case Type::Video: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Video>(context, result); | 
					
						
							|  |  |  | 	case Type::Sticker: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Sticker>(context, result); | 
					
						
							|  |  |  | 	case Type::Gif: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Gif>(context, result); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	case Type::Article: | 
					
						
							| 
									
										
										
										
											2016-04-11 11:43:40 +04:00
										 |  |  | 	case Type::Geo: | 
					
						
							| 
									
										
										
										
											2018-06-28 15:15:47 +01:00
										 |  |  | 	case Type::Venue: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Article>( | 
					
						
							|  |  |  | 			context, | 
					
						
							|  |  |  | 			result, | 
					
						
							|  |  |  | 			forceThumb); | 
					
						
							|  |  |  | 	case Type::Game: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Game>(context, result); | 
					
						
							|  |  |  | 	case Type::Contact: | 
					
						
							|  |  |  | 		return std::make_unique<internal::Contact>(context, result); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-13 19:14:00 +03:00
										 |  |  | 	return nullptr; | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-25 18:16:04 +04:00
										 |  |  | std::unique_ptr<ItemBase> ItemBase::createLayoutGif( | 
					
						
							|  |  |  | 		not_null<Context*> context, | 
					
						
							|  |  |  | 		not_null<DocumentData*> document) { | 
					
						
							| 
									
										
										
										
											2017-03-27 21:11:51 +03:00
										 |  |  | 	return std::make_unique<internal::Gif>(context, document, true); | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | DocumentData *ItemBase::getResultDocument() const { | 
					
						
							|  |  |  | 	return _result ? _result->_document : nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PhotoData *ItemBase::getResultPhoto() const { | 
					
						
							|  |  |  | 	return _result ? _result->_photo : nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-27 18:31:39 +04:00
										 |  |  | bool ItemBase::hasResultThumb() const { | 
					
						
							|  |  |  | 	return _result | 
					
						
							|  |  |  | 		&& (!_result->_thumbnail.empty() | 
					
						
							|  |  |  | 			|| !_result->_locationThumbnail.empty()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Image *ItemBase::getResultThumb(Data::FileOrigin origin) const { | 
					
						
							|  |  |  | 	if (_result && !_thumbnail) { | 
					
						
							|  |  |  | 		if (!_result->_thumbnail.empty()) { | 
					
						
							|  |  |  | 			_thumbnail = _result->_thumbnail.createView(); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:51:18 +04:00
										 |  |  | 			_result->_thumbnail.load(_result->_session, origin); | 
					
						
							| 
									
										
										
										
											2020-05-27 18:31:39 +04:00
										 |  |  | 		} else if (!_result->_locationThumbnail.empty()) { | 
					
						
							|  |  |  | 			_thumbnail = _result->_locationThumbnail.createView(); | 
					
						
							| 
									
										
										
										
											2020-05-28 17:51:18 +04:00
										 |  |  | 			_result->_locationThumbnail.load(_result->_session, origin); | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-27 18:31:39 +04:00
										 |  |  | 	return _thumbnail->image(); | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QPixmap ItemBase::getResultContactAvatar(int width, int height) const { | 
					
						
							|  |  |  | 	if (_result->_type == Result::Type::Contact) { | 
					
						
							| 
									
										
										
										
											2017-12-05 12:43:18 +04:00
										 |  |  | 		auto result = Ui::EmptyUserpic( | 
					
						
							|  |  |  | 			Data::PeerUserpicColor(qHash(_result->_id)), | 
					
						
							| 
									
										
										
										
											2017-12-01 14:21:40 +04:00
										 |  |  | 			_result->getLayoutTitle() | 
					
						
							|  |  |  | 		).generate(width); | 
					
						
							| 
									
										
										
										
											2016-12-29 13:03:51 +04:00
										 |  |  | 		if (result.height() != height * cIntRetinaFactor()) { | 
					
						
							|  |  |  | 			result = result.scaled(QSize(width, height) * cIntRetinaFactor(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-21 17:37:53 +03:00
										 |  |  | 		return result; | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return QPixmap(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ItemBase::getResultDuration() const { | 
					
						
							| 
									
										
										
										
											2018-03-04 23:04:13 +03:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString ItemBase::getResultUrl() const { | 
					
						
							|  |  |  | 	return _result->_url; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ClickHandlerPtr ItemBase::getResultUrlHandler() const { | 
					
						
							|  |  |  | 	if (!_result->_url.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2017-12-18 13:07:18 +04:00
										 |  |  | 		return std::make_shared<UrlClickHandler>(_result->_url); | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ClickHandlerPtr(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-07 12:19:04 +03:00
										 |  |  | ClickHandlerPtr ItemBase::getResultPreviewHandler() const { | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	if (!_result->_content_url.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2019-07-04 11:23:39 +02:00
										 |  |  | 		return std::make_shared<UrlClickHandler>( | 
					
						
							|  |  |  | 			_result->_content_url, | 
					
						
							|  |  |  | 			false); | 
					
						
							| 
									
										
										
										
											2020-04-17 18:02:10 +04:00
										 |  |  | 	} else if (const auto document = _result->_document | 
					
						
							|  |  |  | 		&& _result->_document->createMediaView()->canBePlayed()) { | 
					
						
							| 
									
										
										
										
											2019-10-07 12:19:04 +03:00
										 |  |  | 		return std::make_shared<DocumentOpenClickHandler>( | 
					
						
							|  |  |  | 			_result->_document); | 
					
						
							|  |  |  | 	} else if (_result->_photo) { | 
					
						
							|  |  |  | 		return std::make_shared<PhotoOpenClickHandler>(_result->_photo); | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ClickHandlerPtr(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString ItemBase::getResultThumbLetter() const { | 
					
						
							| 
									
										
										
										
											2016-08-29 23:24:16 -06:00
										 |  |  | #ifndef OS_MAC_OLD
 | 
					
						
							|  |  |  | 	auto parts = _result->_url.splitRef('/'); | 
					
						
							|  |  |  | #else // OS_MAC_OLD
 | 
					
						
							|  |  |  | 	auto parts = _result->_url.split('/'); | 
					
						
							|  |  |  | #endif // OS_MAC_OLD
 | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 	if (!parts.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2016-08-29 23:24:16 -06:00
										 |  |  | 		auto domain = parts.at(0); | 
					
						
							| 
									
										
										
										
											2016-04-06 00:24:27 +04:00
										 |  |  | 		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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-04 15:09:48 +04:00
										 |  |  | Data::FileOrigin ItemBase::fileOrigin() const { | 
					
						
							|  |  |  | 	return _context->inlineItemFileOrigin(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  | const DocumentItems *documentItems() { | 
					
						
							|  |  |  | 	return documentItemsMap.data(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-17 19:21:01 +03:00
										 |  |  | void regDocumentItem( | 
					
						
							|  |  |  | 		not_null<const DocumentData*> document, | 
					
						
							|  |  |  | 		not_null<ItemBase*> item) { | 
					
						
							| 
									
										
										
										
											2016-10-12 22:34:25 +03:00
										 |  |  | 	documentItemsMap.createIfNull(); | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 	(*documentItemsMap)[document].insert(item); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-17 19:21:01 +03:00
										 |  |  | void unregDocumentItem( | 
					
						
							|  |  |  | 		not_null<const DocumentData*> document, | 
					
						
							|  |  |  | 		not_null<ItemBase*> item) { | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 	if (documentItemsMap) { | 
					
						
							|  |  |  | 		auto i = documentItemsMap->find(document); | 
					
						
							|  |  |  | 		if (i != documentItemsMap->cend()) { | 
					
						
							| 
									
										
										
										
											2018-01-17 19:21:01 +03:00
										 |  |  | 			if (i->second.remove(item) && i->second.empty()) { | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 				documentItemsMap->erase(i); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-01-17 19:21:01 +03:00
										 |  |  | 		if (documentItemsMap->empty()) { | 
					
						
							|  |  |  | 			documentItemsMap.clear(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-04-10 22:18:26 +04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace internal
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 01:09:46 +04:00
										 |  |  | } // namespace Layout
 | 
					
						
							|  |  |  | } // namespace InlineBots
 |