diff --git a/Telegram/SourceFiles/data/data_community.cpp b/Telegram/SourceFiles/data/data_community.cpp index 47cd822ca5..61d5d8ab73 100644 --- a/Telegram/SourceFiles/data/data_community.cpp +++ b/Telegram/SourceFiles/data/data_community.cpp @@ -132,6 +132,13 @@ void CommunityInfo::applyLinkedPeers(const QVector &list) { } _linkedPeers = std::move(now); + _hiddenPeers.clear(); + for (const auto &linked : _linkedPeers) { + if (linked.visible.has_value() && !*linked.visible) { + _hiddenPeers.emplace(linked.peer); + } + } + const auto communityId = peerToChannel(_channel->id); for (const auto &linked : _linkedPeers) { if (const auto channel = linked.peer->asChannel()) { @@ -163,6 +170,10 @@ rpl::producer<> CommunityInfo::linkedPeersValue() const { ) | rpl::then(_linkedPeersChanges.events()); } +bool CommunityInfo::isHidden(not_null peer) const { + return _hiddenPeers.contains(peer); +} + bool CommunityInfo::collapsedInDialogs() const { return _channel->flags() & ChannelDataFlag::CommunityCollapsed; } diff --git a/Telegram/SourceFiles/data/data_community.h b/Telegram/SourceFiles/data/data_community.h index 96b0c9e23d..dca961adf2 100644 --- a/Telegram/SourceFiles/data/data_community.h +++ b/Telegram/SourceFiles/data/data_community.h @@ -39,6 +39,7 @@ public: return _linkedPeers; } [[nodiscard]] rpl::producer<> linkedPeersValue() const; + [[nodiscard]] bool isHidden(not_null peer) const; [[nodiscard]] bool collapsedInDialogs() const; void collapsedChanged(); @@ -78,6 +79,7 @@ private: const not_null _channel; std::vector _linkedPeers; + base::flat_set> _hiddenPeers; rpl::event_stream<> _linkedPeersChanges; base::flat_set> _histories; diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index aa1664b4ab..1304955418 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -159,6 +159,13 @@ dialogsCommunityBadgeSkip: point(-3px, -3px); dialogsCommunityBadgeStroke: 2px; dialogsCommunityBadgeLine: 1px; +dialogsCommunityHiddenBadgeSize: 16px; +dialogsCommunityHiddenBadgeSkip: point(-3px, -3px); +dialogsCommunityHiddenBadgeStroke: 2px; +dialogsCommunityHiddenBadgeLine: 1px; +dialogsCommunityHiddenBadgePupil: 1px; +dialogsCommunityHiddenBadgeFg: menuIconFg; + 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_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 39e56f9369..fcde54456e 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1002,6 +1002,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) { .topicJumpCache = _topicJumpCache.get(), .folder = _openedFolder, .forum = _openedForum, + .community = _openedCommunity, .currentBg = currentBg(), .filter = _filterId, .now = ms, diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 09e4320a51..3da8ae1ed4 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/ui/dialogs_video_userpic.h" #include "dialogs/ui/dialogs_layout.h" #include "data/data_channel.h" +#include "data/data_community.h" #include "data/data_folder.h" #include "data/data_forum.h" #include "data/data_session.h" @@ -359,13 +360,16 @@ void Row::updateCornerBadgeShown( not_null peer, Fn updateCallback, bool hasUnreadBadgesAbove, - bool insideCommunity) const { + bool insideCommunity, + bool hidden) const { const auto user = peer->asUser(); const auto now = user ? base::unixtime::now() : TimeId(); const auto channel = user ? nullptr : peer->asChannel(); const auto nextLayer = [&] { if (hasUnreadBadgesAbove) { return kNoneLayer; + } else if (hidden) { + return kTopLayer; } else if (user && Data::IsUserOnline(user, now)) { return kTopLayer; } else if (channel @@ -400,7 +404,8 @@ void Row::PaintCornerBadgeFrame( Ui::PeerUserpicView &view, const Ui::PaintContext &context, bool subscribed, - bool communityMember) { + bool communityMember, + bool hidden) { data->frame.fill(Qt::transparent); Painter q(&data->frame); @@ -490,6 +495,61 @@ void Row::PaintCornerBadgeFrame( return; } + if (hidden) { + if (!hq) { + hq.emplace(q); + } + q.setCompositionMode(QPainter::CompositionMode_Source); + const auto size = st::dialogsCommunityHiddenBadgeSize; + const auto &skip = st::dialogsCommunityHiddenBadgeSkip; + const auto rect = QRectF( + photoSize - skip.x() - size, + photoSize - skip.y() - size, + size, + size); + auto pen = QPen(Qt::transparent); + pen.setWidthF(st::dialogsCommunityHiddenBadgeStroke); + q.setPen(pen); + q.setBrush(st::dialogsCommunityHiddenBadgeFg); + q.drawEllipse(rect); + q.setCompositionMode(QPainter::CompositionMode_SourceOver); + + const auto center = rect.center(); + const auto eyeWidth = size / 3.; + const auto eyeHeight = size / 5.; + auto glyph = QPen(st::windowBg->c); + glyph.setWidthF(st::dialogsCommunityHiddenBadgeLine); + glyph.setCapStyle(Qt::RoundCap); + glyph.setJoinStyle(Qt::RoundJoin); + q.setPen(glyph); + q.setBrush(Qt::NoBrush); + auto eye = QPainterPath(); + eye.moveTo(center.x() - eyeWidth, center.y()); + eye.quadTo( + center.x(), + center.y() - eyeHeight * 2., + center.x() + eyeWidth, + center.y()); + eye.quadTo( + center.x(), + center.y() + eyeHeight * 2., + center.x() - eyeWidth, + center.y()); + q.drawPath(eye); + + q.setPen(Qt::NoPen); + q.setBrush(st::windowBg->c); + const auto pupil = st::dialogsCommunityHiddenBadgePupil; + q.drawEllipse(center, pupil, pupil); + + q.setPen(glyph); + q.setBrush(Qt::NoBrush); + q.drawLine( + QPointF(center.x() - eyeWidth, center.y() + eyeWidth), + QPointF(center.x() + eyeWidth, center.y() - eyeWidth)); + return; + } + if (communityMember) { if (!hq) { hq.emplace(q); @@ -594,12 +654,16 @@ void Row::paintUserpic( _communityUserpicEffect = nullptr; } const auto insideCommunity = context.insideCommunity; + const auto hidden = context.community + && peer + && context.community->isHidden(peer); if (peer) { updateCornerBadgeShown( peer, nullptr, hasUnreadBadgesAbove, - insideCommunity); + insideCommunity, + hidden); } const auto cornerBadgeShown = !_cornerBadgeUserpic @@ -687,6 +751,7 @@ void Row::paintUserpic( || _cornerBadgeUserpic->storiesCount != storiesCount || _cornerBadgeUserpic->storiesUnreadCount != storiesUnreadCount || _cornerBadgeUserpic->storiesHasVideoStream != storiesHasVideoStream + || _cornerBadgeUserpic->hidden != hidden || videoUserpic) { _cornerBadgeUserpic->key = key; _cornerBadgeUserpic->paletteVersion = paletteVersion; @@ -695,6 +760,7 @@ void Row::paintUserpic( _cornerBadgeUserpic->storiesUnreadCount = storiesUnreadCount; _cornerBadgeUserpic->storiesHasVideoStream = storiesHasVideoStream; _cornerBadgeUserpic->frameIndex = frameIndex; + _cornerBadgeUserpic->hidden = hidden; _cornerBadgeUserpic->layersManager.markFrameShown(); PaintCornerBadgeFrame( _cornerBadgeUserpic.get(), @@ -705,7 +771,8 @@ void Row::paintUserpic( userpicView(), context, subscribed, - communityMember); + communityMember, + hidden); } p.drawImage( context.st->padding.left() - framePadding, @@ -715,7 +782,8 @@ void Row::paintUserpic( if (!history || history->peer->isUser() || subscribed - || communityMember) { + || communityMember + || hidden) { return; } const auto actionPainter = history->sendActionPainter(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index 9e0f07329b..c86435d9f6 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -106,7 +106,8 @@ public: not_null peer, Fn updateCallback = nullptr, bool hasUnreadBadgesAbove = false, - bool insideCommunity = false) const; + bool insideCommunity = false, + bool hidden = false) const; void paintUserpic( Painter &p, not_null entry, @@ -189,6 +190,7 @@ private: uint32 storiesUnreadCount : 7 = 0; uint32 storiesHasVideoStream : 1 = 0; uint32 active : 1 = 0; + uint32 hidden : 1 = 0; }; void setCornerBadgeShown( @@ -204,7 +206,8 @@ private: Ui::PeerUserpicView &view, const Ui::PaintContext &context, bool subscribed, - bool communityMember); + bool communityMember, + bool hidden); Key _id; mutable std::unique_ptr _cornerBadgeUserpic; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h index 661224dadd..6c500a457c 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h @@ -23,6 +23,7 @@ namespace Data { class Forum; class Folder; class Thread; +class CommunityInfo; } // namespace Data namespace Dialogs { @@ -61,6 +62,7 @@ struct PaintContext { TopicJumpCache *topicJumpCache = nullptr; Data::Folder *folder = nullptr; Data::Forum *forum = nullptr; + Data::CommunityInfo *community = nullptr; required currentBg; FilterId filter = 0; float64 topicsExpanded = 0.;