Load similar channels correctly.

This commit is contained in:
John Preston 2023-11-22 18:40:10 +04:00
parent 2df6729f2d
commit 4dbe5c0a0f
10 changed files with 84 additions and 19 deletions

View file

@ -587,9 +587,6 @@ void ChatParticipants::requestSelf(not_null<ChannelData*> channel) {
} else {
history->owner().histories().requestDialogEntry(history);
}
if (dateChanged) {
loadSimilarChannels(channel);
}
}
};
_selfParticipantRequests.emplace(channel);
@ -713,9 +710,17 @@ void ChatParticipants::loadSimilarChannels(not_null<ChannelData*> 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();
}

View file

@ -120,6 +120,8 @@ public:
not_null<ChannelData*> channel,
not_null<PeerData*> participant);
void loadSimilarChannels(not_null<ChannelData*> channel);
[[nodiscard]] const std::vector<not_null<ChannelData*>> &similar(
not_null<ChannelData*> channel);
[[nodiscard]] auto similarLoaded() const
@ -131,8 +133,6 @@ private:
mtpRequestId requestId = 0;
};
void loadSimilarChannels(not_null<ChannelData*> channel);
MTP::Sender _api;
using PeerRequests = base::flat_map<PeerData*, mtpRequestId>;

View file

@ -1739,6 +1739,10 @@ void ApiWrap::joinChannel(not_null<ChannelData*> channel) {
}).send();
_channelAmInRequests.emplace(channel, requestId);
using Flag = ChannelDataFlag;
chatParticipants().loadSimilarChannels(channel);
channel->setFlags(channel->flags() | Flag::SimilarExpanded);
}
}

View file

@ -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()) {

View file

@ -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<ChannelDataFlag>;

View file

@ -3190,6 +3190,7 @@ void History::insertMessageToBlocks(not_null<HistoryItem*> 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();

View file

@ -99,6 +99,8 @@ public:
not_null<History*> migrateToOrMe() const;
History *migrateFrom() const;
MsgRange rangeForDifferenceRequest() const;
HistoryItem *joinedMessageInstance() const;
void checkLocalMessages();
void removeJoinedMessage();

View file

@ -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<HistoryServiceSameBackground>()) {
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;
}

View file

@ -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<LambdaClickHandler>(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<LambdaClickHandler>([=](
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() };

View file

@ -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<QImage, 4> _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<Channel> _channels;
mutable ClickHandlerPtr _viewAllLink;
mutable ClickHandlerPtr _toggleLink;
};