diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp index 8b395d9a9e..dd06d2abc9 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.cpp +++ b/Telegram/SourceFiles/api/api_chat_invite.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "window/window_session_controller.h" +#include "info/profile/info_profile_badge.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "ui/empty_userpic.h" @@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/toast/toast.h" #include "boxes/premium_limits_box.h" #include "styles/style_boxes.h" +#include "styles/style_info.h" #include "styles/style_layers.h" namespace Api { @@ -195,6 +197,13 @@ ConfirmInviteBox::ConfirmInviteBox( : _session(session) , _submit(std::move(submit)) , _title(this, st::confirmInviteTitle) +, _badge(std::make_unique( + this, + st::infoPeerBadge, + _session, + rpl::single(Info::Profile::Badge::Content{ BadgeForInvite(invite) }), + nullptr, + [=] { return false; })) , _status(this, st::confirmInviteStatus) , _about(this, st::confirmInviteAbout) , _aboutRequests(this, st::confirmInviteStatus) @@ -275,9 +284,24 @@ ConfirmInviteBox::ChatInvite ConfirmInviteBox::Parse( .isMegagroup = data.is_megagroup(), .isBroadcast = data.is_broadcast(), .isRequestNeeded = data.is_request_needed(), + .isFake = data.is_fake(), + .isScam = data.is_scam(), + .isVerified = data.is_verified(), }; } +[[nodiscard]] Info::Profile::BadgeType ConfirmInviteBox::BadgeForInvite( + const ChatInvite &invite) { + using Type = Info::Profile::BadgeType; + return invite.isVerified + ? Type::Verified + : invite.isScam + ? Type::Scam + : invite.isFake + ? Type::Fake + : Type::None; +} + void ConfirmInviteBox::prepare() { addButton( (_requestApprove @@ -326,8 +350,26 @@ void ConfirmInviteBox::prepare() { void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { BoxContent::resizeEvent(e); - _title->move((width() - _title->width()) / 2, st::confirmInviteTitleTop); - _status->move((width() - _status->width()) / 2, st::confirmInviteStatusTop); + + const auto padding = st::boxRowPadding; + auto nameWidth = width() - padding.left() - padding.right(); + auto badgeWidth = 0; + if (const auto widget = _badge->widget()) { + badgeWidth = st::infoVerifiedCheckPosition.x() + widget->width(); + nameWidth -= badgeWidth; + } + _title->resizeToWidth(std::min(nameWidth, _title->textMaxWidth())); + _title->moveToLeft( + (width() - _title->width() - badgeWidth) / 2, + st::confirmInviteTitleTop); + const auto badgeLeft = _title->x() + _title->width(); + const auto badgeTop = _title->y(); + const auto badgeBottom = _title->y() + _title->height(); + _badge->move(badgeLeft, badgeTop, badgeBottom); + + _status->move( + (width() - _status->width()) / 2, + st::confirmInviteStatusTop); auto bottom = _status->y() + _status->height() + st::boxPadding.bottom() diff --git a/Telegram/SourceFiles/api/api_chat_invite.h b/Telegram/SourceFiles/api/api_chat_invite.h index 1ae6f2529c..c8d99548c9 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.h +++ b/Telegram/SourceFiles/api/api_chat_invite.h @@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class UserData; class ChannelData; +namespace Info::Profile { +class Badge; +enum class BadgeType; +} // namespace Info::Profile + namespace Main { class Session; } // namespace Main @@ -66,10 +71,15 @@ private: bool isMegagroup = false; bool isBroadcast = false; bool isRequestNeeded = false; + bool isFake = false; + bool isScam = false; + bool isVerified = false; }; [[nodiscard]] static ChatInvite Parse( not_null session, const MTPDchatInvite &data); + [[nodiscard]] Info::Profile::BadgeType BadgeForInvite( + const ChatInvite &invite); ConfirmInviteBox( not_null session, @@ -81,12 +91,14 @@ private: Fn _submit; object_ptr _title; + std::unique_ptr _badge; object_ptr _status; object_ptr _about; object_ptr _aboutRequests; std::shared_ptr _photo; std::unique_ptr _photoEmpty; std::vector _participants; + bool _isChannel = false; bool _requestApprove = false; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp index 61a99b336f..73437e1ddd 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp @@ -22,6 +22,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Info::Profile { namespace { +[[nodiscard]] rpl::producer ContentForPeer( + not_null peer) { + return rpl::combine( + BadgeValue(peer), + EmojiStatusIdValue(peer) + ) | rpl::map([=](BadgeType badge, DocumentId emojiStatusId) { + return Badge::Content{ badge, emojiStatusId }; + }); +} + } // namespace Badge::Badge( @@ -32,18 +42,37 @@ Badge::Badge( Fn animationPaused, int customStatusLoopsLimit, base::flags allowed) +: Badge( + parent, + st, + &peer->session(), + ContentForPeer(peer), + emojiStatusPanel, + std::move(animationPaused), + customStatusLoopsLimit, + allowed) { +} + +Badge::Badge( + not_null parent, + const style::InfoPeerBadge &st, + not_null session, + rpl::producer content, + EmojiStatusPanel *emojiStatusPanel, + Fn animationPaused, + int customStatusLoopsLimit, + base::flags allowed) : _parent(parent) , _st(st) -, _peer(peer) +, _session(session) , _emojiStatusPanel(emojiStatusPanel) , _customStatusLoopsLimit(customStatusLoopsLimit) , _allowed(allowed) , _animationPaused(std::move(animationPaused)) { - rpl::combine( - BadgeValue(peer), - EmojiStatusIdValue(peer) - ) | rpl::start_with_next([=](BadgeType badge, DocumentId emojiStatusId) { - setBadge(badge, emojiStatusId); + std::move( + content + ) | rpl::start_with_next([=](Content content) { + setContent(content); }, _lifetime); } @@ -51,37 +80,36 @@ Ui::RpWidget *Badge::widget() const { return _view.data(); } -void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { - if (!(_allowed & badge) - || (!_peer->session().premiumBadgesShown() - && badge == BadgeType::Premium)) { - badge = BadgeType::None; +void Badge::setContent(Content content) { + if (!(_allowed & content.badge) + || (!_session->premiumBadgesShown() + && content.badge == BadgeType::Premium)) { + content.badge = BadgeType::None; } - if (!(_allowed & badge)) { - badge = BadgeType::None; + if (!(_allowed & content.badge)) { + content.badge = BadgeType::None; } - if (badge != BadgeType::Premium) { - emojiStatusId = 0; + if (content.badge != BadgeType::Premium) { + content.emojiStatusId = 0; } - if (_badge == badge && _emojiStatusId == emojiStatusId) { + if (_content == content) { return; } - _badge = badge; - _emojiStatusId = emojiStatusId; + _content = content; _emojiStatus = nullptr; _view.destroy(); - if (_badge == BadgeType::None) { + if (_content.badge == BadgeType::None) { _updated.fire({}); return; } _view.create(_parent); _view->show(); - switch (_badge) { + switch (_content.badge) { case BadgeType::Verified: case BadgeType::Premium: { - if (_emojiStatusId) { - _emojiStatus = _peer->owner().customEmojiManager().create( - _emojiStatusId, + if (const auto id = _content.emojiStatusId) { + _emojiStatus = _session->data().customEmojiManager().create( + id, [raw = _view.data()] { raw->update(); }, sizeTag()); if (_customStatusLoopsLimit > 0) { @@ -107,7 +135,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } }, _view->lifetime()); } else { - const auto icon = (_badge == BadgeType::Verified) + const auto icon = (_content.badge == BadgeType::Verified) ? &_st.verified : &_st.premium; _view->resize(icon->size()); @@ -120,7 +148,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } break; case BadgeType::Scam: case BadgeType::Fake: { - const auto fake = (_badge == BadgeType::Fake); + const auto fake = (_content.badge == BadgeType::Fake); const auto size = Ui::ScamBadgeSize(fake); const auto skip = st::infoVerifiedCheckPosition.x(); _view->resize( @@ -139,7 +167,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { } break; } - if (_badge != BadgeType::Premium || !_premiumClickCallback) { + if (_content.badge != BadgeType::Premium || !_premiumClickCallback) { _view->setAttribute(Qt::WA_TransparentForMouseEvents); } else { _view->setClickedCallback(_premiumClickCallback); @@ -150,7 +178,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { void Badge::setPremiumClickCallback(Fn callback) { _premiumClickCallback = std::move(callback); - if (_view && _badge == BadgeType::Premium) { + if (_view && _content.badge == BadgeType::Premium) { if (!_premiumClickCallback) { _view->setAttribute(Qt::WA_TransparentForMouseEvents); } else { @@ -169,7 +197,8 @@ void Badge::move(int left, int top, int bottom) { return; } const auto star = !_emojiStatus - && (_badge == BadgeType::Premium || _badge == BadgeType::Verified); + && (_content.badge == BadgeType::Premium + || _content.badge == BadgeType::Verified); const auto fake = !_emojiStatus && !star; const auto skip = fake ? 0 : _st.position.x(); const auto badgeLeft = left + skip; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.h b/Telegram/SourceFiles/info/profile/info_profile_badge.h index 9e9d01d75d..daada96d1b 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.h +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.h @@ -18,6 +18,10 @@ namespace Data { enum class CustomEmojiSizeTag : uchar; } // namespace Data +namespace Main { +class Session; +} // namespace Main + namespace Ui { class RpWidget; class AbstractButton; @@ -45,7 +49,25 @@ public: EmojiStatusPanel *emojiStatusPanel, Fn animationPaused, int customStatusLoopsLimit = 0, - base::flags allowed = base::flags::from_raw(-1)); + base::flags allowed + = base::flags::from_raw(-1)); + + struct Content { + BadgeType badge = BadgeType::None; + DocumentId emojiStatusId = 0; + + friend inline constexpr bool operator==(Content, Content) = default; + }; + Badge( + not_null parent, + const style::InfoPeerBadge &st, + not_null session, + rpl::producer content, + EmojiStatusPanel *emojiStatusPanel, + Fn animationPaused, + int customStatusLoopsLimit = 0, + base::flags allowed + = base::flags::from_raw(-1)); [[nodiscard]] Ui::RpWidget *widget() const; @@ -56,17 +78,16 @@ public: [[nodiscard]] Data::CustomEmojiSizeTag sizeTag() const; private: - void setBadge(BadgeType badge, DocumentId emojiStatusId); + void setContent(Content content); const not_null _parent; const style::InfoPeerBadge &_st; - const not_null _peer; + const not_null _session; EmojiStatusPanel *_emojiStatusPanel = nullptr; const int _customStatusLoopsLimit = 0; - DocumentId _emojiStatusId = 0; std::unique_ptr _emojiStatus; base::flags _allowed; - BadgeType _badge = BadgeType(); + Content _content; Fn _premiumClickCallback; Fn _animationPaused; object_ptr _view = { nullptr };