From 4b23f93fcf42f4651732068d50a3470a9dc33caa Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 12 Jun 2026 09:59:21 +0400 Subject: [PATCH] Try showing communities in the chat list. --- Telegram/SourceFiles/data/data_channel.cpp | 19 ++++++ Telegram/SourceFiles/dialogs/dialogs.style | 4 ++ Telegram/SourceFiles/dialogs/dialogs_row.cpp | 58 +++++++++++++++++-- Telegram/SourceFiles/dialogs/dialogs_row.h | 3 +- Telegram/SourceFiles/history/history.cpp | 11 ++++ .../window/window_session_controller.cpp | 8 +++ 6 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 5d64f5a374..656f38e0f2 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -264,6 +264,19 @@ void ChannelData::setFlags(ChannelDataFlags which) { } } } + if (diff & Flag::CommunityCollapsed) { + const auto communityId = peerToChannel(id); + const auto refresh = [&](not_null peer) { + const auto channel = peer->asChannel(); + if (channel && channel->linkedCommunityId() == communityId) { + if (const auto history = owner().historyLoaded(channel)) { + history->updateChatListExistence(); + } + } + }; + owner().enumerateGroups(refresh); + owner().enumerateBroadcasts(refresh); + } if (const auto raw = takenForum.get()) { owner().forumIcons().clearUserpicsReset(raw); } @@ -368,7 +381,13 @@ bool ChannelData::monoforumDisabled() const { } void ChannelData::setLinkedCommunityId(ChannelId id) { + if (_linkedCommunityId == id) { + return; + } _linkedCommunityId = id; + if (const auto history = owner().historyLoaded(this)) { + history->updateChatListExistence(); + } } ChannelId ChannelData::linkedCommunityId() const { diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 64d66da238..b40d34b582 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -154,6 +154,10 @@ dialogsCallBadgeSkip: point(-3px, -3px); dialogsSubscriptionBadgeSize: 16px; dialogsSubscriptionBadgeSkip: point(-4px, -4px); +dialogsCommunityBadgeSize: 16px; +dialogsCommunityBadgeSkip: point(-3px, -3px); +dialogsCommunityBadgeStroke: 2px; + dialogsTTLBadgeSize: 20px; dialogsTTLBadgeInnerMargins: margins(2px, 2px, 2px, 2px); // Relative to a photo place, not a whole userpic place. diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 3b01b6e83f..8270b392e7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/dialogs_entry.h" #include "dialogs/ui/dialogs_video_userpic.h" #include "dialogs/ui/dialogs_layout.h" +#include "data/data_channel.h" #include "data/data_folder.h" #include "data/data_forum.h" #include "data/data_session.h" @@ -368,7 +369,8 @@ void Row::updateCornerBadgeShown( return kTopLayer; } else if (channel && (Data::ChannelHasActiveCall(channel) - || Data::ChannelHasSubscriptionUntilDate(channel))) { + || Data::ChannelHasSubscriptionUntilDate(channel) + || channel->linkedCommunityId())) { return kTopLayer; } else if (peer->messagesTTL()) { return kBottomLayer; @@ -396,7 +398,8 @@ void Row::PaintCornerBadgeFrame( Ui::VideoUserpic *videoUserpic, Ui::PeerUserpicView &view, const Ui::PaintContext &context, - bool subscribed) { + bool subscribed, + bool communityMember) { data->frame.fill(Qt::transparent); Painter q(&data->frame); @@ -486,6 +489,47 @@ void Row::PaintCornerBadgeFrame( return; } + if (communityMember) { + if (!hq) { + hq.emplace(q); + } + q.setCompositionMode(QPainter::CompositionMode_Source); + const auto size = st::dialogsCommunityBadgeSize; + const auto &skip = st::dialogsCommunityBadgeSkip; + const auto rect = QRectF( + photoSize - skip.x() - size, + photoSize - skip.y() - size, + size, + size); + auto pen = QPen(Qt::transparent); + pen.setWidthF(st::dialogsCommunityBadgeStroke); + q.setPen(pen); + q.setBrush(data->active + ? st::dialogsVerifiedIconBgActive + : st::dialogsVerifiedIconBg); + q.drawEllipse(rect); + q.setCompositionMode(QPainter::CompositionMode_SourceOver); + + const auto center = rect.center(); + const auto radius = size / 5.; + auto arrow = QPen(data->active + ? st::dialogsVerifiedIconFgActive + : st::dialogsVerifiedIconFg); + arrow.setWidthF(st::dialogsCommunityBadgeStroke / 2.); + arrow.setCapStyle(Qt::RoundCap); + arrow.setJoinStyle(Qt::RoundJoin); + q.setPen(arrow); + q.setBrush(Qt::NoBrush); + auto path = QPainterPath(); + path.moveTo(center.x() - radius, center.y() + radius); + path.lineTo(center.x() + radius, center.y() - radius); + path.moveTo(center.x() - radius * 0.4, center.y() - radius); + path.lineTo(center.x() + radius, center.y() - radius); + path.lineTo(center.x() + radius, center.y() + radius * 0.4); + q.drawPath(path); + return; + } + const auto &manager = data->layersManager; if (const auto p = manager.progressForLayer(kBottomLayer); p > 0.) { const auto size = photoSize; @@ -612,8 +656,13 @@ void Row::paintUserpic( if (keyChanged) { _cornerBadgeUserpic->cacheTTL = QImage(); } + const auto badgeChannel = peer ? peer->asChannel() : nullptr; const auto subscribed = Data::ChannelHasSubscriptionUntilDate( - peer ? peer->asChannel() : nullptr); + badgeChannel); + const auto communityMember = badgeChannel + && badgeChannel->linkedCommunityId() + && !Data::ChannelHasActiveCall(badgeChannel) + && !subscribed; if (keyChanged || !_cornerBadgeUserpic->layersManager.isFinished() || _cornerBadgeUserpic->active != active @@ -638,7 +687,8 @@ void Row::paintUserpic( videoUserpic, userpicView(), context, - subscribed); + subscribed, + communityMember); } p.drawImage( context.st->padding.left() - framePadding, diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index 7e2f9a6708..04ee0f0ddf 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -202,7 +202,8 @@ private: Ui::VideoUserpic *videoUserpic, Ui::PeerUserpicView &view, const Ui::PaintContext &context, - bool subscribed); + bool subscribed, + bool communityMember); Key _id; mutable std::unique_ptr _cornerBadgeUserpic; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 0c6ef93d2b..8735f49322 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -3268,6 +3268,17 @@ bool History::shouldBeInChatList() const { } else if (isPinnedDialog(FilterId())) { return true; } else if (const auto channel = peer->asChannel()) { + if (channel->isCommunity()) { + return !(channel->flags() & ChannelDataFlag::Forbidden) + && !channel->haveLeft(); + } else if (const auto communityId = channel->linkedCommunityId()) { + const auto community = owner().channelLoaded(communityId); + if (community + && (community->flags() + & ChannelDataFlag::CommunityCollapsed)) { + return false; + } + } if (!channel->amIn()) { return isTopPromoted(); } diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index e62d4055eb..160ba43ee0 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -3034,6 +3034,14 @@ void SessionController::showPeerHistory( PeerId peerId, const SectionShow ¶ms, MsgId msgId) { + if (const auto peer = session().data().peerLoaded(peerId)) { + if (const auto channel = peer->asChannel()) { + if (channel->isCommunity()) { + ShowCommunityBox(this, channel); + return; + } + } + } content()->showHistory(peerId, params, msgId); }