Add verified/fake/scam badge to ConfirmInviteBox.

This commit is contained in:
John Preston 2023-09-01 20:45:44 +04:00
parent dbd4aecc56
commit a6b844408a
4 changed files with 139 additions and 35 deletions

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "info/profile/info_profile_badge.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
@ -25,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "boxes/premium_limits_box.h" #include "boxes/premium_limits_box.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_info.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
namespace Api { namespace Api {
@ -195,6 +197,13 @@ ConfirmInviteBox::ConfirmInviteBox(
: _session(session) : _session(session)
, _submit(std::move(submit)) , _submit(std::move(submit))
, _title(this, st::confirmInviteTitle) , _title(this, st::confirmInviteTitle)
, _badge(std::make_unique<Info::Profile::Badge>(
this,
st::infoPeerBadge,
_session,
rpl::single(Info::Profile::Badge::Content{ BadgeForInvite(invite) }),
nullptr,
[=] { return false; }))
, _status(this, st::confirmInviteStatus) , _status(this, st::confirmInviteStatus)
, _about(this, st::confirmInviteAbout) , _about(this, st::confirmInviteAbout)
, _aboutRequests(this, st::confirmInviteStatus) , _aboutRequests(this, st::confirmInviteStatus)
@ -275,9 +284,24 @@ ConfirmInviteBox::ChatInvite ConfirmInviteBox::Parse(
.isMegagroup = data.is_megagroup(), .isMegagroup = data.is_megagroup(),
.isBroadcast = data.is_broadcast(), .isBroadcast = data.is_broadcast(),
.isRequestNeeded = data.is_request_needed(), .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() { void ConfirmInviteBox::prepare() {
addButton( addButton(
(_requestApprove (_requestApprove
@ -326,8 +350,26 @@ void ConfirmInviteBox::prepare() {
void ConfirmInviteBox::resizeEvent(QResizeEvent *e) { void ConfirmInviteBox::resizeEvent(QResizeEvent *e) {
BoxContent::resizeEvent(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() auto bottom = _status->y()
+ _status->height() + _status->height()
+ st::boxPadding.bottom() + st::boxPadding.bottom()

View file

@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class UserData; class UserData;
class ChannelData; class ChannelData;
namespace Info::Profile {
class Badge;
enum class BadgeType;
} // namespace Info::Profile
namespace Main { namespace Main {
class Session; class Session;
} // namespace Main } // namespace Main
@ -66,10 +71,15 @@ private:
bool isMegagroup = false; bool isMegagroup = false;
bool isBroadcast = false; bool isBroadcast = false;
bool isRequestNeeded = false; bool isRequestNeeded = false;
bool isFake = false;
bool isScam = false;
bool isVerified = false;
}; };
[[nodiscard]] static ChatInvite Parse( [[nodiscard]] static ChatInvite Parse(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPDchatInvite &data); const MTPDchatInvite &data);
[[nodiscard]] Info::Profile::BadgeType BadgeForInvite(
const ChatInvite &invite);
ConfirmInviteBox( ConfirmInviteBox(
not_null<Main::Session*> session, not_null<Main::Session*> session,
@ -81,12 +91,14 @@ private:
Fn<void()> _submit; Fn<void()> _submit;
object_ptr<Ui::FlatLabel> _title; object_ptr<Ui::FlatLabel> _title;
std::unique_ptr<Info::Profile::Badge> _badge;
object_ptr<Ui::FlatLabel> _status; object_ptr<Ui::FlatLabel> _status;
object_ptr<Ui::FlatLabel> _about; object_ptr<Ui::FlatLabel> _about;
object_ptr<Ui::FlatLabel> _aboutRequests; object_ptr<Ui::FlatLabel> _aboutRequests;
std::shared_ptr<Data::PhotoMedia> _photo; std::shared_ptr<Data::PhotoMedia> _photo;
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty; std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
std::vector<Participant> _participants; std::vector<Participant> _participants;
bool _isChannel = false; bool _isChannel = false;
bool _requestApprove = false; bool _requestApprove = false;

View file

@ -22,6 +22,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Info::Profile { namespace Info::Profile {
namespace { namespace {
[[nodiscard]] rpl::producer<Badge::Content> ContentForPeer(
not_null<PeerData*> peer) {
return rpl::combine(
BadgeValue(peer),
EmojiStatusIdValue(peer)
) | rpl::map([=](BadgeType badge, DocumentId emojiStatusId) {
return Badge::Content{ badge, emojiStatusId };
});
}
} // namespace } // namespace
Badge::Badge( Badge::Badge(
@ -32,18 +42,37 @@ Badge::Badge(
Fn<bool()> animationPaused, Fn<bool()> animationPaused,
int customStatusLoopsLimit, int customStatusLoopsLimit,
base::flags<BadgeType> allowed) base::flags<BadgeType> allowed)
: Badge(
parent,
st,
&peer->session(),
ContentForPeer(peer),
emojiStatusPanel,
std::move(animationPaused),
customStatusLoopsLimit,
allowed) {
}
Badge::Badge(
not_null<QWidget*> parent,
const style::InfoPeerBadge &st,
not_null<Main::Session*> session,
rpl::producer<Content> content,
EmojiStatusPanel *emojiStatusPanel,
Fn<bool()> animationPaused,
int customStatusLoopsLimit,
base::flags<BadgeType> allowed)
: _parent(parent) : _parent(parent)
, _st(st) , _st(st)
, _peer(peer) , _session(session)
, _emojiStatusPanel(emojiStatusPanel) , _emojiStatusPanel(emojiStatusPanel)
, _customStatusLoopsLimit(customStatusLoopsLimit) , _customStatusLoopsLimit(customStatusLoopsLimit)
, _allowed(allowed) , _allowed(allowed)
, _animationPaused(std::move(animationPaused)) { , _animationPaused(std::move(animationPaused)) {
rpl::combine( std::move(
BadgeValue(peer), content
EmojiStatusIdValue(peer) ) | rpl::start_with_next([=](Content content) {
) | rpl::start_with_next([=](BadgeType badge, DocumentId emojiStatusId) { setContent(content);
setBadge(badge, emojiStatusId);
}, _lifetime); }, _lifetime);
} }
@ -51,37 +80,36 @@ Ui::RpWidget *Badge::widget() const {
return _view.data(); return _view.data();
} }
void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) { void Badge::setContent(Content content) {
if (!(_allowed & badge) if (!(_allowed & content.badge)
|| (!_peer->session().premiumBadgesShown() || (!_session->premiumBadgesShown()
&& badge == BadgeType::Premium)) { && content.badge == BadgeType::Premium)) {
badge = BadgeType::None; content.badge = BadgeType::None;
} }
if (!(_allowed & badge)) { if (!(_allowed & content.badge)) {
badge = BadgeType::None; content.badge = BadgeType::None;
} }
if (badge != BadgeType::Premium) { if (content.badge != BadgeType::Premium) {
emojiStatusId = 0; content.emojiStatusId = 0;
} }
if (_badge == badge && _emojiStatusId == emojiStatusId) { if (_content == content) {
return; return;
} }
_badge = badge; _content = content;
_emojiStatusId = emojiStatusId;
_emojiStatus = nullptr; _emojiStatus = nullptr;
_view.destroy(); _view.destroy();
if (_badge == BadgeType::None) { if (_content.badge == BadgeType::None) {
_updated.fire({}); _updated.fire({});
return; return;
} }
_view.create(_parent); _view.create(_parent);
_view->show(); _view->show();
switch (_badge) { switch (_content.badge) {
case BadgeType::Verified: case BadgeType::Verified:
case BadgeType::Premium: { case BadgeType::Premium: {
if (_emojiStatusId) { if (const auto id = _content.emojiStatusId) {
_emojiStatus = _peer->owner().customEmojiManager().create( _emojiStatus = _session->data().customEmojiManager().create(
_emojiStatusId, id,
[raw = _view.data()] { raw->update(); }, [raw = _view.data()] { raw->update(); },
sizeTag()); sizeTag());
if (_customStatusLoopsLimit > 0) { if (_customStatusLoopsLimit > 0) {
@ -107,7 +135,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) {
} }
}, _view->lifetime()); }, _view->lifetime());
} else { } else {
const auto icon = (_badge == BadgeType::Verified) const auto icon = (_content.badge == BadgeType::Verified)
? &_st.verified ? &_st.verified
: &_st.premium; : &_st.premium;
_view->resize(icon->size()); _view->resize(icon->size());
@ -120,7 +148,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) {
} break; } break;
case BadgeType::Scam: case BadgeType::Scam:
case BadgeType::Fake: { case BadgeType::Fake: {
const auto fake = (_badge == BadgeType::Fake); const auto fake = (_content.badge == BadgeType::Fake);
const auto size = Ui::ScamBadgeSize(fake); const auto size = Ui::ScamBadgeSize(fake);
const auto skip = st::infoVerifiedCheckPosition.x(); const auto skip = st::infoVerifiedCheckPosition.x();
_view->resize( _view->resize(
@ -139,7 +167,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) {
} break; } break;
} }
if (_badge != BadgeType::Premium || !_premiumClickCallback) { if (_content.badge != BadgeType::Premium || !_premiumClickCallback) {
_view->setAttribute(Qt::WA_TransparentForMouseEvents); _view->setAttribute(Qt::WA_TransparentForMouseEvents);
} else { } else {
_view->setClickedCallback(_premiumClickCallback); _view->setClickedCallback(_premiumClickCallback);
@ -150,7 +178,7 @@ void Badge::setBadge(BadgeType badge, DocumentId emojiStatusId) {
void Badge::setPremiumClickCallback(Fn<void()> callback) { void Badge::setPremiumClickCallback(Fn<void()> callback) {
_premiumClickCallback = std::move(callback); _premiumClickCallback = std::move(callback);
if (_view && _badge == BadgeType::Premium) { if (_view && _content.badge == BadgeType::Premium) {
if (!_premiumClickCallback) { if (!_premiumClickCallback) {
_view->setAttribute(Qt::WA_TransparentForMouseEvents); _view->setAttribute(Qt::WA_TransparentForMouseEvents);
} else { } else {
@ -169,7 +197,8 @@ void Badge::move(int left, int top, int bottom) {
return; return;
} }
const auto star = !_emojiStatus 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 fake = !_emojiStatus && !star;
const auto skip = fake ? 0 : _st.position.x(); const auto skip = fake ? 0 : _st.position.x();
const auto badgeLeft = left + skip; const auto badgeLeft = left + skip;

View file

@ -18,6 +18,10 @@ namespace Data {
enum class CustomEmojiSizeTag : uchar; enum class CustomEmojiSizeTag : uchar;
} // namespace Data } // namespace Data
namespace Main {
class Session;
} // namespace Main
namespace Ui { namespace Ui {
class RpWidget; class RpWidget;
class AbstractButton; class AbstractButton;
@ -45,7 +49,25 @@ public:
EmojiStatusPanel *emojiStatusPanel, EmojiStatusPanel *emojiStatusPanel,
Fn<bool()> animationPaused, Fn<bool()> animationPaused,
int customStatusLoopsLimit = 0, int customStatusLoopsLimit = 0,
base::flags<BadgeType> allowed = base::flags<BadgeType>::from_raw(-1)); base::flags<BadgeType> allowed
= base::flags<BadgeType>::from_raw(-1));
struct Content {
BadgeType badge = BadgeType::None;
DocumentId emojiStatusId = 0;
friend inline constexpr bool operator==(Content, Content) = default;
};
Badge(
not_null<QWidget*> parent,
const style::InfoPeerBadge &st,
not_null<Main::Session*> session,
rpl::producer<Content> content,
EmojiStatusPanel *emojiStatusPanel,
Fn<bool()> animationPaused,
int customStatusLoopsLimit = 0,
base::flags<BadgeType> allowed
= base::flags<BadgeType>::from_raw(-1));
[[nodiscard]] Ui::RpWidget *widget() const; [[nodiscard]] Ui::RpWidget *widget() const;
@ -56,17 +78,16 @@ public:
[[nodiscard]] Data::CustomEmojiSizeTag sizeTag() const; [[nodiscard]] Data::CustomEmojiSizeTag sizeTag() const;
private: private:
void setBadge(BadgeType badge, DocumentId emojiStatusId); void setContent(Content content);
const not_null<QWidget*> _parent; const not_null<QWidget*> _parent;
const style::InfoPeerBadge &_st; const style::InfoPeerBadge &_st;
const not_null<PeerData*> _peer; const not_null<Main::Session*> _session;
EmojiStatusPanel *_emojiStatusPanel = nullptr; EmojiStatusPanel *_emojiStatusPanel = nullptr;
const int _customStatusLoopsLimit = 0; const int _customStatusLoopsLimit = 0;
DocumentId _emojiStatusId = 0;
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus; std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
base::flags<BadgeType> _allowed; base::flags<BadgeType> _allowed;
BadgeType _badge = BadgeType(); Content _content;
Fn<void()> _premiumClickCallback; Fn<void()> _premiumClickCallback;
Fn<bool()> _animationPaused; Fn<bool()> _animationPaused;
object_ptr<Ui::AbstractButton> _view = { nullptr }; object_ptr<Ui::AbstractButton> _view = { nullptr };