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 "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<Info::Profile::Badge>(
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()

View File

@ -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<Main::Session*> session,
const MTPDchatInvite &data);
[[nodiscard]] Info::Profile::BadgeType BadgeForInvite(
const ChatInvite &invite);
ConfirmInviteBox(
not_null<Main::Session*> session,
@ -81,12 +91,14 @@ private:
Fn<void()> _submit;
object_ptr<Ui::FlatLabel> _title;
std::unique_ptr<Info::Profile::Badge> _badge;
object_ptr<Ui::FlatLabel> _status;
object_ptr<Ui::FlatLabel> _about;
object_ptr<Ui::FlatLabel> _aboutRequests;
std::shared_ptr<Data::PhotoMedia> _photo;
std::unique_ptr<Ui::EmptyUserpic> _photoEmpty;
std::vector<Participant> _participants;
bool _isChannel = false;
bool _requestApprove = false;

View File

@ -22,6 +22,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Info::Profile {
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
Badge::Badge(
@ -32,18 +42,37 @@ Badge::Badge(
Fn<bool()> animationPaused,
int customStatusLoopsLimit,
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)
, _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<void()> 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;

View File

@ -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<bool()> animationPaused,
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;
@ -56,17 +78,16 @@ public:
[[nodiscard]] Data::CustomEmojiSizeTag sizeTag() const;
private:
void setBadge(BadgeType badge, DocumentId emojiStatusId);
void setContent(Content content);
const not_null<QWidget*> _parent;
const style::InfoPeerBadge &_st;
const not_null<PeerData*> _peer;
const not_null<Main::Session*> _session;
EmojiStatusPanel *_emojiStatusPanel = nullptr;
const int _customStatusLoopsLimit = 0;
DocumentId _emojiStatusId = 0;
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
base::flags<BadgeType> _allowed;
BadgeType _badge = BadgeType();
Content _content;
Fn<void()> _premiumClickCallback;
Fn<bool()> _animationPaused;
object_ptr<Ui::AbstractButton> _view = { nullptr };