diff --git a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp index c86fd057a1..e1b62ff393 100644 --- a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp +++ b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/dynamic_thumbnails.h" #include "data/data_changes.h" +#include "data/data_cloud_file.h" #include "data/data_document.h" #include "data/data_document_media.h" #include "data/data_file_origin.h" @@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/text/text_custom_emoji.h" #include "ui/userpic_view.h" +#include "styles/style_chat.h" #include "styles/style_overview.h" namespace Ui { @@ -244,6 +246,31 @@ private: }; +class GeoThumbnail final : public DynamicImage { +public: + GeoThumbnail( + not_null data, + not_null session, + Data::FileOrigin origin, + bool drawPin); + + std::shared_ptr clone() override; + + QImage image(int size) override; + void subscribeToUpdates(Fn callback) override; + +private: + const not_null _data; + const not_null _session; + const Data::FileOrigin _origin; + const bool _drawPin; + std::shared_ptr _view; + QImage _prepared; + int _paletteVersion = 0; + rpl::lifetime _subscription; + +}; + class DocumentFilePreviewThumbnail final : public DynamicImage { public: DocumentFilePreviewThumbnail( @@ -747,6 +774,97 @@ QImage EmojiThumbnail::image(int size) { return _frame; } +GeoThumbnail::GeoThumbnail( + not_null data, + not_null session, + Data::FileOrigin origin, + bool drawPin) +: _data(data) +, _session(session) +, _origin(origin) +, _drawPin(drawPin) { +} + +std::shared_ptr GeoThumbnail::clone() { + return std::make_shared( + _data, + _session, + _origin, + _drawPin); +} + +QImage GeoThumbnail::image(int size) { + const auto ratio = style::DevicePixelRatio(); + const auto full = QSize(size, size) * ratio; + const auto paletteVersion = style::PaletteVersion(); + if (_prepared.size() == full && _paletteVersion == paletteVersion) { + return _prepared; + } + _paletteVersion = paletteVersion; + + const auto loaded = _view ? *_view : QImage(); + if (loaded.isNull()) { + _prepared = QImage(full, QImage::Format_ARGB32_Premultiplied); + _prepared.fill(Qt::black); + } else { + const auto w = loaded.width(); + const auto h = loaded.height(); + const auto side = std::min(w, h); + const auto x = (w - side) / 2; + const auto y = (h - side) / 2; + _prepared = loaded.copy(x, y, side, side).scaled( + full, + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + } + _prepared = Images::Round( + std::move(_prepared), + ImageRoundRadius::Small); + _prepared.setDevicePixelRatio(ratio); + if (_drawPin && !loaded.isNull()) { + auto p = Painter(&_prepared); + auto hq = PainterHighQualityEnabler(p); + const auto pinScale = std::min( + 1.0, + size / (st::historyMapPoint.height() * 2.5)); + const auto center = QPointF(size / 2.0, size / 2.0); + p.translate(center); + p.scale(pinScale, pinScale); + p.translate(-center); + const auto paintMarker = [&](const style::icon &icon) { + icon.paint( + p, + (size - icon.width()) / 2, + (size / 2) - icon.height(), + size); + }; + paintMarker(st::historyMapPoint); + paintMarker(st::historyMapPointInner); + } + return _prepared; +} + +void GeoThumbnail::subscribeToUpdates(Fn callback) { + _subscription.destroy(); + if (!callback) { + _view = nullptr; + _prepared = QImage(); + return; + } + _view = _data->createView(); + _data->load(_session, _origin); + if (!_view->isNull()) { + return; + } + _subscription = _session->downloaderTaskFinished( + ) | rpl::filter([=] { + return !_view->isNull(); + }) | rpl::take(1) | rpl::on_next([=] { + _prepared = QImage(); + callback(); + }); +} + DocumentFilePreviewThumbnail::DocumentFilePreviewThumbnail( not_null document, Data::FileOrigin origin) @@ -816,7 +934,7 @@ QImage DocumentFilePreviewThumbnail::prepareGenericImage(int size) { result.setDevicePixelRatio(ratio); auto p = QPainter(&result); - PainterHighQualityEnabler hq(p); + auto hq = PainterHighQualityEnabler(p); p.setPen(Qt::NoPen); p.setBrush(_generic.color); p.drawRoundedRect( @@ -992,4 +1110,26 @@ std::shared_ptr MakeDocumentFilePreviewThumbnail( fullId); } +std::shared_ptr MakeGeoThumbnail( + not_null data, + not_null session, + Data::FileOrigin origin) { + return std::make_shared( + data, + session, + std::move(origin), + false); +} + +std::shared_ptr MakeGeoThumbnailWithPin( + not_null data, + not_null session, + Data::FileOrigin origin) { + return std::make_shared( + data, + session, + std::move(origin), + true); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/dynamic_thumbnails.h b/Telegram/SourceFiles/ui/dynamic_thumbnails.h index ea1ecc00e3..2cad87b189 100644 --- a/Telegram/SourceFiles/ui/dynamic_thumbnails.h +++ b/Telegram/SourceFiles/ui/dynamic_thumbnails.h @@ -11,7 +11,12 @@ class DocumentData; class PeerData; class PhotoData; +namespace Main { +class Session; +} // namespace Main + namespace Data { +class CloudImage; class Story; class Session; struct FileOrigin; @@ -52,5 +57,13 @@ class DynamicImage; [[nodiscard]] std::shared_ptr MakeDocumentFilePreviewThumbnail( not_null document, FullMsgId fullId); +[[nodiscard]] std::shared_ptr MakeGeoThumbnail( + not_null data, + not_null session, + Data::FileOrigin origin); +[[nodiscard]] std::shared_ptr MakeGeoThumbnailWithPin( + not_null data, + not_null session, + Data::FileOrigin origin); } // namespace Ui