Add support for FAKE badge.

This commit is contained in:
John Preston 2021-01-21 16:39:40 +04:00
parent 1774b21e88
commit 58733ba6ea
13 changed files with 136 additions and 94 deletions

View File

@ -126,6 +126,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_status" = "channel";
"lng_group_status" = "group";
"lng_scam_badge" = "SCAM";
"lng_fake_badge" = "FAKE";
"lng_flood_error" = "Too many tries. Please try again later.";
"lng_gif_error" = "An error has occurred while reading GIF animation :(";

View File

@ -109,7 +109,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#200250ba id:int = User;
user#938458c1 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
user#938458c1 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#69d3ab26 flags:# has_video:flags.0?true photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
@ -124,7 +124,7 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#9ba2d800 id:int = Chat;
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#7328bdb id:int title:string = Chat;
channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#f3474af6 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall = ChatFull;
@ -1217,6 +1217,8 @@ messages.chatInviteImporters#81b6b00a count:int importers:Vector<ChatInviteImpor
messages.historyImport#1662af0b id:long = messages.HistoryImport;
messages.historyImportParsed#8d94ab42 flags:# pm:flags.0?true group:flags.1?true title:flags.1?string = messages.HistoryImportParsed;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1473,6 +1475,7 @@ messages.deleteExportedChatInvite#d464a42b peer:InputPeer link:string = Bool;
messages.getChatInviteImporters#26fb7289 peer:InputPeer link:string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.deleteChat#83247d11 chat_id:int = Bool;
messages.deletePhoneCallHistory#6cff1b45 flags:# revoke:flags.0?true = messages.AffectedHistory;
messages.checkHistoryImport#43fe19f3 import_head:string = messages.HistoryImportParsed;
messages.initHistoryImport#34090c3b peer:InputPeer file:InputFile media_count:int = messages.HistoryImport;
messages.uploadImportedMedia#2a862092 peer:InputPeer import_id:long file_name:string media:InputMedia = MessageMedia;
messages.startHistoryImport#b43df344 peer:InputPeer import_id:long = Bool;

View File

@ -94,6 +94,7 @@ public:
| MTPDchannel::Flag::f_broadcast
| MTPDchannel::Flag::f_verified
| MTPDchannel::Flag::f_scam
| MTPDchannel::Flag::f_fake
| MTPDchannel::Flag::f_megagroup
| MTPDchannel::Flag::f_restricted
| MTPDchannel::Flag::f_signatures
@ -203,6 +204,9 @@ public:
[[nodiscard]] bool isScam() const {
return flags() & MTPDchannel::Flag::f_scam;
}
[[nodiscard]] bool isFake() const {
return flags() & MTPDchannel::Flag::f_fake;
}
static MTPChatBannedRights KickedRestrictedRights();
static constexpr auto kRestrictUntilForever = TimeId(INT_MAX);

View File

@ -747,6 +747,15 @@ bool PeerData::isScam() const {
return false;
}
bool PeerData::isFake() const {
if (const auto user = asUser()) {
return user->isFake();
} else if (const auto channel = asChannel()) {
return channel->isFake();
}
return false;
}
bool PeerData::isMegagroup() const {
return isChannel() ? asChannel()->isMegagroup() : false;
}

View File

@ -158,6 +158,7 @@ public:
}
[[nodiscard]] bool isVerified() const;
[[nodiscard]] bool isScam() const;
[[nodiscard]] bool isFake() const;
[[nodiscard]] bool isMegagroup() const;
[[nodiscard]] bool isBroadcast() const;
[[nodiscard]] bool isRepliesChat() const;

View File

@ -50,6 +50,7 @@ public:
| MTPDuser::Flag::f_bot_nochats
| MTPDuser::Flag::f_verified
| MTPDuser::Flag::f_scam
| MTPDuser::Flag::f_fake
| MTPDuser::Flag::f_restricted
| MTPDuser::Flag::f_bot_inline_geo;
using Flags = Data::Flags<
@ -111,48 +112,51 @@ public:
void removeFullFlags(MTPDuserFull::Flags which) {
_fullFlags.remove(which);
}
auto fullFlags() const {
[[nodiscard]] auto fullFlags() const {
return _fullFlags.current();
}
auto fullFlagsValue() const {
[[nodiscard]] auto fullFlagsValue() const {
return _fullFlags.value();
}
bool isVerified() const {
[[nodiscard]] bool isVerified() const {
return flags() & MTPDuser::Flag::f_verified;
}
bool isScam() const {
[[nodiscard]] bool isScam() const {
return flags() & MTPDuser::Flag::f_scam;
}
bool isBotInlineGeo() const {
[[nodiscard]] bool isFake() const {
return flags() & MTPDuser::Flag::f_fake;
}
[[nodiscard]] bool isBotInlineGeo() const {
return flags() & MTPDuser::Flag::f_bot_inline_geo;
}
bool isBot() const {
[[nodiscard]] bool isBot() const {
return botInfo != nullptr;
}
bool isSupport() const {
[[nodiscard]] bool isSupport() const {
return flags() & MTPDuser::Flag::f_support;
}
bool isInaccessible() const {
[[nodiscard]] bool isInaccessible() const {
constexpr auto inaccessible = 0
| MTPDuser::Flag::f_deleted;
// | MTPDuser_ClientFlag::f_inaccessible;
return flags() & inaccessible;
}
bool canWrite() const {
[[nodiscard]] bool canWrite() const {
// Duplicated in Data::CanWriteValue().
return !isInaccessible() && !isRepliesChat();
}
bool canShareThisContact() const;
bool canAddContact() const {
[[nodiscard]] bool canShareThisContact() const;
[[nodiscard]] bool canAddContact() const {
return canShareThisContact() && !isContact();
}
// In Data::Session::processUsers() we check only that.
// When actually trying to share contact we perform
// a full check by canShareThisContact() call.
bool canShareThisContactFast() const {
[[nodiscard]] bool canShareThisContactFast() const {
return !_phone.isEmpty();
}
@ -161,7 +165,7 @@ public:
QString firstName;
QString lastName;
QString username;
const QString &phone() const {
[[nodiscard]] const QString &phone() const {
return _phone;
}
QString nameOrPhone;

View File

@ -452,11 +452,6 @@ void paintRow(
}
p.setFont(st::msgNameFont);
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
if (flags & (Flag::SavedMessages | Flag::RepliesMessages)) {
auto text = (flags & Flag::SavedMessages)
? tr::lng_saved_messages(tr::now)
@ -465,6 +460,11 @@ void paintRow(
if (textWidth > rectForName.width()) {
text = st::msgNameFont->elided(text, rectForName.width());
}
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
p.drawTextLeft(rectForName.left(), rectForName.top(), fullWidth, text);
} else if (from) {
if (!(flags & Flag::SearchResult)) {
@ -488,15 +488,25 @@ void paintRow(
badgeStyle);
rectForName.setWidth(rectForName.width() - badgeWidth);
}
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
from->nameText().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} else if (hiddenSenderInfo) {
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsNameFgOver
: st::dialogsNameFg);
hiddenSenderInfo->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} else {
if (!active) {
p.setPen(selected
? st::dialogsArchiveFgOver
: st::dialogsArchiveFg);
}
p.setPen(active
? st::dialogsNameFgActive
: selected
? st::dialogsArchiveFgOver
: st::dialogsArchiveFg);
auto text = entry->chatListName(); // TODO feed name with emoji
auto textWidth = st::msgNameFont->width(text);
if (textWidth > rectForName.width()) {

View File

@ -322,15 +322,10 @@ void Cover::initViewers(rpl::producer<QString> title) {
} else if (_peer->isSelf()) {
refreshUploadPhotoOverlay();
}
VerifiedValue(
BadgeValue(
_peer
) | rpl::start_with_next([=](bool verified) {
setVerified(verified);
}, lifetime());
ScamValue(
_peer
) | rpl::start_with_next([=](bool scam) {
setScam(scam);
) | rpl::start_with_next([=](Badge badge) {
setBadge(badge);
}, lifetime());
}
@ -345,50 +340,45 @@ void Cover::refreshUploadPhotoOverlay() {
}());
}
void Cover::setVerified(bool verified) {
if ((_verifiedCheck != nullptr) == verified) {
void Cover::setBadge(Badge badge) {
if (_badge == badge) {
return;
}
if (verified) {
_scamBadge.destroy();
_badge = badge;
_verifiedCheck.destroy();
_scamFakeBadge.destroy();
switch (_badge) {
case Badge::Verified:
_verifiedCheck.create(this);
_verifiedCheck->show();
_verifiedCheck->resize(st::infoVerifiedCheck.size());
_verifiedCheck->paintRequest(
) | rpl::start_with_next([check = _verifiedCheck.data()] {
) | rpl::start_with_next([check = _verifiedCheck.data()]{
Painter p(check);
st::infoVerifiedCheck.paint(p, 0, 0, check->width());
}, _verifiedCheck->lifetime());
} else {
_verifiedCheck.destroy();
}
refreshNameGeometry(width());
}
void Cover::setScam(bool scam) {
if ((_scamBadge != nullptr) == scam) {
return;
}
if (scam) {
_verifiedCheck.destroy();
const auto size = Ui::ScamBadgeSize();
}, _verifiedCheck->lifetime());
break;
case Badge::Scam:
case Badge::Fake: {
const auto fake = (_badge == Badge::Fake);
const auto size = Ui::ScamBadgeSize(fake);
const auto skip = st::infoVerifiedCheckPosition.x();
_scamBadge.create(this);
_scamBadge->show();
_scamBadge->resize(
_scamFakeBadge.create(this);
_scamFakeBadge->show();
_scamFakeBadge->resize(
size.width() + 2 * skip,
size.height() + 2 * skip);
_scamBadge->paintRequest(
) | rpl::start_with_next([=, badge = _scamBadge.data()] {
_scamFakeBadge->paintRequest(
) | rpl::start_with_next([=, badge = _scamFakeBadge.data()]{
Painter p(badge);
Ui::DrawScamBadge(
fake,
p,
badge->rect().marginsRemoved({ skip, skip, skip, skip }),
badge->width(),
st::attentionButtonFg);
}, _scamBadge->lifetime());
} else {
_scamBadge.destroy();
}, _scamFakeBadge->lifetime());
} break;
}
refreshNameGeometry(width());
}
@ -452,9 +442,9 @@ void Cover::refreshNameGeometry(int newWidth) {
if (_verifiedCheck) {
nameWidth -= st::infoVerifiedCheckPosition.x()
+ _verifiedCheck->width();
} else if (_scamBadge) {
} else if (_scamFakeBadge) {
nameWidth -= st::infoVerifiedCheckPosition.x()
+ _scamBadge->width();
+ _scamFakeBadge->width();
}
_name->resizeToNaturalWidth(nameWidth);
_name->moveToLeft(nameLeft, nameTop, newWidth);
@ -465,15 +455,15 @@ void Cover::refreshNameGeometry(int newWidth) {
const auto checkTop = nameTop
+ st::infoVerifiedCheckPosition.y();
_verifiedCheck->moveToLeft(checkLeft, checkTop, newWidth);
} else if (_scamBadge) {
} else if (_scamFakeBadge) {
const auto skip = st::infoVerifiedCheckPosition.x();
const auto badgeLeft = nameLeft
+ _name->width()
+ st::infoVerifiedCheckPosition.x()
- skip;
const auto badgeTop = nameTop
+ (_name->height() - _scamBadge->height()) / 2;
_scamBadge->moveToLeft(badgeLeft, badgeTop, newWidth);
+ (_name->height() - _scamFakeBadge->height()) / 2;
_scamFakeBadge->moveToLeft(badgeLeft, badgeTop, newWidth);
}
}

View File

@ -34,6 +34,8 @@ class Section;
namespace Info {
namespace Profile {
enum class Badge;
class SectionWithToggle : public Ui::FixedHeightWidget {
public:
using FixedHeightWidget::FixedHeightWidget;
@ -85,16 +87,16 @@ private:
void refreshNameGeometry(int newWidth);
void refreshStatusGeometry(int newWidth);
void refreshUploadPhotoOverlay();
void setVerified(bool verified);
void setScam(bool scam);
void setBadge(Badge badge);
not_null<PeerData*> _peer;
int _onlineCount = 0;
Badge _badge = Badge();
object_ptr<Ui::UserpicButton> _userpic;
object_ptr<Ui::FlatLabel> _name = { nullptr };
object_ptr<Ui::RpWidget> _verifiedCheck = { nullptr };
object_ptr<Ui::RpWidget> _scamBadge = { nullptr };
object_ptr<Ui::RpWidget> _scamFakeBadge = { nullptr };
object_ptr<Ui::FlatLabel> _status = { nullptr };
//object_ptr<CoverDropArea> _dropArea = { nullptr };
base::Timer _refreshStatusTimer;

View File

@ -376,27 +376,31 @@ rpl::producer<bool> CanAddMemberValue(not_null<PeerData*> peer) {
return rpl::single(false);
}
rpl::producer<bool> VerifiedValue(not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) {
return Data::PeerFlagValue(user, MTPDuser::Flag::f_verified);
} else if (const auto channel = peer->asChannel()) {
return Data::PeerFlagValue(
channel,
MTPDchannel::Flag::f_verified);
}
return rpl::single(false);
template <typename Flag, typename Peer>
rpl::producer<Badge> BadgeValueFromFlags(Peer peer) {
return Data::PeerFlagsValue(
peer,
Flag::f_verified | Flag::f_scam | Flag::f_fake
) | rpl::map([=](base::flags<Flag> value) {
return (value & Flag::f_verified)
? Badge::Verified
: (value & Flag::f_scam)
? Badge::Scam
: (value & Flag::f_fake)
? Badge::Fake
: Badge::None;
});
}
rpl::producer<bool> ScamValue(not_null<PeerData*> peer) {
rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) {
return Data::PeerFlagValue(user, MTPDuser::Flag::f_scam);
return BadgeValueFromFlags<MTPDuser::Flag>(user);
} else if (const auto channel = peer->asChannel()) {
return Data::PeerFlagValue(
channel,
MTPDchannel::Flag::f_scam);
return BadgeValueFromFlags<MTPDchannel::Flag>(channel);
}
return rpl::single(false);
return rpl::single(Badge::None);
}
// // #feed
//rpl::producer<int> FeedChannelsCountValue(not_null<Data::Feed*> feed) {
// using Flag = Data::FeedUpdateFlag;

View File

@ -59,8 +59,14 @@ rpl::producer<int> SharedMediaCountValue(
Storage::SharedMediaType type);
rpl::producer<int> CommonGroupsCountValue(not_null<UserData*> user);
rpl::producer<bool> CanAddMemberValue(not_null<PeerData*> peer);
rpl::producer<bool> VerifiedValue(not_null<PeerData*> peer);
rpl::producer<bool> ScamValue(not_null<PeerData*> peer);
enum class Badge {
None,
Verified,
Scam,
Fake,
};
rpl::producer<Badge> BadgeValue(not_null<PeerData*> peer);
//rpl::producer<int> FeedChannelsCountValue(not_null<Data::Feed*> feed); // #feed

View File

@ -48,8 +48,10 @@ void UnreadBadge::paintEvent(QPaintEvent *e) {
unreadSt);
}
QSize ScamBadgeSize() {
const auto phrase = tr::lng_scam_badge(tr::now);
QSize ScamBadgeSize(bool fake) {
const auto phrase = fake
? tr::lng_fake_badge(tr::now)
: tr::lng_scam_badge(tr::now);
const auto phraseWidth = st::dialogsScamFont->width(phrase);
const auto width = st::dialogsScamPadding.left()
+ phraseWidth
@ -60,7 +62,7 @@ QSize ScamBadgeSize() {
return { width, height };
}
void DrawScamBadge(
void DrawScamFakeBadge(
Painter &p,
QRect rect,
int outerWidth,
@ -83,12 +85,15 @@ void DrawScamBadge(
}
void DrawScamBadge(
bool fake,
Painter &p,
QRect rect,
int outerWidth,
const style::color &color) {
const auto phrase = tr::lng_scam_badge(tr::now);
DrawScamBadge(
const auto phrase = fake
? tr::lng_fake_badge(tr::now)
: tr::lng_scam_badge(tr::now);
DrawScamFakeBadge(
p,
rect,
outerWidth,
@ -112,8 +117,10 @@ int DrawPeerBadgeGetWidth(
rectForName.y(),
outerWidth);
return iconw;
} else if (peer->isScam() && st.scam) {
const auto phrase = tr::lng_scam_badge(tr::now);
} else if ((peer->isScam() || peer->isFake()) && st.scam) {
const auto phrase = peer->isScam()
? tr::lng_scam_badge(tr::now)
: tr::lng_fake_badge(tr::now);
const auto phraseWidth = st::dialogsScamFont->width(phrase);
const auto width = st::dialogsScamPadding.left()
+ phraseWidth
@ -129,7 +136,7 @@ int DrawPeerBadgeGetWidth(
rectForName.y() + (rectForName.height() - height) / 2,
width,
height);
DrawScamBadge(p, rect, outerWidth, *st.scam, phrase, phraseWidth);
DrawScamFakeBadge(p, rect, outerWidth, *st.scam, phrase, phraseWidth);
return st::dialogsScamSkip + width;
}
return 0;

View File

@ -38,8 +38,9 @@ int DrawPeerBadgeGetWidth(
int nameWidth,
int outerWidth,
const PeerBadgeStyle &st);
QSize ScamBadgeSize();
QSize ScamBadgeSize(bool fake);
void DrawScamBadge(
bool fake,
Painter &p,
QRect rect,
int outerWidth,