Use color index from API.

This commit is contained in:
John Preston 2023-10-16 13:52:08 +04:00
parent f90a010b84
commit 4b6107fa56
26 changed files with 282 additions and 149 deletions

View file

@ -202,8 +202,7 @@ void Userpic::createCache(Image *image) {
{
auto p = QPainter(&filled);
Ui::EmptyUserpic(
Ui::EmptyUserpic::UserpicColor(
Data::PeerColorIndex(_peer->id)),
Ui::EmptyUserpic::UserpicColor(_peer->colorIndex()),
_peer->name()
).paintCircle(p, 0, 0, size, size);
}

View file

@ -71,41 +71,42 @@ struct PeerUpdate {
FullInfo = (1ULL << 11),
Usernames = (1ULL << 12),
TranslationDisabled = (1ULL << 13),
Color = (1ULL << 14),
// For users
CanShareContact = (1ULL << 14),
IsContact = (1ULL << 15),
PhoneNumber = (1ULL << 16),
OnlineStatus = (1ULL << 17),
BotCommands = (1ULL << 18),
BotCanBeInvited = (1ULL << 19),
BotStartToken = (1ULL << 20),
CommonChats = (1ULL << 21),
HasCalls = (1ULL << 22),
SupportInfo = (1ULL << 23),
IsBot = (1ULL << 24),
EmojiStatus = (1ULL << 25),
StoriesState = (1ULL << 26),
CanShareContact = (1ULL << 15),
IsContact = (1ULL << 16),
PhoneNumber = (1ULL << 17),
OnlineStatus = (1ULL << 18),
BotCommands = (1ULL << 19),
BotCanBeInvited = (1ULL << 20),
BotStartToken = (1ULL << 21),
CommonChats = (1ULL << 22),
HasCalls = (1ULL << 23),
SupportInfo = (1ULL << 24),
IsBot = (1ULL << 25),
EmojiStatus = (1ULL << 26),
StoriesState = (1ULL << 27),
// For chats and channels
InviteLinks = (1ULL << 27),
Members = (1ULL << 28),
Admins = (1ULL << 29),
BannedUsers = (1ULL << 30),
Rights = (1ULL << 31),
PendingRequests = (1ULL << 32),
Reactions = (1ULL << 33),
InviteLinks = (1ULL << 28),
Members = (1ULL << 29),
Admins = (1ULL << 30),
BannedUsers = (1ULL << 31),
Rights = (1ULL << 32),
PendingRequests = (1ULL << 33),
Reactions = (1ULL << 34),
// For channels
ChannelAmIn = (1ULL << 34),
StickersSet = (1ULL << 35),
ChannelLinkedChat = (1ULL << 36),
ChannelLocation = (1ULL << 37),
Slowmode = (1ULL << 38),
GroupCall = (1ULL << 39),
ChannelAmIn = (1ULL << 35),
StickersSet = (1ULL << 36),
ChannelLinkedChat = (1ULL << 37),
ChannelLocation = (1ULL << 38),
Slowmode = (1ULL << 39),
GroupCall = (1ULL << 40),
// For iteration
LastUsedBit = (1ULL << 39),
LastUsedBit = (1ULL << 40),
};
using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; }

View file

@ -59,8 +59,8 @@ using UpdateFlag = Data::PeerUpdate::Flag;
namespace Data {
int PeerColorIndex(PeerId peerId) {
return Ui::EmptyUserpic::ColorIndex(peerId.value & PeerId::kChatTypeMask);
uint8 DecideColorIndex(PeerId peerId) {
return Ui::DecideColorIndex(peerId.value & PeerId::kChatTypeMask);
}
PeerId FakePeerIdForJustName(const QString &name) {
@ -230,7 +230,7 @@ not_null<Ui::EmptyUserpic*> PeerData::ensureEmptyUserpic() const {
if (!_userpicEmpty) {
const auto user = asUser();
_userpicEmpty = std::make_unique<Ui::EmptyUserpic>(
Ui::EmptyUserpic::UserpicColor(Data::PeerColorIndex(id)),
Ui::EmptyUserpic::UserpicColor(colorIndex()),
((user && user->isInaccessible())
? Ui::EmptyUserpic::InaccessibleName()
: name()));
@ -251,7 +251,7 @@ void PeerData::setUserpic(
const ImageLocation &location,
bool hasVideo) {
_userpicPhotoId = photoId;
_userpicHasVideo = hasVideo;
_userpicHasVideo = hasVideo ? 1 : 0;
_userpic.set(&session(), ImageWithLocation{ .location = location });
}
@ -389,6 +389,22 @@ QImage PeerData::generateUserpicImage(
return result;
}
ImageLocation PeerData::userpicLocation() const {
return _userpic.location();
}
bool PeerData::userpicPhotoUnknown() const {
return (_userpicPhotoId == kUnknownPhotoId);
}
PhotoId PeerData::userpicPhotoId() const {
return userpicPhotoUnknown() ? 0 : _userpicPhotoId;
}
bool PeerData::userpicHasVideo() const {
return _userpicHasVideo != 0;
}
Data::FileOrigin PeerData::userpicOrigin() const {
return Data::FileOriginPeerPhoto(id);
}
@ -428,7 +444,7 @@ void PeerData::setUserpicChecked(
bool hasVideo) {
if (_userpicPhotoId != photoId
|| _userpic.location() != location
|| _userpicHasVideo != hasVideo) {
|| _userpicHasVideo != (hasVideo ? 1 : 0)) {
const auto known = !userpicPhotoUnknown();
setUserpic(photoId, location, hasVideo);
session().changes().peerUpdated(this, UpdateFlag::Photo);
@ -818,6 +834,15 @@ QString PeerData::userName() const {
return QString();
}
bool PeerData::changeColorIndex(uint8 index) {
index %= Ui::kColorIndexCount;
if (_colorIndex == index) {
return false;
}
_colorIndex = index;
return true;
}
bool PeerData::isSelf() const {
if (const auto user = asUser()) {
return (user->flags() & UserDataFlag::Self);

View file

@ -39,7 +39,7 @@ class GroupCall;
struct ReactionId;
class WallPaper;
[[nodiscard]] int PeerColorIndex(PeerId peerId);
[[nodiscard]] uint8 DecideColorIndex(PeerId peerId);
// Must be used only for PeerColor-s.
[[nodiscard]] PeerId FakePeerIdForJustName(const QString &name);
@ -164,6 +164,11 @@ public:
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] Main::Account &account() const;
[[nodiscard]] uint8 colorIndex() const {
return _colorIndex;
}
bool changeColorIndex(uint8 index);
[[nodiscard]] bool isUser() const {
return peerIsUser(id);
}
@ -285,20 +290,12 @@ public:
Ui::PeerUserpicView &view,
int size,
std::optional<int> radius = {}) const;
[[nodiscard]] ImageLocation userpicLocation() const {
return _userpic.location();
}
[[nodiscard]] ImageLocation userpicLocation() const;
static constexpr auto kUnknownPhotoId = PhotoId(0xFFFFFFFFFFFFFFFFULL);
[[nodiscard]] bool userpicPhotoUnknown() const {
return (_userpicPhotoId == kUnknownPhotoId);
}
[[nodiscard]] PhotoId userpicPhotoId() const {
return userpicPhotoUnknown() ? 0 : _userpicPhotoId;
}
[[nodiscard]] bool userpicHasVideo() const {
return _userpicHasVideo;
}
[[nodiscard]] bool userpicPhotoUnknown() const;
[[nodiscard]] PhotoId userpicPhotoId() const;
[[nodiscard]] bool userpicHasVideo() const;
[[nodiscard]] Data::FileOrigin userpicOrigin() const;
[[nodiscard]] Data::FileOrigin userpicPhotoOrigin() const;
@ -460,14 +457,15 @@ private:
TimeId _ttlPeriod = 0;
QString _requestChatTitle;
TimeId _requestChatDate = 0;
Settings _settings = PeerSettings(PeerSetting::Unknown);
BlockStatus _blockStatus = BlockStatus::Unknown;
LoadedStatus _loadedStatus = LoadedStatus::Not;
TranslationFlag _translationFlag = TranslationFlag::Unknown;
bool _userpicHasVideo = false;
QString _requestChatTitle;
TimeId _requestChatDate = 0;
uint8 _colorIndex : 7 = 0;
uint8 _userpicHasVideo : 1 = 0;
QString _about;
QString _themeEmoticon;

View file

@ -705,6 +705,9 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
if (canShareThisContact != result->canShareThisContactFast()) {
flags |= UpdateFlag::CanShareContact;
}
if (result->changeColorIndex(uint8(data.vcolor().v))) {
flags |= UpdateFlag::Color;
}
});
if (minimal) {
@ -979,6 +982,9 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
if (wasCallNotEmpty != Data::ChannelHasActiveCall(channel)) {
flags |= UpdateFlag::GroupCall;
}
if (result->changeColorIndex(uint8(data.vcolor().v))) {
flags |= UpdateFlag::Color;
}
}, [&](const MTPDchannelForbidden &data) {
const auto channel = result->asChannel();

View file

@ -54,17 +54,16 @@ QString PrepareStoryFileName(
} // namespace
int PeerColorIndex(BareId bareId) {
const auto index = bareId % 7;
const int map[] = { 0, 7, 4, 1, 6, 3, 5 };
return map[index];
uint8 PeerColorIndex(BareId bareId) {
const uint8 map[] = { 0, 7, 4, 1, 6, 3, 5 };
return map[bareId % base::array_size(map)];
}
BareId PeerToBareId(PeerId peerId) {
return (peerId.value & PeerId::kChatTypeMask);
}
int PeerColorIndex(PeerId peerId) {
uint8 PeerColorIndex(PeerId peerId) {
return PeerColorIndex(PeerToBareId(peerId));
}
@ -78,7 +77,7 @@ BareId StringBarePeerId(const Utf8String &data) {
return result;
}
int ApplicationColorIndex(int applicationId) {
uint8 ApplicationColorIndex(int applicationId) {
static const auto official = std::map<int, int> {
{ 1, 0 }, // iOS
{ 7, 0 }, // iOS X
@ -767,6 +766,7 @@ ContactInfo ParseContactInfo(const MTPUser &data) {
auto result = ContactInfo();
data.match([&](const MTPDuser &data) {
result.userId = data.vid().v;
result.colorIndex = data.vcolor().v;
if (const auto firstName = data.vfirst_name()) {
result.firstName = ParseString(*firstName);
}
@ -778,15 +778,13 @@ ContactInfo ParseContactInfo(const MTPUser &data) {
}
}, [&](const MTPDuserEmpty &data) {
result.userId = data.vid().v;
result.colorIndex = PeerColorIndex(result.userId);
});
return result;
}
int ContactColorIndex(const ContactInfo &data) {
if (data.userId != 0) {
return PeerColorIndex(data.userId.bare);
}
return PeerColorIndex(StringBarePeerId(data.phoneNumber));
uint8 ContactColorIndex(const ContactInfo &data) {
return data.colorIndex;
}
PeerId User::id() const {
@ -798,6 +796,7 @@ User ParseUser(const MTPUser &data) {
result.info = ParseContactInfo(data);
data.match([&](const MTPDuser &data) {
result.bareId = data.vid().v;
result.colorIndex = data.vcolor().v;
if (const auto username = data.vusername()) {
result.username = ParseString(*username);
}
@ -852,6 +851,7 @@ Chat ParseChat(const MTPChat &data) {
result.input = MTP_inputPeerChat(MTP_long(result.bareId));
}, [&](const MTPDchannel &data) {
result.bareId = data.vid().v;
result.colorIndex = data.vcolor().v;
result.isBroadcast = data.is_broadcast();
result.isSupergroup = data.is_megagroup();
result.title = ParseString(data.vtitle());
@ -935,6 +935,15 @@ MTPInputPeer Peer::input() const {
Unexpected("Variant in Peer::id.");
}
uint8 Peer::colorIndex() const {
if (const auto user = this->user()) {
return user->colorIndex;
} else if (const auto chat = this->chat()) {
return chat->colorIndex;
}
Unexpected("Variant in Peer::colorIndex.");
}
std::map<PeerId, Peer> ParsePeersLists(
const MTPVector<MTPUser> &users,
const MTPVector<MTPChat> &chats) {
@ -1541,6 +1550,8 @@ ContactsList ParseContactsList(const MTPVector<MTPSavedContact> &data) {
info.lastName = ParseString(data.vlast_name());
info.phoneNumber = ParseString(data.vphone());
info.date = data.vdate().v;
info.colorIndex = PeerColorIndex(
StringBarePeerId(info.phoneNumber));
return info;
});
result.list.push_back(std::move(info));
@ -1758,6 +1769,7 @@ DialogsInfo ParseDialogsInfo(const MTPmessages_Dialogs &data) {
info.lastName = peer.user()
? peer.user()->info.lastName
: Utf8String();
info.colorIndex = peer.colorIndex();
info.input = peer.input();
info.migratedToChannelId = peer.chat()
? peer.chat()->migratedToChannelId

View file

@ -24,10 +24,10 @@ namespace Data {
using Utf8String = QByteArray;
int PeerColorIndex(BareId bareId);
uint8 PeerColorIndex(BareId bareId);
BareId PeerToBareId(PeerId peerId);
int PeerColorIndex(PeerId peerId);
int ApplicationColorIndex(int applicationId);
uint8 PeerColorIndex(PeerId peerId);
uint8 ApplicationColorIndex(int applicationId);
int DomainApplicationId(const Utf8String &data);
Utf8String ParseString(const MTPstring &data);
@ -108,12 +108,13 @@ struct ContactInfo {
Utf8String lastName;
Utf8String phoneNumber;
TimeId date = 0;
uint8 colorIndex = 0;
Utf8String name() const;
};
ContactInfo ParseContactInfo(const MTPUser &data);
int ContactColorIndex(const ContactInfo &data);
uint8 ContactColorIndex(const ContactInfo &data);
struct Photo {
uint64 id = 0;
@ -217,6 +218,7 @@ struct User {
BareId bareId = 0;
ContactInfo info;
Utf8String username;
uint8 colorIndex = 0;
bool isBot = false;
bool isSelf = false;
bool isReplies = false;
@ -236,6 +238,7 @@ struct Chat {
ChannelId migratedToChannelId = 0;
Utf8String title;
Utf8String username;
uint8 colorIndex = 0;
bool isBroadcast = false;
bool isSupergroup = false;
@ -249,6 +252,7 @@ struct Peer {
PeerId id() const;
Utf8String name() const;
MTPInputPeer input() const;
uint8 colorIndex() const;
const User *user() const;
const Chat *chat() const;
@ -746,6 +750,7 @@ struct DialogInfo {
int32 topMessageId = 0;
TimeId topMessageDate = 0;
PeerId peerId = 0;
uint8 colorIndex = 0;
MTPInputPeer migratedFromInput = MTP_inputPeerEmpty();
ChannelId migratedToChannelId = 0;

View file

@ -25,7 +25,7 @@ constexpr auto kPersonalUserpicSize = 90;
constexpr auto kEntryUserpicSize = 48;
constexpr auto kServiceMessagePhotoSize = 60;
constexpr auto kHistoryUserpicSize = 42;
constexpr auto kSavedMessagesColorIndex = 3;
constexpr auto kSavedMessagesColorIndex = uint8(3);
constexpr auto kJoinWithinSeconds = 900;
constexpr auto kPhotoMaxWidth = 520;
constexpr auto kPhotoMaxHeight = 520;
@ -351,7 +351,7 @@ QByteArray FormatTimeText(TimeId date) {
namespace details {
struct UserpicData {
int colorIndex = 0;
uint8 colorIndex = 0;
int pixelSize = 0;
QString imageLink;
QString largeLink;
@ -991,7 +991,7 @@ QByteArray HtmlWriter::Wrap::pushServiceMessage(
result.append(popTag());
if (photo) {
auto userpic = UserpicData();
userpic.colorIndex = Data::PeerColorIndex(dialog.peerId);
userpic.colorIndex = dialog.colorIndex;
userpic.firstName = dialog.name;
userpic.lastName = dialog.lastName;
userpic.pixelSize = kServiceMessagePhotoSize;
@ -2170,7 +2170,7 @@ Result HtmlWriter::start(
Result HtmlWriter::writePersonal(const Data::PersonalInfo &data) {
Expects(_summary != nullptr);
_selfColorIndex = Data::PeerColorIndex(data.user.info.userId);
_selfColorIndex = data.user.info.colorIndex;
if (_settings.types & Settings::Type::Userpics) {
_delayedPersonalInfo = std::make_unique<Data::PersonalInfo>(data);
return Result::Success();

View file

@ -150,7 +150,7 @@ private:
bool _summaryNeedDivider = false;
bool _haveSections = false;
int _selfColorIndex = 0;
uint8 _selfColorIndex = 0;
std::unique_ptr<Data::PersonalInfo> _delayedPersonalInfo;
int _userpicsCount = 0;

View file

@ -110,9 +110,9 @@ void HistoryMessageVia::resize(int32 availw) const {
HiddenSenderInfo::HiddenSenderInfo(const QString &name, bool external)
: name(name)
, colorPeerId(Data::FakePeerIdForJustName(name))
, colorIndex(Data::DecideColorIndex(Data::FakePeerIdForJustName(name)))
, emptyUserpic(
Ui::EmptyUserpic::UserpicColor(Data::PeerColorIndex(colorPeerId)),
Ui::EmptyUserpic::UserpicColor(colorIndex),
(external
? Ui::EmptyUserpic::ExternalName()
: name)) {
@ -400,13 +400,13 @@ bool HistoryMessageReply::updateData(
if (resolvedMessage) {
const auto peer = resolvedMessage->history()->peer;
_colorKey = (!holder->out()
_colorIndexPlusOne = (!holder->out()
&& (peer->isMegagroup() || peer->isChat())
&& resolvedMessage->from()->isUser())
? resolvedMessage->from()->id
: PeerId();
? (resolvedMessage->from()->colorIndex() + 1)
: uint8();
} else if (!resolvedStory) {
_unavailable = true;
_unavailable = 1;
}
const auto media = resolvedMessage
@ -419,9 +419,9 @@ bool HistoryMessageReply::updateData(
}
} else if (force) {
if (_fields.messageId || _fields.storyId) {
_unavailable = true;
_unavailable = 1;
}
_colorKey = 0;
_colorIndexPlusOne = 0;
spoiler = nullptr;
}
if (force) {
@ -502,7 +502,7 @@ void HistoryMessageReply::clearData(not_null<HistoryItem*> holder) {
resolvedStory.get());
resolvedStory = nullptr;
}
_unavailable = true;
_unavailable = 1;
refreshReplyToMedia();
}
@ -663,8 +663,8 @@ void HistoryMessageReply::paint(
const auto outerWidth = w + 2 * x;
const auto &bar = !inBubble
? st->msgImgReplyBarColor()
: _colorKey
? HistoryView::FromNameFg(context, _colorKey)
: _colorIndexPlusOne
? HistoryView::FromNameFg(context, _colorIndexPlusOne - 1)
: stm->msgReplyBarColor;
const auto rbar = style::rtlrect(
x + st::msgReplyBarPos.x(),
@ -735,8 +735,10 @@ void HistoryMessageReply::paint(
if (w > st::msgReplyBarSkip + previewSkip) {
p.setPen(!inBubble
? st->msgImgReplyBarColor()
: _colorKey
? HistoryView::FromNameFg(context, _colorKey)
: _colorIndexPlusOne
? HistoryView::FromNameFg(
context,
_colorIndexPlusOne - 1)
: stm->msgServiceFg);
_name.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top(), w - st::msgReplyBarSkip - previewSkip, w + 2 * x);
if (originalVia && w > st::msgReplyBarSkip + previewSkip + _name.maxWidth() + st::msgServiceFont->spacew) {

View file

@ -90,7 +90,7 @@ public:
QString name;
QString firstName;
QString lastName;
PeerId colorPeerId = 0;
uint8 colorIndex = 0;
Ui::EmptyUserpic emptyUserpic;
mutable Data::CloudImage customUserpic;
@ -291,9 +291,6 @@ struct HistoryMessageReply
bool inBubble) const;
void unloadPersistentAnimation();
[[nodiscard]] PeerId colorKey() const {
return _colorKey;
}
[[nodiscard]] PeerId externalPeerId() const {
return _fields.externalPeerId;
}
@ -337,14 +334,14 @@ struct HistoryMessageReply
private:
ReplyFields _fields;
PeerId _colorKey = 0;
ClickHandlerPtr _link;
mutable Ui::Text::String _name;
mutable Ui::Text::String _text;
mutable PeerData *_externalSender = nullptr;
mutable int _maxWidth = 0;
mutable int _nameVersion = 0;
bool _unavailable = false;
uint8 _colorIndexPlusOne : 7 = 0;
uint8 _unavailable : 1 = 0;
};

View file

@ -368,33 +368,8 @@ QString FastReplyText() {
style::color FromNameFg(
const Ui::ChatPaintContext &context,
PeerId peerId) {
const auto st = context.st;
if (context.selected()) {
const style::color colors[] = {
st->historyPeer1NameFgSelected(),
st->historyPeer2NameFgSelected(),
st->historyPeer3NameFgSelected(),
st->historyPeer4NameFgSelected(),
st->historyPeer5NameFgSelected(),
st->historyPeer6NameFgSelected(),
st->historyPeer7NameFgSelected(),
st->historyPeer8NameFgSelected(),
};
return colors[Data::PeerColorIndex(peerId)];
} else {
const style::color colors[] = {
st->historyPeer1NameFg(),
st->historyPeer2NameFg(),
st->historyPeer3NameFg(),
st->historyPeer4NameFg(),
st->historyPeer5NameFg(),
st->historyPeer6NameFg(),
st->historyPeer7NameFg(),
st->historyPeer8NameFg(),
};
return colors[Data::PeerColorIndex(peerId)];
}
uint8 colorIndex) {
return Ui::FromNameFg(context.st, context.selected(), colorIndex);
}
struct Message::CommentsButton {
@ -1355,7 +1330,7 @@ void Message::paintFromName(
const auto service = (context.outbg || item->isPost());
const auto st = context.st;
const auto nameFg = !service
? FromNameFg(context, from ? from->id : info->colorPeerId)
? FromNameFg(context, from ? from->colorIndex() : info->colorIndex)
: item->isSponsored()
? st->boxTextFgGood()
: stm->msgServiceFg;
@ -1630,7 +1605,7 @@ void Message::paintText(
.availableWidth = trect.width(),
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -58,7 +58,7 @@ struct BottomRippleMask {
[[nodiscard]] style::color FromNameFg(
const Ui::ChatPaintContext &context,
PeerId peerId);
uint8 colorIndex);
class Message final : public Element {
public:

View file

@ -122,7 +122,7 @@ QSize Contact::countOptimalSize() {
} else {
const auto full = _name.toString();
_photoEmpty = std::make_unique<Ui::EmptyUserpic>(
Ui::EmptyUserpic::UserpicColor(Data::PeerColorIndex(_userId
Ui::EmptyUserpic::UserpicColor(Data::DecideColorIndex(_userId
? peerFromUser(_userId)
: Data::FakePeerIdForJustName(full))),
full);

View file

@ -749,7 +749,7 @@ void Document::draw(
.availableWidth = captionw,
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -236,7 +236,7 @@ void ExtendedPreview::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw,
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -710,7 +710,7 @@ void Gif::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw,
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -368,7 +368,7 @@ void GroupedMedia::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw,
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -406,7 +406,7 @@ void Photo::draw(Painter &p, const PaintContext &context) const {
.availableWidth = captionw,
.palette = &stm->textPalette,
.pre = stm->preCache.get(),
.blockquote = stm->blockquoteCache.get(),
.blockquote = stm->quoteCache.get(),
.colors = context.st->highlightColors(),
.spoiler = Ui::Text::DefaultSpoilerCache(),
.now = context.now,

View file

@ -161,7 +161,8 @@ QImage *ItemBase::getResultThumb(Data::FileOrigin origin) const {
QPixmap ItemBase::getResultContactAvatar(int width, int height) const {
if (_result->_type == Result::Type::Contact) {
auto result = Ui::EmptyUserpic(
Ui::EmptyUserpic::UserpicColor(BareId(qHash(_result->_id))),
Ui::EmptyUserpic::UserpicColor(Ui::EmptyUserpic::ColorIndex(
BareId(qHash(_result->_id)))),
_result->getLayoutTitle()
).generate(width);
if (result.height() != height * cIntRetinaFactor()) {

View file

@ -25,7 +25,7 @@ void EnsureCorners(
const style::color &color,
const style::color *shadow = nullptr) {
if (corners.p[0].isNull()) {
corners = Ui::PrepareCornerPixmaps(radius, color, shadow);
corners = PrepareCornerPixmaps(radius, color, shadow);
}
}
@ -482,7 +482,7 @@ void ChatStyle::applyAdjustedServiceBg(QColor serviceBg) {
msgServiceBg().set(uchar(r), uchar(g), uchar(b), uchar(a));
}
std::span<Ui::Text::SpecialColor> ChatStyle::highlightColors() const {
std::span<Text::SpecialColor> ChatStyle::highlightColors() const {
if (_highlightColors.empty()) {
const auto push = [&](const style::color &color) {
_highlightColors.push_back({ &color->p, &color->p });
@ -523,7 +523,8 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
for (auto &style : _messageStyles) {
style.msgBgCornersSmall = {};
style.msgBgCornersLarge = {};
style.blockquoteCache = nullptr;
style.quoteCache = nullptr;
style.replyCache = nullptr;
style.preCache = nullptr;
}
for (auto &style : _imageStyles) {
@ -560,7 +561,7 @@ const CornersPixmaps &ChatStyle::serviceBgCornersNormal() const {
const CornersPixmaps &ChatStyle::serviceBgCornersInverted() const {
if (_serviceBgCornersInverted.p[0].isNull()) {
_serviceBgCornersInverted = Ui::PrepareInvertedCornerPixmaps(
_serviceBgCornersInverted = PrepareInvertedCornerPixmaps(
HistoryServiceMsgInvertedRadius(),
msgServiceBg());
}
@ -580,12 +581,12 @@ const MessageStyle &ChatStyle::messageStyle(bool outbg, bool selected) const {
result.msgBg,
&result.msgShadow);
EnsureBlockquoteCache(
result.blockquoteCache,
result.replyCache,
result.msgReplyBarColor);
const auto preBgOverride = [&] {
const auto withBg = [&](const QColor &color) {
return Ui::CountContrast(windowBg()->c, color);
return CountContrast(windowBg()->c, color);
};
const auto dark = (withBg({ 0, 0, 0 }) < withBg({ 255, 255, 255 }));
return dark ? QColor(0, 0, 0, 192) : std::optional<QColor>();
@ -621,9 +622,44 @@ const MessageImageStyle &ChatStyle::imageStyle(bool selected) const {
result.msgShadowCornersLarge,
BubbleRadiusLarge(),
result.msgShadow);
return result;
}
not_null<Text::QuotePaintCache*> ChatStyle::serviceQuoteCache() const {
EnsureBlockquoteCache(_serviceQuoteCache, msgServiceFg());
return _serviceQuoteCache.get();
}
not_null<Text::QuotePaintCache*> ChatStyle::serviceReplyCache() const {
EnsureBlockquoteCache(_serviceReplyCache, msgServiceFg());
return _serviceReplyCache.get();
}
not_null<Text::QuotePaintCache*> ChatStyle::coloredQuoteCache(
bool selected,
uint8 colorIndex) const {
return coloredCache(_coloredQuoteCaches, selected, colorIndex);
}
not_null<Text::QuotePaintCache*> ChatStyle::coloredReplyCache(
bool selected,
uint8 colorIndex) const {
return coloredCache(_coloredReplyCaches, selected, colorIndex);
}
not_null<Text::QuotePaintCache*> ChatStyle::coloredCache(
ColoredQuotePaintCaches &caches,
bool selected,
uint8 colorIndex) const {
Expects(colorIndex >= 0 && colorIndex < kColorIndexCount);
const auto shift = (selected ? kColorIndexCount : 0);
auto &cache = caches[shift + colorIndex];
EnsureBlockquoteCache(cache, FromNameFg(this, selected, colorIndex));
return cache.get();
}
const CornersPixmaps &ChatStyle::msgBotKbOverBgAddCornersSmall() const {
EnsureCorners(
_msgBotKbOverBgAddCornersSmall,
@ -751,6 +787,50 @@ void ChatStyle::make(
make(imageSelected().*my, originalSelected);
}
uint8 DecideColorIndex(uint64 id) {
return id % kColorIndexCount;
}
uint8 ColorIndexToPaletteIndex(uint8 colorIndex) {
Expects(colorIndex >= 0 && colorIndex < kColorIndexCount);
const int8 map[] = { 0, 7, 4, 1, 6, 3, 5 };
return map[colorIndex];
}
style::color FromNameFg(
not_null<const ChatStyle*> st,
bool selected,
uint8 colorIndex) {
Expects(colorIndex >= 0 && colorIndex < kColorIndexCount);
if (selected) {
const style::color colors[] = {
st->historyPeer1NameFgSelected(),
st->historyPeer2NameFgSelected(),
st->historyPeer3NameFgSelected(),
st->historyPeer4NameFgSelected(),
st->historyPeer5NameFgSelected(),
st->historyPeer6NameFgSelected(),
st->historyPeer7NameFgSelected(),
st->historyPeer8NameFgSelected(),
};
return colors[ColorIndexToPaletteIndex(colorIndex)];
} else {
const style::color colors[] = {
st->historyPeer1NameFg(),
st->historyPeer2NameFg(),
st->historyPeer3NameFg(),
st->historyPeer4NameFg(),
st->historyPeer5NameFg(),
st->historyPeer6NameFg(),
st->historyPeer7NameFg(),
st->historyPeer8NameFg(),
};
return colors[ColorIndexToPaletteIndex(colorIndex)];
}
}
void FillComplexOverlayRect(
QPainter &p,
QRect rect,

View file

@ -27,6 +27,8 @@ class ChatTheme;
class ChatStyle;
struct BubblePattern;
inline constexpr auto kColorIndexCount = uint8(7);
struct MessageStyle {
CornersPixmaps msgBgCornersSmall;
CornersPixmaps msgBgCornersLarge;
@ -76,9 +78,9 @@ struct MessageStyle {
style::icon historyPollChoiceRight = { Qt::Uninitialized };
style::icon historyTranscribeIcon = { Qt::Uninitialized };
style::icon historyTranscribeHide = { Qt::Uninitialized };
std::unique_ptr<Text::QuotePaintCache> blockquoteCache;
std::unique_ptr<Text::QuotePaintCache> quoteCache;
std::unique_ptr<Text::QuotePaintCache> replyCache;
std::unique_ptr<Text::QuotePaintCache> preCache;
};
struct MessageImageStyle {
@ -170,7 +172,7 @@ public:
void applyCustomPalette(const style::palette *palette);
void applyAdjustedServiceBg(QColor serviceBg);
[[nodiscard]] std::span<Ui::Text::SpecialColor> highlightColors() const;
[[nodiscard]] std::span<Text::SpecialColor> highlightColors() const;
[[nodiscard]] rpl::producer<> paletteChanged() const {
return _paletteChanged.events();
@ -200,6 +202,17 @@ public:
bool selected) const;
[[nodiscard]] const MessageImageStyle &imageStyle(bool selected) const;
[[nodiscard]] auto serviceQuoteCache() const
-> not_null<Text::QuotePaintCache*>;
[[nodiscard]] auto serviceReplyCache() const
-> not_null<Text::QuotePaintCache*>;
[[nodiscard]] not_null<Text::QuotePaintCache*> coloredQuoteCache(
bool selected,
uint8 colorIndex) const;
[[nodiscard]] not_null<Text::QuotePaintCache*> coloredReplyCache(
bool selected,
uint8 colorIndex) const;
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersSmall() const;
[[nodiscard]] const CornersPixmaps &msgBotKbOverBgAddCornersLarge() const;
[[nodiscard]] const CornersPixmaps &msgSelectOverlayCorners(
@ -285,8 +298,16 @@ public:
}
private:
using ColoredQuotePaintCaches = std::array<
std::unique_ptr<Text::QuotePaintCache>,
kColorIndexCount * 2>;
void assignPalette(not_null<const style::palette*> palette);
[[nodiscard]] not_null<Text::QuotePaintCache*> coloredCache(
ColoredQuotePaintCaches &caches,
bool selected,
uint8 colorIndex) const;
void make(style::color &my, const style::color &original) const;
void make(style::icon &my, const style::icon &original) const;
void make(
@ -336,7 +357,11 @@ private:
mutable CornersPixmaps _msgSelectOverlayCorners[
int(CachedCornerRadius::kCount)];
mutable std::vector<Ui::Text::SpecialColor> _highlightColors;
mutable std::vector<Text::SpecialColor> _highlightColors;
mutable std::unique_ptr<Text::QuotePaintCache> _serviceQuoteCache;
mutable std::unique_ptr<Text::QuotePaintCache> _serviceReplyCache;
mutable ColoredQuotePaintCaches _coloredQuoteCaches;
mutable ColoredQuotePaintCaches _coloredReplyCaches;
style::TextPalette _historyPsaForwardPalette;
style::TextPalette _imgReplyTextPalette;
@ -371,6 +396,14 @@ private:
};
[[nodiscard]] uint8 DecideColorIndex(uint64 id);
[[nodiscard]] uint8 ColorIndexToPaletteIndex(uint8 colorIndex);
[[nodiscard]] style::color FromNameFg(
not_null<const ChatStyle*> st,
bool selected,
uint8 colorIndex);
void FillComplexOverlayRect(
QPainter &p,
QRect rect,

View file

@ -1050,8 +1050,7 @@ void UserpicButton::prepareUserpicPixmap() {
} else {
const auto user = _peer->asUser();
auto empty = Ui::EmptyUserpic(
Ui::EmptyUserpic::UserpicColor(
Data::PeerColorIndex(_peer->id)),
Ui::EmptyUserpic::UserpicColor(_peer->colorIndex()),
((user && user->isInaccessible())
? Ui::EmptyUserpic::InaccessibleName()
: _peer->name()));

View file

@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/empty_userpic.h"
#include "ui/emoji_config.h"
#include "ui/chat/chat_style.h"
#include "ui/effects/animation_value.h"
#include "ui/emoji_config.h"
#include "ui/painter.h"
#include "ui/ui_utility.h"
#include "styles/style_chat.h"
@ -221,13 +222,11 @@ QString EmptyUserpic::InaccessibleName() {
return QChar(0) + u"inaccessible"_q;
}
int EmptyUserpic::ColorIndex(uint64 id) {
const auto index = id % 7;
const int map[] = { 0, 7, 4, 1, 6, 3, 5 };
return map[index];
uint8 EmptyUserpic::ColorIndex(uint64 id) {
return DecideColorIndex(id);
}
EmptyUserpic::BgColors EmptyUserpic::UserpicColor(int id) {
EmptyUserpic::BgColors EmptyUserpic::UserpicColor(uint8 colorIndex) {
const EmptyUserpic::BgColors colors[] = {
{ st::historyPeer1UserpicBg, st::historyPeer1UserpicBg2 },
{ st::historyPeer2UserpicBg, st::historyPeer2UserpicBg2 },
@ -238,7 +237,7 @@ EmptyUserpic::BgColors EmptyUserpic::UserpicColor(int id) {
{ st::historyPeer7UserpicBg, st::historyPeer7UserpicBg2 },
{ st::historyPeer8UserpicBg, st::historyPeer8UserpicBg2 },
};
return colors[id];
return colors[ColorIndexToPaletteIndex(colorIndex)];
}
void EmptyUserpic::paint(

View file

@ -18,8 +18,9 @@ public:
const style::color color2;
};
[[nodiscard]] static int ColorIndex(uint64 id);
[[nodiscard]] static EmptyUserpic::BgColors UserpicColor(int id);
[[nodiscard]] static uint8 ColorIndex(uint64 id);
[[nodiscard]] static EmptyUserpic::BgColors UserpicColor(
uint8 colorIndex);
[[nodiscard]] static QString ExternalName();
[[nodiscard]] static QString InaccessibleName();

View file

@ -986,7 +986,7 @@ void Generator::paintService(QString text) {
}
void Generator::paintUserpic(int x, int y, Row::Type type, int index, QString letters) {
const auto colorIndex = Ui::EmptyUserpic::ColorIndex(index);
const auto colorIndex = Ui::DecideColorIndex(index);
const auto colors = Ui::EmptyUserpic::UserpicColor(colorIndex);
auto userpic = Ui::EmptyUserpic(colors, letters);