Improve verified badge display.
BIN
Telegram/Resources/art/verified_bg.webp
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
Telegram/Resources/art/verified_fg.webp
Normal file
After Width: | Height: | Size: 500 B |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 672 B After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1,001 B After Width: | Height: | Size: 1.9 KiB |
|
@ -34,6 +34,8 @@
|
||||||
<file alias="topic_icons/general.svg">../../art/topic_icons/general.svg</file>
|
<file alias="topic_icons/general.svg">../../art/topic_icons/general.svg</file>
|
||||||
<file alias="links_subscription.svg">../../icons/info/edit/links_subscription.svg</file>
|
<file alias="links_subscription.svg">../../icons/info/edit/links_subscription.svg</file>
|
||||||
<file alias="plane_white.svg">../../icons/plane_white.svg</file>
|
<file alias="plane_white.svg">../../icons/plane_white.svg</file>
|
||||||
|
<file alias="art/verified_bg.webp">../../art/verified_bg.webp</file>
|
||||||
|
<file alias="art/verified_fg.webp">../../art/verified_fg.webp</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/icons">
|
<qresource prefix="/icons">
|
||||||
<file alias="calls/hands.lottie">../../icons/calls/hands.lottie</file>
|
<file alias="calls/hands.lottie">../../icons/calls/hands.lottie</file>
|
||||||
|
|
|
@ -799,9 +799,6 @@ int PeerListRow::paintNameIconGetWidth(
|
||||||
outerWidth,
|
outerWidth,
|
||||||
{
|
{
|
||||||
.peer = peer(),
|
.peer = peer(),
|
||||||
.verified = &(selected
|
|
||||||
? st::dialogsVerifiedIconOver
|
|
||||||
: st::dialogsVerifiedIcon),
|
|
||||||
.premium = &(selected
|
.premium = &(selected
|
||||||
? st::dialogsPremiumIcon.over
|
? st::dialogsPremiumIcon.over
|
||||||
: st::dialogsPremiumIcon.icon),
|
: st::dialogsPremiumIcon.icon),
|
||||||
|
|
|
@ -31,6 +31,12 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kDontCacheLottieAfterArea = 512 * 512;
|
constexpr auto kDontCacheLottieAfterArea = 512 * 512;
|
||||||
|
|
||||||
|
[[nodiscard]] uint64 LocalStickerId(QStringView name) {
|
||||||
|
auto full = u"local_sticker:"_q;
|
||||||
|
full.append(name);
|
||||||
|
return XXH64(full.data(), full.size() * sizeof(QChar), 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
uint8 LottieCacheKeyShift(uint8 replacementsTag, StickerLottieSize sizeTag) {
|
uint8 LottieCacheKeyShift(uint8 replacementsTag, StickerLottieSize sizeTag) {
|
||||||
|
@ -315,16 +321,9 @@ QSize ComputeStickerSize(not_null<DocumentData*> document, QSize box) {
|
||||||
return HistoryView::NonEmptySize(request.size(dimensions, 8) / ratio);
|
return HistoryView::NonEmptySize(request.size(dimensions, 8) / ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] uint64 LocalTgsStickerId(QStringView name) {
|
not_null<DocumentData*> GenerateLocalSticker(
|
||||||
auto full = u"local_tgs_sticker:"_q;
|
|
||||||
full.append(name);
|
|
||||||
return XXH64(full.data(), full.size() * sizeof(QChar), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
not_null<DocumentData*> GenerateLocalTgsSticker(
|
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QString &name) {
|
const QString &path) {
|
||||||
const auto path = u":/animations/"_q + name + u".tgs"_q;
|
|
||||||
auto task = FileLoadTask(
|
auto task = FileLoadTask(
|
||||||
session,
|
session,
|
||||||
path,
|
path,
|
||||||
|
@ -335,7 +334,7 @@ not_null<DocumentData*> GenerateLocalTgsSticker(
|
||||||
{},
|
{},
|
||||||
false,
|
false,
|
||||||
nullptr,
|
nullptr,
|
||||||
LocalTgsStickerId(name));
|
LocalStickerId(path));
|
||||||
task.process({ .generateGoodThumbnail = false });
|
task.process({ .generateGoodThumbnail = false });
|
||||||
const auto result = task.peekResult();
|
const auto result = task.peekResult();
|
||||||
Assert(result != nullptr);
|
Assert(result != nullptr);
|
||||||
|
@ -348,8 +347,18 @@ not_null<DocumentData*> GenerateLocalTgsSticker(
|
||||||
document->setLocation(Core::FileLocation(path));
|
document->setLocation(Core::FileLocation(path));
|
||||||
|
|
||||||
Ensures(document->sticker());
|
Ensures(document->sticker());
|
||||||
Ensures(document->sticker()->isLottie());
|
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
not_null<DocumentData*> GenerateLocalTgsSticker(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const QString &name) {
|
||||||
|
const auto result = GenerateLocalSticker(
|
||||||
|
session,
|
||||||
|
u":/animations/"_q + name + u".tgs"_q);
|
||||||
|
|
||||||
|
Ensures(result->sticker()->isLottie());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ChatHelpers
|
} // namespace ChatHelpers
|
||||||
|
|
|
@ -130,6 +130,10 @@ bool PaintStickerThumbnailPath(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
QSize box);
|
QSize box);
|
||||||
|
|
||||||
|
[[nodiscard]] not_null<DocumentData*> GenerateLocalSticker(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const QString &path);
|
||||||
|
|
||||||
[[nodiscard]] not_null<DocumentData*> GenerateLocalTgsSticker(
|
[[nodiscard]] not_null<DocumentData*> GenerateLocalTgsSticker(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QString &name);
|
const QString &name);
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_bot.h"
|
#include "api/api_bot.h"
|
||||||
#include "api/api_text_entities.h"
|
#include "api/api_text_entities.h"
|
||||||
#include "api/api_user_names.h"
|
#include "api/api_user_names.h"
|
||||||
|
#include "chat_helpers/stickers_lottie.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
#include "core/mime_type.h" // Core::IsMimeSticker
|
#include "core/mime_type.h" // Core::IsMimeSticker
|
||||||
|
@ -353,11 +354,16 @@ Session::Session(not_null<Main::Session*> session)
|
||||||
|
|
||||||
Ui::VerifyDetails Session::verifiedByTelegram() {
|
Ui::VerifyDetails Session::verifiedByTelegram() {
|
||||||
if (_verifiedByTelegramIconBgId.isEmpty()) {
|
if (_verifiedByTelegramIconBgId.isEmpty()) {
|
||||||
auto &manager = customEmojiManager();
|
const auto bg = ChatHelpers::GenerateLocalSticker(
|
||||||
_verifiedByTelegramIconBgId = manager.registerInternalEmoji(
|
_session,
|
||||||
st::dialogsVerifiedBg);
|
u":/gui/art/verified_bg.webp"_q);
|
||||||
_verifiedByTelegramIconFgId = manager.registerInternalEmoji(
|
bg->overrideEmojiUsesTextColor(true);
|
||||||
st::dialogsVerifiedFg);
|
const auto fg = ChatHelpers::GenerateLocalSticker(
|
||||||
|
_session,
|
||||||
|
u":/gui/art/verified_fg.webp"_q);
|
||||||
|
fg->overrideEmojiUsesTextColor(true);
|
||||||
|
_verifiedByTelegramIconBgId = Data::SerializeCustomEmojiId(bg);
|
||||||
|
_verifiedByTelegramIconFgId = Data::SerializeCustomEmojiId(fg);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
.iconBgId = _verifiedByTelegramIconBgId,
|
.iconBgId = _verifiedByTelegramIconBgId,
|
||||||
|
|
|
@ -409,6 +409,7 @@ dialogsLockIcon: ThreeStateIcon {
|
||||||
|
|
||||||
dialogsVerifiedBg: icon{{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBg }};
|
dialogsVerifiedBg: icon{{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBg }};
|
||||||
dialogsVerifiedFg: icon{{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFg }};
|
dialogsVerifiedFg: icon{{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFg }};
|
||||||
|
dialogsVerifiedPadding: margins(0px, 3px, 0px, 0px);
|
||||||
dialogsVerifiedColors: VerifiedBadge {
|
dialogsVerifiedColors: VerifiedBadge {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
bg: dialogsVerifiedIconBg;
|
bg: dialogsVerifiedIconBg;
|
||||||
|
@ -423,18 +424,6 @@ dialogsVerifiedColorsActive: VerifiedBadge(dialogsVerifiedColors) {
|
||||||
fg: dialogsVerifiedIconFgActive;
|
fg: dialogsVerifiedIconFgActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogsVerifiedIcon: icon {
|
|
||||||
{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBg },
|
|
||||||
{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFg },
|
|
||||||
};
|
|
||||||
dialogsVerifiedIconOver: icon {
|
|
||||||
{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBgOver },
|
|
||||||
{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFgOver },
|
|
||||||
};
|
|
||||||
dialogsVerifiedIconActive: icon {
|
|
||||||
{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBgActive },
|
|
||||||
{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFgActive },
|
|
||||||
};
|
|
||||||
dialogsPremiumIcon: ThreeStateIcon {
|
dialogsPremiumIcon: ThreeStateIcon {
|
||||||
icon: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
|
icon: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
|
||||||
over: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBgOver }};
|
over: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBgOver }};
|
||||||
|
|
|
@ -1398,11 +1398,6 @@ void InnerWidget::paintPeerSearchResult(
|
||||||
context.width,
|
context.width,
|
||||||
{
|
{
|
||||||
.peer = peer,
|
.peer = peer,
|
||||||
.verified = (context.active
|
|
||||||
? &st::dialogsVerifiedIconActive
|
|
||||||
: context.selected
|
|
||||||
? &st::dialogsVerifiedIconOver
|
|
||||||
: &st::dialogsVerifiedIcon),
|
|
||||||
.premium = &ThreeStateIcon(
|
.premium = &ThreeStateIcon(
|
||||||
st::dialogsPremiumIcon,
|
st::dialogsPremiumIcon,
|
||||||
context.active,
|
context.active,
|
||||||
|
|
|
@ -732,11 +732,6 @@ void PaintRow(
|
||||||
context.width,
|
context.width,
|
||||||
{
|
{
|
||||||
.peer = from,
|
.peer = from,
|
||||||
.verified = (context.active
|
|
||||||
? &st::dialogsVerifiedIconActive
|
|
||||||
: context.selected
|
|
||||||
? &st::dialogsVerifiedIconOver
|
|
||||||
: &st::dialogsVerifiedIcon),
|
|
||||||
.premium = &ThreeStateIcon(
|
.premium = &ThreeStateIcon(
|
||||||
st::dialogsPremiumIcon,
|
st::dialogsPremiumIcon,
|
||||||
context.active,
|
context.active,
|
||||||
|
|
|
@ -589,7 +589,6 @@ void TopBarWidget::paintTopBar(Painter &p) {
|
||||||
width(),
|
width(),
|
||||||
{
|
{
|
||||||
.peer = namePeer,
|
.peer = namePeer,
|
||||||
.verified = &st::dialogsVerifiedIcon,
|
|
||||||
.premium = &st::dialogsPremiumIcon.icon,
|
.premium = &st::dialogsPremiumIcon.icon,
|
||||||
.scam = &st::attentionButtonFg,
|
.scam = &st::attentionButtonFg,
|
||||||
.premiumFg = &st::dialogsVerifiedIconBg,
|
.premiumFg = &st::dialogsVerifiedIconBg,
|
||||||
|
|
|
@ -22,7 +22,6 @@ InfoToggle {
|
||||||
}
|
}
|
||||||
|
|
||||||
InfoPeerBadge {
|
InfoPeerBadge {
|
||||||
verified: icon;
|
|
||||||
premium: icon;
|
premium: icon;
|
||||||
premiumFg: color;
|
premiumFg: color;
|
||||||
premiumInnerFg: color;
|
premiumInnerFg: color;
|
||||||
|
@ -437,7 +436,6 @@ infoVerifiedCheck: icon {
|
||||||
infoPremiumStar: icon {{ "profile_premium", profileVerifiedCheckBg }};
|
infoPremiumStar: icon {{ "profile_premium", profileVerifiedCheckBg }};
|
||||||
|
|
||||||
infoPeerBadge: InfoPeerBadge {
|
infoPeerBadge: InfoPeerBadge {
|
||||||
verified: infoVerifiedCheck;
|
|
||||||
premium: infoPremiumStar;
|
premium: infoPremiumStar;
|
||||||
premiumFg: profileVerifiedCheckBg;
|
premiumFg: profileVerifiedCheckBg;
|
||||||
premiumInnerFg: profileVerifiedCheckFg;
|
premiumInnerFg: profileVerifiedCheckFg;
|
||||||
|
|
|
@ -35,7 +35,12 @@ namespace {
|
||||||
} else if (emojiStatusId && badge == BadgeType::None) {
|
} else if (emojiStatusId && badge == BadgeType::None) {
|
||||||
badge = BadgeType::Premium;
|
badge = BadgeType::Premium;
|
||||||
}
|
}
|
||||||
return Badge::Content{ badge, emojiStatusId };
|
return Badge::Content{
|
||||||
|
badge,
|
||||||
|
(emojiStatusId
|
||||||
|
? Data::SerializeCustomEmojiId(emojiStatusId)
|
||||||
|
: QString()),
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,14 +120,14 @@ void Badge::setContent(Content content) {
|
||||||
case BadgeType::Premium: {
|
case BadgeType::Premium: {
|
||||||
const auto id = _content.emojiStatusId;
|
const auto id = _content.emojiStatusId;
|
||||||
const auto innerId = _content.emojiStatusInnerId;
|
const auto innerId = _content.emojiStatusInnerId;
|
||||||
if (id || innerId) {
|
if (!id.isEmpty() || !innerId.isEmpty()) {
|
||||||
_emojiStatus = id
|
_emojiStatus = !id.isEmpty()
|
||||||
? _session->data().customEmojiManager().create(
|
? _session->data().customEmojiManager().create(
|
||||||
id,
|
id,
|
||||||
[raw = _view.data()] { raw->update(); },
|
[raw = _view.data()] { raw->update(); },
|
||||||
sizeTag())
|
sizeTag())
|
||||||
: nullptr;
|
: nullptr;
|
||||||
_statusInner = innerId
|
_statusInner = !innerId.isEmpty()
|
||||||
? _session->data().customEmojiManager().create(
|
? _session->data().customEmojiManager().create(
|
||||||
innerId,
|
innerId,
|
||||||
[raw = _view.data()] { raw->update(); },
|
[raw = _view.data()] { raw->update(); },
|
||||||
|
@ -162,9 +167,7 @@ void Badge::setContent(Content content) {
|
||||||
}
|
}
|
||||||
}, _view->lifetime());
|
}, _view->lifetime());
|
||||||
} else {
|
} else {
|
||||||
const auto icon = (_content.badge == BadgeType::Verified)
|
const auto icon = &_st.premium;
|
||||||
? &_st.verified
|
|
||||||
: &_st.premium;
|
|
||||||
_view->resize(icon->size());
|
_view->resize(icon->size());
|
||||||
_view->paintRequest(
|
_view->paintRequest(
|
||||||
) | rpl::start_with_next([=, check = _view.data()]{
|
) | rpl::start_with_next([=, check = _view.data()]{
|
||||||
|
@ -224,9 +227,9 @@ void Badge::move(int left, int top, int bottom) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto star = !_emojiStatus
|
const auto star = !_emojiStatus
|
||||||
&& (_content.badge == BadgeType::Premium
|
&& (_content.badge == BadgeType::Premium);
|
||||||
|| _content.badge == BadgeType::Verified);
|
const auto fake = (!_emojiStatus && !star)
|
||||||
const auto fake = !_emojiStatus && !star;
|
|| (_content.badge == BadgeType::Verified);
|
||||||
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;
|
||||||
const auto badgeTop = top
|
const auto badgeTop = top
|
||||||
|
|
|
@ -58,8 +58,8 @@ public:
|
||||||
|
|
||||||
struct Content {
|
struct Content {
|
||||||
BadgeType badge = BadgeType::None;
|
BadgeType badge = BadgeType::None;
|
||||||
DocumentId emojiStatusId = 0;
|
QString emojiStatusId;
|
||||||
DocumentId emojiStatusInnerId = 0;
|
QString emojiStatusInnerId;
|
||||||
|
|
||||||
friend inline constexpr bool operator==(Content, Content) = default;
|
friend inline constexpr bool operator==(Content, Content) = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -302,10 +302,8 @@ Cover::Cover(
|
||||||
const auto details = peer->verifyDetails();
|
const auto details = peer->verifyDetails();
|
||||||
return Badge::Content{
|
return Badge::Content{
|
||||||
.badge = details ? BadgeType::Verified : BadgeType::None,
|
.badge = details ? BadgeType::Verified : BadgeType::None,
|
||||||
.emojiStatusId = details ? details->iconBgId.toULongLong() : 0,
|
.emojiStatusId = details ? details->iconBgId : QString(),
|
||||||
.emojiStatusInnerId = (details
|
.emojiStatusInnerId = details ? details->iconFgId : QString(),
|
||||||
? details->iconFgId.toULongLong()
|
|
||||||
: 0),
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,10 +197,6 @@ settingsInfoPhotoSkip: 7px;
|
||||||
settingsInfoNameSkip: -1px;
|
settingsInfoNameSkip: -1px;
|
||||||
settingsInfoUploadLeft: 6px;
|
settingsInfoUploadLeft: 6px;
|
||||||
settingsInfoPeerBadge: InfoPeerBadge {
|
settingsInfoPeerBadge: InfoPeerBadge {
|
||||||
verified: icon {
|
|
||||||
{ "dialogs/dialogs_verified_star", dialogsVerifiedIconBg },
|
|
||||||
{ "dialogs/dialogs_verified_check", dialogsVerifiedIconFg },
|
|
||||||
};
|
|
||||||
premium: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
|
premium: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
|
||||||
premiumFg: dialogsVerifiedIconBg;
|
premiumFg: dialogsVerifiedIconBg;
|
||||||
premiumInnerFg: dialogsVerifiedIconFg;
|
premiumInnerFg: dialogsVerifiedIconFg;
|
||||||
|
|