From 4dbe5c0a0f462bf6357c7ddc9ba64d4338bf6125 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 22 Nov 2023 18:40:10 +0400 Subject: [PATCH] Load similar channels correctly. --- .../SourceFiles/api/api_chat_participants.cpp | 17 +++++--- .../SourceFiles/api/api_chat_participants.h | 4 +- Telegram/SourceFiles/apiwrap.cpp | 4 ++ Telegram/SourceFiles/data/data_channel.cpp | 7 +++- Telegram/SourceFiles/data/data_channel.h | 1 + Telegram/SourceFiles/history/history.cpp | 5 +++ Telegram/SourceFiles/history/history.h | 2 + .../view/history_view_service_message.cpp | 12 +++++- .../media/history_view_similar_channels.cpp | 41 ++++++++++++++++--- .../media/history_view_similar_channels.h | 10 +++-- 10 files changed, 84 insertions(+), 19 deletions(-) diff --git a/Telegram/SourceFiles/api/api_chat_participants.cpp b/Telegram/SourceFiles/api/api_chat_participants.cpp index 25a6dae37..ff3285aa5 100644 --- a/Telegram/SourceFiles/api/api_chat_participants.cpp +++ b/Telegram/SourceFiles/api/api_chat_participants.cpp @@ -587,9 +587,6 @@ void ChatParticipants::requestSelf(not_null channel) { } else { history->owner().histories().requestDialogEntry(history); } - if (dateChanged) { - loadSimilarChannels(channel); - } } }; _selfParticipantRequests.emplace(channel); @@ -713,9 +710,17 @@ void ChatParticipants::loadSimilarChannels(not_null channel) { _similar[channel].requestId = _api.request( MTPchannels_GetChannelRecommendations(channel->inputChannel) ).done([=](const MTPmessages_Chats &result) { - _similar[channel] = { - .list = ParseSimilar(channel, result), - }; + auto &similar = _similar[channel]; + auto list = ParseSimilar(channel, result); + if (similar.list == list) { + return; + } + similar.list = std::move(list); + if (const auto history = channel->owner().historyLoaded(channel)) { + if (const auto item = history->joinedMessageInstance()) { + history->owner().requestItemResize(item); + } + } _similarLoaded.fire_copy(channel); }).send(); } diff --git a/Telegram/SourceFiles/api/api_chat_participants.h b/Telegram/SourceFiles/api/api_chat_participants.h index 7b7a536bf..6140a5b3d 100644 --- a/Telegram/SourceFiles/api/api_chat_participants.h +++ b/Telegram/SourceFiles/api/api_chat_participants.h @@ -120,6 +120,8 @@ public: not_null channel, not_null participant); + void loadSimilarChannels(not_null channel); + [[nodiscard]] const std::vector> &similar( not_null channel); [[nodiscard]] auto similarLoaded() const @@ -131,8 +133,6 @@ private: mtpRequestId requestId = 0; }; - void loadSimilarChannels(not_null channel); - MTP::Sender _api; using PeerRequests = base::flat_map; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 57a8f2418..ec26f166b 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1739,6 +1739,10 @@ void ApiWrap::joinChannel(not_null channel) { }).send(); _channelAmInRequests.emplace(channel, requestId); + + using Flag = ChannelDataFlag; + chatParticipants().loadSimilarChannels(channel); + channel->setFlags(channel->flags() | Flag::SimilarExpanded); } } diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index eab1be564..06a07844d 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -175,7 +175,7 @@ void ChannelData::setFlags(ChannelDataFlags which) { session().changes().peerUpdated(this, UpdateFlag::Migration); } } - if (diff & (Flag::Forum | Flag::CallNotEmpty)) { + if (diff & (Flag::Forum | Flag::CallNotEmpty | Flag::SimilarExpanded)) { if (const auto history = this->owner().historyLoaded(this)) { if (diff & Flag::CallNotEmpty) { history->updateChatListEntry(); @@ -189,6 +189,11 @@ void ChannelData::setFlags(ChannelDataFlags which) { } } } + if (diff & Flag::SimilarExpanded) { + if (const auto item = history->joinedMessageInstance()) { + history->owner().requestItemResize(item); + } + } } } if (const auto raw = taken.get()) { diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index a52c4d969..0d1faf269 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -64,6 +64,7 @@ enum class ChannelDataFlag { HasUnreadStories = (1 << 28), CanGetStatistics = (1 << 29), ViewAsMessages = (1 << 30), + SimilarExpanded = (1 << 31), }; inline constexpr bool is_flag_type(ChannelDataFlag) { return true; }; using ChannelDataFlags = base::flags; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index c9ede3a95..ed9f07336 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -3190,6 +3190,7 @@ void History::insertMessageToBlocks(not_null item) { const auto lastDate = chatListTimeId(); if (!lastDate || itemDate >= lastDate) { setLastMessage(item); + owner().notifyHistoryChangeDelayed(this); } return; } @@ -3227,6 +3228,10 @@ void History::checkLocalMessages() { } } +HistoryItem *History::joinedMessageInstance() const { + return _joinedMessage; +} + void History::removeJoinedMessage() { if (_joinedMessage) { _joinedMessage->destroy(); diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 2ef89cb46..909549684 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -99,6 +99,8 @@ public: not_null migrateToOrMe() const; History *migrateFrom() const; MsgRange rangeForDifferenceRequest() const; + + HistoryItem *joinedMessageInstance() const; void checkLocalMessages(); void removeJoinedMessage(); diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.cpp b/Telegram/SourceFiles/history/view/history_view_service_message.cpp index 4f6c04cd3..b9b27a168 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_service_message.cpp @@ -639,6 +639,12 @@ TextState Service::textState(QPoint point, StateRequest request) const { } else if (mediaDisplayed) { g.setHeight(g.height() - (st::msgServiceMargin.top() + media->height())); } + const auto mediaLeft = st::msgServiceMargin.left() + + (media ? ((g.width() - media->width()) / 2) : 0); + const auto mediaTop = st::msgServiceMargin.top() + + g.height() + + st::msgServiceMargin.top(); + const auto mediaPoint = point - QPoint(mediaLeft, mediaTop); auto trect = g.marginsAdded(-st::msgServicePadding); if (trect.contains(point)) { auto textRequest = request.forText(); @@ -667,10 +673,12 @@ TextState Service::textState(QPoint point, StateRequest request) const { } } else if (const auto same = item->Get()) { result.link = same->lnk; + } else if (media && data()->showSimilarChannels()) { + result = media->textState(mediaPoint, request); } } - } else if (mediaDisplayed) { - result = media->textState(point - QPoint(st::msgServiceMargin.left() + (g.width() - media->width()) / 2, st::msgServiceMargin.top() + g.height() + st::msgServiceMargin.top()), request); + } else if (mediaDisplayed && point.y() >= mediaTop) { + result = media->textState(mediaPoint, request); } return result; } diff --git a/Telegram/SourceFiles/history/view/media/history_view_similar_channels.cpp b/Telegram/SourceFiles/history/view/media/history_view_similar_channels.cpp index 888f54360..ea5b1771a 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_similar_channels.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_similar_channels.cpp @@ -142,6 +142,9 @@ void SimilarChannels::clickHandlerPressedChanged( } void SimilarChannels::draw(Painter &p, const PaintContext &context) const { + if (!_toggled) { + return; + } const auto large = Ui::BubbleCornerRounding::Large; const auto geometry = QRect(0, 0, width(), height()); Ui::PaintBubble( @@ -334,6 +337,23 @@ void SimilarChannels::validateParticipansBg(const Channel &channel) const { channel.participantsBg = std::move(result); } +ClickHandlerPtr SimilarChannels::ensureToggleLink() const { + if (_toggleLink) { + return _toggleLink; + } + _toggleLink = std::make_shared(crl::guard(this, [=]( + ClickContext context) { + const auto channel = history()->peer->asChannel(); + Assert(channel != nullptr); + using Flag = ChannelDataFlag; + const auto flags = channel->flags(); + channel->setFlags((flags & Flag::SimilarExpanded) + ? (flags & ~Flag::SimilarExpanded) + : (flags | Flag::SimilarExpanded)); + })); + return _toggleLink; +} + void SimilarChannels::ensureCacheReady(QSize size) const { const auto ratio = style::DevicePixelRatio(); if (_roundedCache.size() != size * ratio) { @@ -352,6 +372,10 @@ TextState SimilarChannels::textState( QPoint point, StateRequest request) const { auto result = TextState(); + if (point.y() < 0 && !_empty) { + result.link = ensureToggleLink(); + return result; + } result.horizontalScroll = (_scrollMax > 0); const auto skip = st::chatSimilarTitlePosition; const auto viewWidth = _hasViewAll ? (_viewAllWidth + 2 * skip.x()) : 0; @@ -362,7 +386,7 @@ TextState SimilarChannels::textState( const auto channel = parent()->history()->peer->asChannel(); Assert(channel != nullptr); _viewAllLink = std::make_shared([=]( - ClickContext context) { + ClickContext context) { Assert(channel != nullptr); const auto api = &channel->session().api(); const auto &list = api->chatParticipants().similar(channel); @@ -396,8 +420,12 @@ QSize SimilarChannels::countOptimalSize() { _channels.clear(); const auto api = &channel->session().api(); + api->chatParticipants().loadSimilarChannels(channel); const auto similar = api->chatParticipants().similar(channel); - if (similar.empty()) { + _empty = similar.empty() ? 1 : 0; + using Flag = ChannelDataFlag; + _toggled = (channel->flags() & Flag::SimilarExpanded) ? 1 : 0; + if (_empty || !_toggled) { return {}; } @@ -441,7 +469,7 @@ QSize SimilarChannels::countOptimalSize() { _title = tr::lng_similar_channels_title(tr::now); _titleWidth = st::chatSimilarTitle->width(_title); _viewAll = tr::lng_similar_channels_view_all(tr::now); - _viewAllWidth = st::normalFont->width(_viewAll); + _viewAllWidth = std::max(st::normalFont->width(_viewAll), 0); const auto count = int(_channels.size()); const auto desired = (count ? (x - skip) : x) - st::chatSimilarPadding.left(); @@ -451,7 +479,7 @@ QSize SimilarChannels::countOptimalSize() { const auto titleSkip = st::chatSimilarTitlePosition.x(); const auto min = _titleWidth + 2 * titleSkip; const auto limited = std::max( - std::min(_fullWidth, st::chatSimilarWidthMax), + std::min(int(_fullWidth), st::chatSimilarWidthMax), min); if (limited > _fullWidth) { const auto shift = (limited - _fullWidth) / 2; @@ -463,7 +491,10 @@ QSize SimilarChannels::countOptimalSize() { } QSize SimilarChannels::countCurrentSize(int newWidth) { - _scrollMax = std::max(_fullWidth - newWidth, 0); + if (!_toggled) { + return {}; + } + _scrollMax = std::max(int(_fullWidth) - newWidth, 0); _scrollLeft = std::clamp(_scrollLeft, uint32(), _scrollMax); _hasViewAll = (_scrollMax != 0) ? 1 : 0; return { newWidth, minHeight() }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_similar_channels.h b/Telegram/SourceFiles/history/view/media/history_view_similar_channels.h index 594f86bb2..2b5ce0edb 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_similar_channels.h +++ b/Telegram/SourceFiles/history/view/media/history_view_similar_channels.h @@ -49,7 +49,7 @@ public: return true; } bool isDisplayed() const override { - return !_channels.empty(); + return !_empty && _toggled; } void unloadHeavyPart() override; @@ -74,6 +74,7 @@ private: void ensureCacheReady(QSize size) const; void validateParticipansBg(const Channel &channel) const; + [[nodiscard]] ClickHandlerPtr ensureToggleLink() const; QSize countOptimalSize() override; QSize countCurrentSize(int newWidth) override; @@ -83,8 +84,10 @@ private: mutable std::array _roundedCorners; mutable QPoint _lastPoint; int _titleWidth = 0; - int _viewAllWidth = 0; - int _fullWidth = 0; + uint32 _viewAllWidth : 15 = 0; + uint32 _fullWidth : 15 = 0; + uint32 _empty : 1 = 0; + mutable uint32 _toggled : 1 = 0; uint32 _scrollLeft : 15 = 0; uint32 _scrollMax : 15 = 0; uint32 _hasViewAll : 1 = 0; @@ -92,6 +95,7 @@ private: std::vector _channels; mutable ClickHandlerPtr _viewAllLink; + mutable ClickHandlerPtr _toggleLink; };