diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp index cc1098ae6..ef2504eec 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.cpp @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/event_filter.h" #include "data/data_peer.h" #include "data/data_session.h" +#include "data/data_stories.h" +#include "data/data_story.h" #include "history/history_item.h" #include "info/info_controller.h" #include "info/info_memento.h" @@ -697,26 +699,39 @@ void InnerWidget::fillRecentPosts() { const auto addMessage = [=]( not_null messageWrap, - not_null item, + HistoryItem *maybeItem, + Data::Story *maybeStory, const Data::StatisticsMessageInteractionInfo &info) { const auto button = messageWrap->add( object_ptr( messageWrap, rpl::never(), st::statisticsRecentPostButton)); - auto it = _state.recentPostPreviews.find( - { .messageId = item->fullId() }); + const auto fullRecentId = RecentPostId{ + .messageId = maybeItem ? maybeItem->fullId() : FullMsgId(), + .storyId = maybeStory ? maybeStory->fullId() : FullStoryId(), + }; + auto it = _state.recentPostPreviews.find(fullRecentId); auto cachedPreview = (it != end(_state.recentPostPreviews)) ? base::take(it->second) : QImage(); - const auto raw = Ui::CreateChild( - button, - item, - info.viewsCount, - info.forwardsCount, - std::move(cachedPreview)); + const auto raw = maybeItem + ? Ui::CreateChild( + button, + maybeItem, + info.viewsCount, + info.forwardsCount, + std::move(cachedPreview)) + : Ui::CreateChild( + button, + maybeStory, + info.viewsCount, + info.forwardsCount, + std::move(cachedPreview)); - AddContextMenu(button, _controller, item); + if (maybeItem) { + AddContextMenu(button, _controller, maybeItem); + } _messagePreviews.push_back(raw); raw->show(); @@ -727,8 +742,11 @@ void InnerWidget::fillRecentPosts() { - st::statisticsRecentPostButton.padding); } }, raw->lifetime()); - button->setClickedCallback([=, fullId = item->fullId()] { - _showRequests.fire({ .messageStatistic = fullId }); + button->setClickedCallback([=] { + _showRequests.fire({ + .messageStatistic = fullRecentId.messageId, + .storyStatistic = fullRecentId.storyId, + }); }); Ui::AddSkip(messageWrap); if (!wrap->toggled()) { @@ -765,18 +783,30 @@ void InnerWidget::fillRecentPosts() { const auto &recent = stats.recentMessageInteractions[i]; const auto messageWrap = content->add( object_ptr(content)); - const auto msgId = recent.messageId; - if (const auto item = _peer->owner().message(_peer, msgId)) { - addMessage(messageWrap, item, recent); - continue; - } - const auto callback = crl::guard(content, [=] { - if (const auto item = _peer->owner().message(_peer, msgId)) { - addMessage(messageWrap, item, recent); - content->resizeToWidth(content->width()); + auto &data = _peer->owner(); + if (recent.messageId) { + const auto fullId = FullMsgId(_peer->id, recent.messageId); + if (const auto item = data.message(fullId)) { + addMessage(messageWrap, item, nullptr, recent); + continue; } - }); - _peer->session().api().requestMessageData(_peer, msgId, callback); + const auto callback = crl::guard(content, [=] { + if (const auto item = _peer->owner().message(fullId)) { + addMessage(messageWrap, item, nullptr, recent); + content->resizeToWidth(content->width()); + } + }); + _peer->session().api().requestMessageData( + _peer, + fullId.msg, + callback); + } else if (recent.storyId) { + const auto fullId = FullStoryId{ _peer->id, recent.storyId }; + if (const auto story = data.stories().lookup(fullId)) { + addMessage(messageWrap, nullptr, *story, recent); + continue; + } + } } container->resizeToWidth(container->width()); }; diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.h b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.h index d71091298..ed4e93a9f 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.h +++ b/Telegram/SourceFiles/info/statistics/info_statistics_inner_widget.h @@ -32,6 +32,7 @@ public: PeerId info = PeerId(0); FullMsgId history; FullMsgId messageStatistic; + FullStoryId storyStatistic; }; InnerWidget( diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.cpp index f69861117..b1aada079 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/statistics/info_statistics_recent_message.h" +#include "base/unixtime.h" #include "core/ui_integration.h" #include "data/data_document.h" #include "data/data_document_media.h" @@ -14,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo.h" #include "data/data_photo_media.h" #include "data/data_session.h" +#include "data/data_story.h" #include "history/history.h" #include "history/history_item.h" #include "history/history_item_helpers.h" @@ -21,13 +23,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/statistics/info_statistics_common.h" #include "lang/lang_keys.h" #include "main/main_session.h" +#include "ui/effects/outline_segments.h" // UnreadStoryOutlineGradient #include "ui/effects/ripple_animation.h" #include "ui/effects/spoiler_mess.h" +#include "ui/painter.h" #include "ui/power_saving.h" #include "ui/rect.h" #include "ui/text/format_values.h" #include "ui/text/text_options.h" #include "styles/style_boxes.h" +#include "styles/style_dialogs.h" #include "styles/style_layers.h" #include "styles/style_statistics.h" @@ -73,6 +78,7 @@ MessagePreview::MessagePreview( int shares, QImage cachedPreview) : Ui::RpWidget(parent) +, _messageId(item->fullId()) , _date( st::statisticsHeaderTitleTextStyle, Ui::FormatDateTime(ItemDateTime(item))) @@ -103,26 +109,74 @@ MessagePreview::MessagePreview( .session = &item->history()->session(), .customEmojiRepaint = [=] { update(); }, }); + if (item->media()->hasSpoiler()) { + _spoiler = std::make_unique([=] { update(); }); + } if (_preview.isNull()) { - processPreview(item); + if (const auto media = item->media()) { + if (const auto photo = media->photo()) { + _photoMedia = photo->createMediaView(); + _photoMedia->wanted(Data::PhotoSize::Large, item->fullId()); + } else if (const auto document = media->document()) { + _documentMedia = document->createMediaView(); + _documentMedia->thumbnailWanted(item->fullId()); + } + } + processPreview(); } } -void MessagePreview::processPreview(not_null item) { - if (const auto media = item->media()) { - if (item->media()->hasSpoiler()) { - _spoiler = std::make_unique([=] { - update(); - }); - } - if (const auto photo = media->photo()) { +MessagePreview::MessagePreview( + not_null parent, + not_null story, + int views, + int shares, + QImage cachedPreview) +: Ui::RpWidget(parent) +, _storyId(story->fullId()) +, _date( + st::statisticsHeaderTitleTextStyle, + Ui::FormatDateTime(base::unixtime::parse(story->date()))) +, _views( + st::defaultPeerListItem.nameStyle, + (views >= 0) + ? tr::lng_stats_recent_messages_views( + tr::now, + lt_count_decimal, + views) + : QString()) +, _shares( + st::statisticsHeaderTitleTextStyle, + (shares >= 0) + ? tr::lng_stats_recent_messages_shares( + tr::now, + lt_count_decimal, + shares) + : QString()) +, _viewsWidth(_views.maxWidth()) +, _sharesWidth(_shares.maxWidth()) +, _preview(std::move(cachedPreview)) { + _text.setMarkedText( + st::defaultPeerListItem.nameStyle, + { tr::lng_in_dlg_story(tr::now) }, + Ui::DialogTextOptions(), + Core::MarkedTextContext{ + .session = &story->peer()->session(), + .customEmojiRepaint = [=] { update(); }, + }); + if (_preview.isNull()) { + if (const auto photo = story->photo()) { _photoMedia = photo->createMediaView(); - _photoMedia->wanted(Data::PhotoSize::Large, item->fullId()); - } else if (const auto document = media->document()) { + _photoMedia->wanted(Data::PhotoSize::Large, story->fullId()); + } else if (const auto document = story->document()) { _documentMedia = document->createMediaView(); - _documentMedia->thumbnailWanted(item->fullId()); + _documentMedia->thumbnailWanted(story->fullId()); } + processPreview(); } +} + +void MessagePreview::processPreview() { const auto session = _photoMedia ? &_photoMedia->owner()->session() : _documentMedia @@ -143,9 +197,8 @@ void MessagePreview::processPreview(not_null item) { return { true, _documentMedia->thumbnail() }; } else if (const auto large = _photoMedia->image(Size::Large)) { return { true, large }; - } else if (const auto thumbnail = _photoMedia->image( - Size::Thumbnail)) { - return { false, thumbnail }; + } else if (const auto thumb = _photoMedia->image(Size::Thumbnail)) { + return { false, thumb }; } else if (const auto small = _photoMedia->image(Size::Small)) { return { false, small }; } else { @@ -168,7 +221,7 @@ void MessagePreview::processPreview(not_null item) { } _preview = PreparePreviewImage( computed.image->original(), - ImageRoundRadius::Large, + _messageId ? ImageRoundRadius::Large : ImageRoundRadius::Ellipse, !!_spoiler); }, _lifetimeDownload); } @@ -186,11 +239,11 @@ void MessagePreview::paintEvent(QPaintEvent *e) { ? st::peerListBoxItem.photoPosition.x() : st::peerListBoxItem.namePosition.x(); if (left) { - p.drawImage(st::peerListBoxItem.photoPosition, _preview); + const auto rect = QRect( + st::peerListBoxItem.photoPosition, + Size(st::peerListBoxItem.photoSize)); + p.drawImage(rect.topLeft(), _preview); if (_spoiler) { - const auto rect = QRect( - st::peerListBoxItem.photoPosition, - Size(st::peerListBoxItem.photoSize)); const auto paused = On(PowerSaving::kChatSpoiler); FillSpoilerRect( p, @@ -201,6 +254,17 @@ void MessagePreview::paintEvent(QPaintEvent *e) { _spoiler->index(crl::now(), paused)), _cornerCache); } + if (_storyId) { + auto hq = PainterHighQualityEnabler(p); + const auto line = st::dialogsStoriesFull.lineTwice / 2.; + auto gradient = Ui::UnreadStoryOutlineGradient(); + gradient.setStart(rect.topRight()); + gradient.setFinalStop(rect.bottomLeft()); + + p.setPen(QPen(gradient, line)); + p.setBrush(Qt::NoBrush); + p.drawEllipse(rect + Margins(1.5 * line)); + } } const auto topTextTop = st::peerListBoxItem.namePosition.y(); const auto bottomTextTop = st::peerListBoxItem.statusPosition.y(); @@ -237,7 +301,8 @@ void MessagePreview::paintEvent(QPaintEvent *e) { void MessagePreview::saveState(SavedState &state) const { if (!_lifetimeDownload) { - state.recentPostPreviews[{ .messageId = _messageId }] = _preview; + const auto fullId = RecentPostId{ _messageId, _storyId }; + state.recentPostPreviews[fullId] = _preview; } } diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.h b/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.h index 60ca2d420..217c00041 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.h +++ b/Telegram/SourceFiles/info/statistics/info_statistics_recent_message.h @@ -14,6 +14,7 @@ class HistoryItem; namespace Data { class DocumentMedia; class PhotoMedia; +class Story; } // namespace Data namespace Ui { @@ -32,6 +33,12 @@ public: int views, int shares, QImage cachedPreview); + MessagePreview( + not_null parent, + not_null story, + int views, + int shares, + QImage cachedPreview); void saveState(SavedState &state) const; @@ -41,9 +48,10 @@ protected: int resizeGetHeight(int newWidth) override; private: - void processPreview(not_null item); + void processPreview(); FullMsgId _messageId; + FullStoryId _storyId; Ui::Text::String _text; Ui::Text::String _date; Ui::Text::String _views; diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_widget.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_widget.cpp index 0c9fd1ab3..3544b2ae0 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_widget.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_widget.cpp @@ -73,11 +73,11 @@ Widget::Widget( request.history.msg); } else if (request.info) { controller->showPeerInfo(request.info); - } else if (request.messageStatistic) { + } else if (request.messageStatistic || request.storyStatistic) { controller->showSection(Make( controller->statisticsPeer(), request.messageStatistic, - {})); + request.storyStatistic)); } }, _inner->lifetime()); _inner->scrollToRequests(