From 3ece9b1566b4845e070df1b1fece3f760738e6a7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 18 Jun 2024 14:02:05 +0400 Subject: [PATCH] Update API scheme to layer 183. Paid media. --- Telegram/CMakeLists.txt | 2 - Telegram/SourceFiles/api/api_updates.cpp | 2 +- .../SourceFiles/data/data_media_types.cpp | 116 ++++-- Telegram/SourceFiles/data/data_media_types.h | 25 +- Telegram/SourceFiles/data/data_photo.cpp | 36 ++ Telegram/SourceFiles/data/data_photo.h | 18 +- Telegram/SourceFiles/data/data_session.cpp | 3 +- .../export/data/export_data_types.cpp | 24 ++ .../export/data/export_data_types.h | 13 + .../export/output/export_output_html.cpp | 3 + .../export/output/export_output_json.cpp | 2 + .../history/history_inner_widget.cpp | 2 +- Telegram/SourceFiles/history/history_item.cpp | 15 +- Telegram/SourceFiles/history/history_item.h | 4 +- .../history/history_item_components.cpp | 4 +- .../history/history_item_helpers.cpp | 2 + .../history/view/history_view_list_widget.cpp | 2 +- .../view/history_view_scheduled_section.cpp | 2 +- .../media/history_view_extended_preview.cpp | 366 ------------------ .../media/history_view_extended_preview.h | 87 ----- .../history/view/media/history_view_photo.cpp | 12 +- .../media/view/media_view_overlay_widget.cpp | 6 +- Telegram/SourceFiles/mtproto/scheme/api.tl | 8 +- .../business/settings_shortcut_messages.cpp | 2 +- .../ui/controls/userpic_button.cpp | 4 +- 25 files changed, 227 insertions(+), 533 deletions(-) delete mode 100644 Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp delete mode 100644 Telegram/SourceFiles/history/view/media/history_view_extended_preview.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index fc0f622fc..2b41b09fc 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -727,8 +727,6 @@ PRIVATE history/view/media/history_view_dice.h history/view/media/history_view_document.cpp history/view/media/history_view_document.h - history/view/media/history_view_extended_preview.cpp - history/view/media/history_view_extended_preview.h history/view/media/history_view_file.cpp history/view/media/history_view_file.h history/view/media/history_view_game.cpp diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 0ebf17f33..2d7207bae 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1696,7 +1696,7 @@ void Updates::feedUpdate(const MTPUpdate &update) { const auto peerId = peerFromMTP(d.vpeer()); const auto msgId = d.vmsg_id().v; if (const auto item = session().data().message(peerId, msgId)) { - item->applyEdition(d.vextended_media()); + item->applyEdition(d.vextended_media().v); } } break; diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index 4594b7fa2..e076438d7 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -7,12 +7,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_media_types.h" +#include "base/random.h" #include "history/history.h" #include "history/history_item.h" // CreateMedia. #include "history/history_location_manager.h" #include "history/view/history_view_element.h" #include "history/view/history_view_item_preview.h" -#include "history/view/media/history_view_extended_preview.h" #include "history/view/media/history_view_photo.h" #include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_gif.h" @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/media/history_view_giveaway.h" #include "history/view/media/history_view_invoice.h" #include "history/view/media/history_view_media_generic.h" +#include "history/view/media/history_view_media_grouped.h" #include "history/view/media/history_view_call.h" #include "history/view/media/history_view_web_page.h" #include "history/view/media/history_view_poll.h" @@ -261,48 +262,80 @@ template } bool UpdateExtendedMedia( - Invoice &invoice, + std::unique_ptr &media, not_null item, - const MTPMessageExtendedMedia &media) { - return media.match([&](const MTPDmessageExtendedMediaPreview &data) { - if (invoice.extendedMedia) { - return false; + const MTPMessageExtendedMedia &extended) { + return extended.match([&](const MTPDmessageExtendedMediaPreview &data) { + auto photo = (PhotoData*)nullptr; + if (!media) { + const auto id = base::RandomValue(); + photo = item->history()->owner().photo(id); + } else { + photo = media->photo(); + if (!photo || !photo->extendedMediaPreview()) { + return false; + } } + auto changed = false; - auto &preview = invoice.extendedPreview; + auto size = QSize(); + auto thumbnail = QByteArray(); + auto videoDuration = TimeId(); if (const auto &w = data.vw()) { const auto &h = data.vh(); Assert(h.has_value()); - const auto dimensions = QSize(w->v, h->v); - if (preview.dimensions != dimensions) { - preview.dimensions = dimensions; + size = QSize(w->v, h->v); + if (!changed && photo->size(PhotoSize::Large) != size) { changed = true; } } if (const auto &thumb = data.vthumb()) { if (thumb->type() == mtpc_photoStrippedSize) { - const auto bytes = thumb->c_photoStrippedSize().vbytes().v; - if (preview.inlineThumbnailBytes != bytes) { - preview.inlineThumbnailBytes = bytes; + thumbnail = thumb->c_photoStrippedSize().vbytes().v; + if (!changed && photo->inlineThumbnailBytes() != thumbnail) { changed = true; } } } if (const auto &duration = data.vvideo_duration()) { - if (preview.videoDuration != duration->v) { - preview.videoDuration = duration->v; + videoDuration = duration->v; + if (photo->extendedMediaVideoDuration() != videoDuration) { changed = true; } } + if (changed) { + photo->setExtendedMediaPreview(size, thumbnail, videoDuration); + } + if (!media) { + media = std::make_unique(item, photo, true); + } return changed; }, [&](const MTPDmessageExtendedMedia &data) { - invoice.extendedMedia = HistoryItem::CreateMedia( - item, - data.vmedia()); + media = HistoryItem::CreateMedia(item, data.vmedia()); return true; }); } +bool UpdateExtendedMedia( + Invoice &invoice, + not_null item, + const QVector &media) { + auto changed = false; + const auto count = int(media.size()); + for (auto i = 0; i != count; ++i) { + if (i < invoice.extendedMedia.size()) { + invoice.extendedMedia.emplace_back(); + changed = true; + } + UpdateExtendedMedia(invoice.extendedMedia[i], item, media[i]); + } + if (count < invoice.extendedMedia.size()) { + invoice.extendedMedia.resize(count); + changed = true; + } + return changed; +} + TextForMimeData WithCaptionClipboardText( const QString &attachType, TextForMimeData &&caption) { @@ -344,11 +377,22 @@ Invoice ComputeInvoiceData( .isTest = data.is_test(), }; if (const auto &media = data.vextended_media()) { - UpdateExtendedMedia(result, item, *media); + UpdateExtendedMedia(result, item, { *media }); } return result; } +Invoice ComputeInvoiceData( + not_null item, + const MTPDmessageMediaPaidMedia &data) { + auto result = Invoice{ + .amount = data.vstars_amount().v, + .currency = Ui::kCreditsCurrency, + }; + UpdateExtendedMedia(result, item, data.vextended_media().v); + return result; +} + Call ComputeCallData(const MTPDmessageActionPhoneCall &call) { auto result = Call(); result.finishReason = [&] { @@ -424,6 +468,18 @@ GiveawayResults ComputeGiveawayResultsData( return result; } +bool HasExtendedMedia(const Invoice &invoice) { + return !invoice.extendedMedia.empty(); +} + +bool HasUnpaidMedia(const Invoice &invoice) { + for (const auto &media : invoice.extendedMedia) { + const auto photo = media->photo(); + return photo && photo->extendedMediaPreview(); + } + return false; +} + Media::Media(not_null parent) : _parent(parent) { } @@ -1851,14 +1907,14 @@ MediaInvoice::MediaInvoice( .currency = data.currency, .title = data.title, .description = data.description, - .extendedPreview = data.extendedPreview, - .extendedMedia = (data.extendedMedia - ? data.extendedMedia->clone(parent) - : nullptr), .photo = data.photo, .isTest = data.isTest, } { - if (_invoice.extendedPreview && !_invoice.extendedMedia) { + _invoice.extendedMedia.reserve(data.extendedMedia.size()); + for (auto &item : data.extendedMedia) { + _invoice.extendedMedia.push_back(item->clone(parent)); + } + if (HasUnpaidMedia(_invoice)) { Ui::PreloadImageSpoiler(); } } @@ -1917,7 +1973,7 @@ bool MediaInvoice::updateSentMedia(const MTPMessageMedia &media) { bool MediaInvoice::updateExtendedMedia( not_null item, - const MTPMessageExtendedMedia &media) { + const QVector &media) { Expects(item == parent()); return UpdateExtendedMedia(_invoice, item, media); @@ -1927,15 +1983,15 @@ std::unique_ptr MediaInvoice::createView( not_null message, not_null realParent, HistoryView::Element *replacing) { - if (_invoice.extendedMedia) { - return _invoice.extendedMedia->createView( + if (_invoice.extendedMedia.size() == 1) { + return _invoice.extendedMedia.front()->createView( message, realParent, replacing); - } else if (_invoice.extendedPreview) { - return std::make_unique( + } else if (!_invoice.extendedMedia.empty()) { + return std::make_unique( message, - &_invoice); + _invoice.extendedMedia); } return std::make_unique(message, &_invoice); } diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 08d1320b9..3e26877d4 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -84,19 +84,6 @@ struct Call { }; -struct ExtendedPreview { - QByteArray inlineThumbnailBytes; - QSize dimensions; - TimeId videoDuration = -1; - - [[nodiscard]] bool empty() const { - return dimensions.isEmpty(); - } - explicit operator bool() const { - return !empty(); - } -}; - class Media; struct Invoice { @@ -105,11 +92,12 @@ struct Invoice { QString currency; QString title; TextWithEntities description; - ExtendedPreview extendedPreview; - std::unique_ptr extendedMedia; + std::vector> extendedMedia; PhotoData *photo = nullptr; bool isTest = false; }; +[[nodiscard]] bool HasExtendedMedia(const Invoice &invoice); +[[nodiscard]] bool HasUnpaidMedia(const Invoice &invoice); struct GiveawayStart { std::vector> channels; @@ -207,7 +195,7 @@ public: virtual bool updateSentMedia(const MTPMessageMedia &media) = 0; virtual bool updateExtendedMedia( not_null item, - const MTPMessageExtendedMedia &media) { + const QVector &media) { return false; } virtual std::unique_ptr createView( @@ -524,7 +512,7 @@ public: bool updateSentMedia(const MTPMessageMedia &media) override; bool updateExtendedMedia( not_null item, - const MTPMessageExtendedMedia &media) override; + const QVector &media) override; std::unique_ptr createView( not_null message, not_null realParent, @@ -750,6 +738,9 @@ private: [[nodiscard]] Invoice ComputeInvoiceData( not_null item, const MTPDmessageMediaInvoice &data); +[[nodiscard]] Invoice ComputeInvoiceData( + not_null item, + const MTPDmessageMediaPaidMedia &data); [[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call); diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp index 2530ccc75..35186750b 100644 --- a/Telegram/SourceFiles/data/data_photo.cpp +++ b/Telegram/SourceFiles/data/data_photo.cpp @@ -50,6 +50,38 @@ PhotoData::~PhotoData() { base::take(_videoSizes); } +void PhotoData::setFields(TimeId date, bool hasAttachedStickers) { + _dateOrExtendedVideoDuration = date; + _hasStickers = hasAttachedStickers; + _extendedMediaPreview = false; +} + +void PhotoData::setExtendedMediaPreview( + QSize dimensions, + const QByteArray &inlineThumbnailBytes, + TimeId videoDuration) { + _extendedMediaPreview = true; + updateImages( + inlineThumbnailBytes, + {}, + {}, + { .location = { {}, dimensions.width(), dimensions.height() } }, + {}, + {}, + {}); + _dateOrExtendedVideoDuration = videoDuration + 1; +} + +bool PhotoData::extendedMediaPreview() const { + return _extendedMediaPreview; +} + +std::optional PhotoData::extendedMediaVideoDuration() const { + return (_extendedMediaPreview && _dateOrExtendedVideoDuration) + ? TimeId(_dateOrExtendedVideoDuration - 1) + : std::optional(); +} + Data::Session &PhotoData::owner() const { return *_owner; } @@ -74,6 +106,10 @@ void PhotoData::load( load(PhotoSize::Large, origin, fromCloud, autoLoading); } +TimeId PhotoData::date() const { + return _extendedMediaPreview ? 0 : _dateOrExtendedVideoDuration; +} + bool PhotoData::loading() const { return loading(PhotoSize::Large); } diff --git a/Telegram/SourceFiles/data/data_photo.h b/Telegram/SourceFiles/data/data_photo.h index 33d990723..98166d265 100644 --- a/Telegram/SourceFiles/data/data_photo.h +++ b/Telegram/SourceFiles/data/data_photo.h @@ -53,6 +53,7 @@ public: void automaticLoadSettingsChanged(); + [[nodiscard]] TimeId date() const; [[nodiscard]] bool loading() const; [[nodiscard]] bool displayLoading() const; void cancel(); @@ -89,6 +90,14 @@ public: [[nodiscard]] auto activeMediaView() const -> std::shared_ptr; + void setFields(TimeId date, bool hasAttachedStickers); + void setExtendedMediaPreview( + QSize dimensions, + const QByteArray &inlineThumbnailBytes, + TimeId videoDuration); + [[nodiscard]] bool extendedMediaPreview() const; + [[nodiscard]] std::optional extendedMediaVideoDuration() const; + void updateImages( const QByteArray &inlineThumbnailBytes, const ImageWithLocation &small, @@ -148,11 +157,10 @@ public: void setHasAttachedStickers(bool value); // For now they return size of the 'large' image. - int width() const; - int height() const; + [[nodiscard]] int width() const; + [[nodiscard]] int height() const; PhotoId id = 0; - TimeId date = 0; PeerData *peer = nullptr; // for chat and channel photos connection // geo, caption @@ -164,6 +172,8 @@ private: [[nodiscard]] const Data::CloudFile &videoFile( Data::PhotoSize size) const; + TimeId _dateOrExtendedVideoDuration = 0; + struct VideoSizes { Data::CloudFile small; Data::CloudFile large; @@ -177,6 +187,8 @@ private: int32 _dc = 0; uint64 _access = 0; bool _hasStickers = false; + bool _extendedMediaPreview = false; + QByteArray _fileReference; std::unique_ptr _replyPreview; std::weak_ptr _media; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index b22126ebb..869476243 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -3077,8 +3077,7 @@ void Session::photoApplyFields( return; } photo->setRemoteLocation(dc, access, fileReference); - photo->date = date; - photo->setHasAttachedStickers(hasStickers); + photo->setFields(date, hasStickers); photo->updateImages( inlineThumbnailBytes, small, diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 71750a575..16dbfb994 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -666,6 +666,28 @@ Invoice ParseInvoice(const MTPDmessageMediaInvoice &data) { return result; } +PaidMedia ParsePaidMedia( + ParseMediaContext &context, + const MTPDmessageMediaPaidMedia &data, + const QString &folder, + TimeId date) { + auto result = PaidMedia(); + result.stars = data.vstars_amount().v; + result.extended.reserve(data.vextended_media().v.size()); + for (const auto &extended : data.vextended_media().v) { + result.extended.push_back(extended.match([]( + const MTPDmessageExtendedMediaPreview &) + -> std::unique_ptr { + return std::unique_ptr(); + }, [&](const MTPDmessageExtendedMedia &data) + -> std::unique_ptr { + return std::make_unique( + ParseMedia(context, data.vmedia(), folder, date)); + })); + } + return result; +} + Poll ParsePoll(const MTPDmessageMediaPoll &data) { auto result = Poll(); data.vpoll().match([&](const MTPDpoll &poll) { @@ -1225,6 +1247,8 @@ Media ParseMedia( result.content = ParseGiveaway(data); }, [&](const MTPDmessageMediaGiveawayResults &data) { // #TODO export giveaway + }, [&](const MTPDmessageMediaPaidMedia &data) { + result.content = ParsePaidMedia(context, data, folder, date); }, [](const MTPDmessageMediaEmpty &data) {}); return result; } diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 76585991c..cc16c47ba 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -182,6 +182,18 @@ struct Invoice { int32 receiptMsgId = 0; }; +struct Media; +struct PaidMedia { + PaidMedia() = default; + PaidMedia(PaidMedia &&) = default; + PaidMedia &operator=(PaidMedia &&) = default; + PaidMedia(const PaidMedia &) = delete; + PaidMedia &operator=(const PaidMedia &) = delete; + + uint64 stars = 0; + std::vector> extended; +}; + struct Poll { struct Answer { Utf8String text; @@ -337,6 +349,7 @@ struct Media { Invoice, Poll, GiveawayStart, + PaidMedia, UnsupportedMedia> content; TimeId ttl = 0; diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index 9df6bcbb3..f49776ede 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -2092,6 +2092,9 @@ MediaData HtmlWriter::Wrap::prepareMediaData( result.status = Data::FormatMoneyAmount(data.amount, data.currency); }, [](const Poll &data) { }, [](const GiveawayStart &data) { + }, [&](const PaidMedia &data) { + result.classes = "media_invoice"; + result.status = Data::FormatMoneyAmount(data.stars, "XTR"); }, [](const UnsupportedMedia &data) { Unexpected("Unsupported message."); }, [](v::null_t) {}); diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index b485e615b..adbad2b7f 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -779,6 +779,8 @@ QByteArray SerializeMessage( { "until_date", SerializeDate(data.untilDate) }, { "channels", serialized }, })); + }, [&](const PaidMedia &data) { + push("paid_stars_amount", data.stars); }, [](const UnsupportedMedia &data) { Unexpected("Unsupported message."); }, [](v::null_t) {}); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 46d1a4612..69268f05e 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1031,7 +1031,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { } } session().data().reactions().poll(item, context.now); - if (item->hasExtendedMediaPreview()) { + if (item->hasUnpaidContent()) { session().api().views().pollExtendedMedia(item); } _reactionsManager->recordCurrentReactionEffect( diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 73e0662c0..da40ecec5 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -349,6 +349,10 @@ std::unique_ptr HistoryItem::CreateMedia( return std::make_unique( item, Data::ComputeGiveawayResultsData(item, media)); + }, [&](const MTPDmessageMediaPaidMedia &media) -> Result { + return std::make_unique( + item, + Data::ComputeInvoiceData(item, media)); }, [](const MTPDmessageMediaEmpty &) -> Result { return nullptr; }, [](const MTPDmessageMediaUnsupported &) -> Result { @@ -1813,7 +1817,8 @@ void HistoryItem::applyEdition(const MTPDmessageService &message) { } } -void HistoryItem::applyEdition(const MTPMessageExtendedMedia &media) { +void HistoryItem::applyEdition( + const QVector &media) { if (const auto existing = this->media()) { if (existing->updateExtendedMedia(this, media)) { checkBuyButton(); @@ -2241,7 +2246,7 @@ bool HistoryItem::forbidsSaving() const { if (forbidsForward()) { return true; } else if (const auto invoice = _media ? _media->invoice() : nullptr) { - return (invoice->extendedMedia != nullptr); + return HasExtendedMedia(*invoice); } return false; } @@ -2991,10 +2996,10 @@ bool HistoryItem::externalReply() const { return false; } -bool HistoryItem::hasExtendedMediaPreview() const { +bool HistoryItem::hasUnpaidContent() const { if (const auto media = _media.get()) { if (const auto invoice = media->invoice()) { - return (invoice->extendedPreview && !invoice->extendedMedia); + return HasUnpaidMedia(*invoice); } } return false; @@ -3778,7 +3783,7 @@ void HistoryItem::createComponents(const MTPDmessage &data) { void HistoryItem::refreshMedia(const MTPMessageMedia *media) { const auto was = (_media != nullptr); if (const auto invoice = was ? _media->invoice() : nullptr) { - if (invoice->extendedMedia) { + if (HasExtendedMedia(*invoice)) { return; } } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 3118bf3bc..bb23aa3fd 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -326,7 +326,7 @@ public: [[nodiscard]] int repliesCount() const; [[nodiscard]] bool repliesAreComments() const; [[nodiscard]] bool externalReply() const; - [[nodiscard]] bool hasExtendedMediaPreview() const; + [[nodiscard]] bool hasUnpaidContent() const; [[nodiscard]] bool inHighlightProcess() const; void highlightProcessDone(); @@ -345,7 +345,7 @@ public: void applyChanges(not_null story); void applyEdition(const MTPDmessageService &message); - void applyEdition(const MTPMessageExtendedMedia &media); + void applyEdition(const QVector &media); void updateForwardedInfo(const MTPMessageFwdHeader *fwd); void updateSentContent( const TextWithEntities &textWithEntities, diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index fd4ff1605..55e9e09a5 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -1091,8 +1091,8 @@ void HistoryMessageReplyMarkup::updateData( bool HistoryMessageReplyMarkup::hiddenBy(Data::Media *media) const { if (media && (data.flags & ReplyMarkupFlag::OnlyBuyButton)) { if (const auto invoice = media->invoice()) { - if (invoice->extendedPreview - && (!invoice->extendedMedia || !invoice->receiptMsgId)) { + if (HasUnpaidMedia(*invoice) + || (HasExtendedMedia(*invoice) && !invoice->receiptMsgId)) { return true; } } diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index d3d9569e6..9a6423bcc 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -557,6 +557,8 @@ MediaCheckResult CheckMessageMedia(const MTPMessageMedia &media) { return Result::Good; }, [](const MTPDmessageMediaGiveawayResults &) { return Result::Good; + }, [](const MTPDmessageMediaPaidMedia &) { + return Result::Good; }, [](const MTPDmessageMediaUnsupported &) { return Result::Unsupported; }); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index eb5e079ad..2c99c6343 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -2263,7 +2263,7 @@ void ListWidget::paintEvent(QPaintEvent *e) { } } session->data().reactions().poll(item, context.now); - if (item->hasExtendedMediaPreview()) { + if (item->hasUnpaidContent()) { session->api().views().pollExtendedMedia(item); } if (_reactionsManager) { diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 045b5b830..07ce6a82d 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -1399,7 +1399,7 @@ CopyRestrictionType ScheduledWidget::listCopyMediaRestrictionType( not_null item) { if (const auto media = item->media()) { if (const auto invoice = media->invoice()) { - if (invoice->extendedMedia) { + if (HasExtendedMedia(*invoice)) { return CopyMediaRestrictionTypeFor(_history->peer, item); } } diff --git a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp deleted file mode 100644 index 9c1a73a64..000000000 --- a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "history/view/media/history_view_extended_preview.h" - -#include "history/history_item.h" -#include "history/history.h" -#include "history/history_item_components.h" -#include "history/view/history_view_element.h" -#include "history/view/history_view_cursor_state.h" -#include "history/view/media/history_view_media_common.h" -#include "media/streaming/media_streaming_utility.h" -#include "ui/effects/spoiler_mess.h" -#include "ui/image/image.h" -#include "ui/image/image_prepare.h" -#include "ui/chat/chat_style.h" -#include "ui/painter.h" -#include "ui/power_saving.h" -#include "data/data_session.h" -#include "payments/payments_checkout_process.h" -#include "payments/payments_non_panel_process.h" -#include "window/window_session_controller.h" -#include "mainwindow.h" -#include "core/click_handler_types.h" -#include "styles/style_chat.h" - -namespace HistoryView { -namespace { - -[[nodiscard]] ClickHandlerPtr MakeInvoiceLink(not_null item) { - return std::make_shared([=](ClickContext context) { - const auto my = context.other.value(); - const auto controller = my.sessionWindow.get(); - Payments::CheckoutProcess::Start( - item, - Payments::Mode::Payment, - (controller - ? crl::guard( - controller, - [=](auto) { controller->widget()->activate(); }) - : Fn()), - (controller - ? Payments::ProcessNonPanelPaymentFormFactory( - controller, - item) - : nullptr)); - }); -} - -} // namespace - -ExtendedPreview::ExtendedPreview( - not_null parent, - not_null invoice) -: Media(parent) -, _invoice(invoice) { - const auto item = parent->data(); - _spoiler.link = MakeInvoiceLink(item); - resolveButtonText(); -} - -void ExtendedPreview::resolveButtonText() { - if (const auto markup = _parent->data()->inlineReplyMarkup()) { - for (const auto &row : markup->data.rows) { - for (const auto &button : row) { - if (button.type == HistoryMessageMarkupButton::Type::Buy) { - _buttonText.setText( - st::semiboldTextStyle, - TextUtilities::SingleLine(button.text)); - return; - } - } - } - } -} - -ExtendedPreview::~ExtendedPreview() { - if (hasHeavyPart()) { - unloadHeavyPart(); - _parent->checkHeavyPart(); - } -} - -void ExtendedPreview::ensureThumbnailRead() const { - if (!_inlineThumbnail.isNull() || _imageCacheInvalid) { - return; - } - const auto &bytes = _invoice->extendedPreview.inlineThumbnailBytes; - if (bytes.isEmpty()) { - return; - } - _inlineThumbnail = Images::FromInlineBytes(bytes); - if (_inlineThumbnail.isNull()) { - _imageCacheInvalid = true; - } else { - history()->owner().registerHeavyViewPart(_parent); - } -} - -bool ExtendedPreview::hasHeavyPart() const { - return _spoiler.animation || !_inlineThumbnail.isNull(); -} - -void ExtendedPreview::unloadHeavyPart() { - _inlineThumbnail - = _spoiler.background - = _spoiler.cornerCache - = _buttonBackground = QImage(); - _spoiler.animation = nullptr; -} - -bool ExtendedPreview::enforceBubbleWidth() const { - return true; -} - -QSize ExtendedPreview::countOptimalSize() { - const auto &preview = _invoice->extendedPreview; - const auto dimensions = preview.dimensions; - const auto minWidth = std::min( - std::max({ - _parent->minWidthForMedia(), - (_parent->hasBubble() - ? st::historyPhotoBubbleMinWidth - : st::minPhotoSize), - minWidthForButton(), - }), - st::maxMediaSize); - const auto scaled = CountDesiredMediaSize(dimensions); - auto maxWidth = qMax(scaled.width(), minWidth); - auto minHeight = qMax(scaled.height(), st::minPhotoSize); - if (preview.videoDuration < 0) { - accumulate_max(maxWidth, scaled.height()); - } - return { maxWidth, minHeight }; -} - -QSize ExtendedPreview::countCurrentSize(int newWidth) { - const auto &preview = _invoice->extendedPreview; - const auto dimensions = preview.dimensions; - const auto thumbMaxWidth = std::min(newWidth, st::maxMediaSize); - const auto minWidth = std::min( - std::max({ - _parent->minWidthForMedia(), - (_parent->hasBubble() - ? st::historyPhotoBubbleMinWidth - : st::minPhotoSize), - minWidthForButton(), - }), - thumbMaxWidth); - const auto scaled = (preview.videoDuration >= 0) - ? CountMediaSize( - CountDesiredMediaSize(dimensions), - newWidth) - : CountPhotoMediaSize( - CountDesiredMediaSize(dimensions), - newWidth, - maxWidth()); - newWidth = qMax(scaled.width(), minWidth); - auto newHeight = qMax(scaled.height(), st::minPhotoSize); - if (_parent->hasBubble()) { - const auto maxWithCaption = qMin( - st::msgMaxWidth, - _parent->textualMaxWidth()); - newWidth = qMin(qMax(newWidth, maxWithCaption), thumbMaxWidth); - } - if (newWidth >= maxWidth()) { - newHeight = qMin(newHeight, minHeight()); - } - return { newWidth, newHeight }; -} - -int ExtendedPreview::minWidthForButton() const { - return (st::msgBotKbButton.margin + st::msgBotKbButton.padding) * 2 - + _buttonText.maxWidth(); -} - -void ExtendedPreview::draw(Painter &p, const PaintContext &context) const { - if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return; - - auto paintx = 0, painty = 0, paintw = width(), painth = height(); - auto bubble = _parent->hasBubble(); - auto rthumb = style::rtlrect(paintx, painty, paintw, painth, width()); - const auto inWebPage = (_parent->media() != this); - const auto rounding = inWebPage - ? std::optional() - : adjustedBubbleRounding(); - if (!bubble) { - Assert(rounding.has_value()); - fillImageShadow(p, rthumb, *rounding, context); - } - validateImageCache(rthumb.size(), rounding); - p.drawImage(rthumb.topLeft(), _spoiler.background); - fillImageSpoiler(p, &_spoiler, rthumb, context); - paintButton(p, rthumb, context); - if (context.selected()) { - fillImageOverlay(p, rthumb, rounding, context); - } - - // date - if (!inWebPage) { - auto fullRight = paintx + paintw; - auto fullBottom = painty + painth; - if (needInfoDisplay()) { - _parent->drawInfo( - p, - context, - fullRight, - fullBottom, - 2 * paintx + paintw, - InfoDisplayType::Image); - } - if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { - auto fastShareLeft = _parent->hasRightLayout() - ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); - auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); - _parent->drawRightAction(p, context, fastShareLeft, fastShareTop, 2 * paintx + paintw); - } - } -} - -void ExtendedPreview::validateImageCache( - QSize outer, - std::optional rounding) const { - const auto ratio = style::DevicePixelRatio(); - if (_spoiler.background.size() == (outer * ratio) - && _spoiler.backgroundRounding == rounding) { - return; - } - _spoiler.background = Images::Round( - prepareImageCache(outer), - MediaRoundingMask(rounding)); - _spoiler.backgroundRounding = rounding; -} - -QImage ExtendedPreview::prepareImageCache(QSize outer) const { - ensureThumbnailRead(); - return PrepareWithBlurredBackground(outer, {}, {}, _inlineThumbnail); -} - -void ExtendedPreview::paintButton( - Painter &p, - QRect outer, - const PaintContext &context) const { - const auto st = context.st; - const auto &padding = st::extendedPreviewButtonPadding; - const auto margin = st::extendedPreviewButtonMargin; - const auto width = std::min( - _buttonText.maxWidth() + padding.left() + padding.right(), - outer.width() - 2 * margin); - const auto height = padding.top() - + st::semiboldFont->height - + padding.bottom(); - const auto overlay = st->msgDateImgBg()->c; - const auto ratio = style::DevicePixelRatio(); - const auto size = QSize(width, height); - if (_buttonBackground.size() != size * ratio - || _buttonBackgroundOverlay != overlay) { - auto &background = _spoiler.background; - if (background.width() < width * ratio - || background.height() < height * ratio) { - return; - } - _buttonBackground = background.copy(QRect( - (background.width() - width * ratio) / 2, - (background.height() - height * ratio) / 2, - width * ratio, - height * ratio)); - _buttonBackground.setDevicePixelRatio(ratio); - auto p = QPainter(&_buttonBackground); - p.fillRect(0, 0, width, height, overlay); - p.end(); - _buttonBackground = Images::Round( - std::move(_buttonBackground), - Images::CornersMask(height / 2)); - } - const auto left = outer.x() + (outer.width() - width) / 2; - const auto top = outer.y() + (outer.height() - height) / 2; - p.drawImage(left, top, _buttonBackground); - p.setPen(st->msgDateImgFg()->c); - _buttonText.drawLeftElided( - p, - left + padding.left(), - top + padding.top(), - width - padding.left() - padding.right(), - outer.width()); -} - -TextState ExtendedPreview::textState(QPoint point, StateRequest request) const { - auto result = TextState(_parent); - - if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) { - return result; - } - auto paintx = 0, painty = 0, paintw = width(), painth = height(); - auto bubble = _parent->hasBubble(); - if (QRect(paintx, painty, paintw, painth).contains(point)) { - result.link = _spoiler.link; - } - if (!bubble && _parent->media() == this) { - auto fullRight = paintx + paintw; - auto fullBottom = painty + painth; - const auto bottomInfoResult = _parent->bottomInfoTextState( - fullRight, - fullBottom, - point, - InfoDisplayType::Image); - if (bottomInfoResult.link - || bottomInfoResult.cursor != CursorState::None - || bottomInfoResult.customTooltip) { - return bottomInfoResult; - } - if (const auto size = bubble ? std::nullopt : _parent->rightActionSize()) { - auto fastShareLeft = _parent->hasRightLayout() - ? (paintx - size->width() - st::historyFastShareLeft) - : (fullRight + st::historyFastShareLeft); - auto fastShareTop = (fullBottom - st::historyFastShareBottom - size->height()); - if (QRect(fastShareLeft, fastShareTop, size->width(), size->height()).contains(point)) { - result.link = _parent->rightActionLink(point - - QPoint(fastShareLeft, fastShareTop)); - } - } - } - return result; -} - -bool ExtendedPreview::toggleSelectionByHandlerClick(const ClickHandlerPtr &p) const { - return p == _spoiler.link; -} - -bool ExtendedPreview::dragItemByHandler(const ClickHandlerPtr &p) const { - return p == _spoiler.link; -} - -bool ExtendedPreview::needInfoDisplay() const { - return _parent->data()->isSending() - || _parent->data()->hasFailed() - || _parent->isUnderCursor() - || (_parent->delegate()->elementContext() == Context::ChatPreview) - || _parent->isLastAndSelfMessage(); -} - -bool ExtendedPreview::needsBubble() const { - const auto item = _parent->data(); - return !item->isService() - && (item->repliesAreComments() - || item->externalReply() - || item->viaBot() - || !item->emptyText() - || _parent->displayReply() - || _parent->displayForwardedFrom() - || _parent->displayFromName() - || _parent->displayedTopicButton()); -} - -QPoint ExtendedPreview::resolveCustomInfoRightBottom() const { - const auto skipx = (st::msgDateImgDelta + st::msgDateImgPadding.x()); - const auto skipy = (st::msgDateImgDelta + st::msgDateImgPadding.y()); - return QPoint(width() - skipx, height() - skipy); -} - -} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h b/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h deleted file mode 100644 index da2cd5d14..000000000 --- a/Telegram/SourceFiles/history/view/media/history_view_extended_preview.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "history/view/media/history_view_media.h" -#include "history/view/media/history_view_media_spoiler.h" - -enum class ImageRoundRadius; - -namespace Ui { -class SpoilerAnimation; -} // namespace Ui - -namespace Data { -struct Invoice; -} // namespace Data - -namespace HistoryView { - -class Element; - -class ExtendedPreview final : public Media { -public: - ExtendedPreview( - not_null parent, - not_null invoice); - ~ExtendedPreview(); - - bool hideMessageText() const override { - return false; - } - - void draw(Painter &p, const PaintContext &context) const override; - TextState textState(QPoint point, StateRequest request) const override; - - [[nodiscard]] bool toggleSelectionByHandlerClick( - const ClickHandlerPtr &p) const override; - [[nodiscard]] bool dragItemByHandler( - const ClickHandlerPtr &p) const override; - - bool needsBubble() const override; - bool customInfoLayout() const override { - return true; - } - QPoint resolveCustomInfoRightBottom() const override; - bool skipBubbleTail() const override { - return isRoundedInBubbleBottom(); - } - - bool hasHeavyPart() const override; - void unloadHeavyPart() override; - bool enforceBubbleWidth() const override; - -private: - int minWidthForButton() const; - void resolveButtonText(); - void ensureThumbnailRead() const; - - QSize countOptimalSize() override; - QSize countCurrentSize(int newWidth) override; - - bool needInfoDisplay() const; - void validateImageCache( - QSize outer, - std::optional rounding) const; - [[nodiscard]] QImage prepareImageCache(QSize outer) const; - void paintButton( - Painter &p, - QRect outer, - const PaintContext &context) const; - - const not_null _invoice; - mutable MediaSpoiler _spoiler; - mutable QImage _inlineThumbnail; - mutable QImage _buttonBackground; - mutable QColor _buttonBackgroundOverlay; - mutable Ui::Text::String _buttonText; - mutable bool _imageCacheInvalid = false; - -}; - -} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index 2205625d8..01a41bdaa 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -219,10 +219,14 @@ QSize Photo::countCurrentSize(int newWidth) { : st::minPhotoSize), thumbMaxWidth); const auto dimensions = photoSize(); - auto pix = CountPhotoMediaSize( - CountDesiredMediaSize(dimensions), - newWidth, - maxWidth()); + auto pix = _data->extendedMediaVideoDuration() + ? CountMediaSize( + CountDesiredMediaSize(dimensions), + newWidth) + : CountPhotoMediaSize( + CountDesiredMediaSize(dimensions), + newWidth, + maxWidth()); newWidth = qMax(pix.width(), minWidth); auto newHeight = qMax(pix.height(), st::minPhotoSize); if (_parent->hasBubble()) { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 2d2da578f..33f08c5a1 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -1362,7 +1362,7 @@ void OverlayWidget::updateControls() { if (_message) { return ItemDateTime(_message); } else if (_photo) { - return base::unixtime::parse(_photo->date); + return base::unixtime::parse(_photo->date()); } else if (_document) { return base::unixtime::parse(_document->date); } @@ -2436,7 +2436,7 @@ void OverlayWidget::saveAs() { u".mp4"_q, QString(), false, - _photo->date), + _photo->date()), crl::guard(_window, [=](const QString &result) { QFile f(result); if (!result.isEmpty() @@ -2467,7 +2467,7 @@ void OverlayWidget::saveAs() { u".jpg"_q, QString(), false, - _photo->date), + _photo->date()), crl::guard(_window, [=](const QString &result) { if (!result.isEmpty() && _photo == photo) { media->saveToFile(result); diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 5d35cc578..9aa1c847d 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -44,6 +44,7 @@ inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector s inputMediaDice#e66fbf7b emoticon:string = InputMedia; inputMediaStory#89fdd778 peer:InputPeer id:int = InputMedia; inputMediaWebPage#c21b8849 flags:# force_large_media:flags.0?true force_small_media:flags.1?true optional:flags.2?true url:string = InputMedia; +inputMediaPaidMedia#aa661fc3 stars_amount:long extended_media:Vector = InputMedia; inputChatPhotoEmpty#1ca48f57 = InputChatPhoto; inputChatUploadedPhoto#bdcdaec0 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.3?VideoSize = InputChatPhoto; @@ -133,6 +134,7 @@ messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia; messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia; messageMediaGiveaway#daad85b0 flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.2?true channels:Vector countries_iso2:flags.1?Vector prize_description:flags.3?string quantity:int months:int until_date:int = MessageMedia; messageMediaGiveawayResults#c6991068 flags:# only_new_subscribers:flags.0?true refunded:flags.2?true channel_id:long additional_peers_count:flags.3?int launch_msg_id:int winners_count:int unclaimed_count:int winners:Vector months:int prize_description:flags.1?string until_date:int = MessageMedia; +messageMediaPaidMedia#a8852491 stars_amount:long extended_media:Vector = MessageMedia; messageActionEmpty#b6aef7b0 = MessageAction; messageActionChatCreate#bd47cbad title:string users:Vector = MessageAction; @@ -384,7 +386,7 @@ updateUserEmojiStatus#28373599 user_id:long emoji_status:EmojiStatus = Update; updateRecentEmojiStatuses#30f443db = Update; updateRecentReactions#6f7863f4 = Update; updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?true stickerset:long = Update; -updateMessageExtendedMedia#5a73a98c peer:Peer msg_id:int extended_media:MessageExtendedMedia = Update; +updateMessageExtendedMedia#d5a41724 peer:Peer msg_id:int extended_media:Vector = Update; updateChannelPinnedTopic#192efbe3 flags:# pinned:flags.0?true channel_id:long topic_id:int = Update; updateChannelPinnedTopics#fe198602 flags:# channel_id:long order:flags.0?Vector = Update; updateUser#20529438 user_id:long = Update; @@ -1806,7 +1808,7 @@ starsTransactionPeer#d80da15d peer:Peer = StarsTransactionPeer; starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption; -starsTransaction#aa00c898 flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string = StarsTransaction; +starsTransaction#2db5418f flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector = StarsTransaction; payments.starsStatus#8cf4ee60 flags:# balance:long history:Vector next_offset:flags.0?string chats:Vector users:Vector = payments.StarsStatus; @@ -2488,4 +2490,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool; fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo; -// LAYER 182 +// LAYER 183 diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index 9724bdec2..5594e6c4c 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -968,7 +968,7 @@ CopyRestrictionType ShortcutMessages::listCopyMediaRestrictionType( not_null item) { if (const auto media = item->media()) { if (const auto invoice = media->invoice()) { - if (invoice->extendedMedia) { + if (!invoice->extendedMedia.empty()) { return CopyMediaRestrictionTypeFor(_history->peer, item); } } diff --git a/Telegram/SourceFiles/ui/controls/userpic_button.cpp b/Telegram/SourceFiles/ui/controls/userpic_button.cpp index 1b86567b3..0b26e1810 100644 --- a/Telegram/SourceFiles/ui/controls/userpic_button.cpp +++ b/Telegram/SourceFiles/ui/controls/userpic_button.cpp @@ -416,7 +416,7 @@ void UserpicButton::openPeerPhoto() { return; } const auto photo = _peer->owner().photo(id); - if (photo->date && _controller) { + if (photo->date() && _controller) { _controller->openPhoto(photo, _peer); } } @@ -744,7 +744,7 @@ void UserpicButton::updateVideo() { return; } const auto photo = _peer->owner().photo(id); - if (!photo->date || !photo->videoCanBePlayed()) { + if (!photo->date() || !photo->videoCanBePlayed()) { clearStreaming(); return; } else if (_streamed && _streamedPhoto == photo) {