Show emoji statuses in channels.

This commit is contained in:
John Preston 2023-12-16 22:43:35 +00:00
parent 6aaf841a73
commit 805a5d73b6
12 changed files with 81 additions and 67 deletions

View File

@ -104,19 +104,19 @@ rpl::producer<> EmojiStatuses::defaultUpdates() const {
}
void EmojiStatuses::registerAutomaticClear(
not_null<UserData*> user,
not_null<PeerData*> peer,
TimeId until) {
if (!until) {
_clearing.remove(user);
_clearing.remove(peer);
if (_clearing.empty()) {
_clearingTimer.cancel();
}
} else if (auto &already = _clearing[user]; already != until) {
} else if (auto &already = _clearing[peer]; already != until) {
already = until;
const auto i = ranges::min_element(_clearing, {}, [](auto &&pair) {
return pair.second;
});
if (i->first == user) {
if (i->first == peer) {
const auto now = base::unixtime::now();
if (now < until) {
processClearingIn(until - now);

View File

@ -51,7 +51,7 @@ public:
void set(DocumentId id, TimeId until = 0);
[[nodiscard]] bool setting() const;
void registerAutomaticClear(not_null<UserData*> user, TimeId until);
void registerAutomaticClear(not_null<PeerData*> peer, TimeId until);
using Groups = std::vector<Ui::EmojiGroup>;
[[nodiscard]] rpl::producer<Groups> emojiGroupsValue() const;
@ -102,7 +102,7 @@ private:
mtpRequestId _sentRequestId = 0;
base::flat_map<not_null<UserData*>, TimeId> _clearing;
base::flat_map<not_null<PeerData*>, TimeId> _clearing;
base::Timer _clearingTimer;
GroupsType _emojiGroups;

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_chat_participant_status.h"
#include "data/data_channel.h"
#include "data/data_changes.h"
#include "data/data_emoji_statuses.h"
#include "data/data_message_reaction_id.h"
#include "data/data_photo.h"
#include "data/data_folder.h"
@ -926,6 +927,24 @@ bool PeerData::changeBackgroundEmojiId(DocumentId id) {
_backgroundEmojiId = id;
return true;
}
void PeerData::setEmojiStatus(const MTPEmojiStatus &status) {
const auto parsed = Data::ParseEmojiStatus(status);
setEmojiStatus(parsed.id, parsed.until);
}
void PeerData::setEmojiStatus(DocumentId emojiStatusId, TimeId until) {
if (_emojiStatusId != emojiStatusId) {
_emojiStatusId = emojiStatusId;
session().changes().peerUpdated(this, UpdateFlag::EmojiStatus);
}
owner().emojiStatuses().registerAutomaticClear(this, until);
}
DocumentId PeerData::emojiStatusId() const {
return _emojiStatusId;
}
bool PeerData::isSelf() const {
if (const auto user = asUser()) {
return (user->flags() & UserDataFlag::Self);

View File

@ -178,6 +178,10 @@ public:
[[nodiscard]] DocumentId backgroundEmojiId() const;
bool changeBackgroundEmojiId(DocumentId id);
void setEmojiStatus(const MTPEmojiStatus &status);
void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0);
[[nodiscard]] DocumentId emojiStatusId() const;
[[nodiscard]] bool isUser() const {
return peerIsUser(id);
}
@ -466,6 +470,7 @@ private:
base::flat_set<QString> _nameWords; // for filtering
base::flat_set<QChar> _nameFirstLetters;
DocumentId _emojiStatusId = 0;
uint64 _backgroundEmojiId = 0;
crl::time _lastFullUpdate = 0;

View File

@ -854,6 +854,11 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
channel->setDefaultRestrictions(ChatRestrictions());
}
if (const auto &status = data.vemoji_status()) {
channel->setEmojiStatus(*status);
} else {
channel->setEmojiStatus(0);
}
if (minimal) {
if (channel->input.type() == mtpc_inputPeerEmpty
|| channel->inputChannel.type() == mtpc_inputChannelEmpty) {

View File

@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer_bot_command.h"
#include "data/data_photo.h"
#include "data/data_stories.h"
#include "data/data_emoji_statuses.h"
#include "data/data_wall_paper.h"
#include "data/notify/data_notify_settings.h"
#include "history/history.h"
@ -73,23 +72,6 @@ void UserData::setPhoto(const MTPUserProfilePhoto &photo) {
});
}
void UserData::setEmojiStatus(const MTPEmojiStatus &status) {
const auto parsed = Data::ParseEmojiStatus(status);
setEmojiStatus(parsed.id, parsed.until);
}
void UserData::setEmojiStatus(DocumentId emojiStatusId, TimeId until) {
if (_emojiStatusId != emojiStatusId) {
_emojiStatusId = emojiStatusId;
session().changes().peerUpdated(this, UpdateFlag::EmojiStatus);
}
owner().emojiStatuses().registerAutomaticClear(this, until);
}
DocumentId UserData::emojiStatusId() const {
return _emojiStatusId;
}
auto UserData::unavailableReasons() const
-> const std::vector<Data::UnavailableReason> & {
return _unavailableReasons;

View File

@ -76,7 +76,6 @@ public:
UserData(not_null<Data::Session*> owner, PeerId id);
void setPhoto(const MTPUserProfilePhoto &photo);
void setEmojiStatus(const MTPEmojiStatus &status);
void setName(
const QString &newFirstName,
@ -85,9 +84,6 @@ public:
const QString &newUsername);
void setUsernames(const Data::Usernames &newUsernames);
void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0);
[[nodiscard]] DocumentId emojiStatusId() const;
void setUsername(const QString &username);
void setPhone(const QString &newPhone);
void setBotInfoVersion(int version);
@ -199,8 +195,6 @@ private:
static constexpr auto kInaccessibleAccessHashOld
= 0xFFFFFFFFFFFFFFFFULL;
DocumentId _emojiStatusId = 0;
};
namespace Data {

View File

@ -98,16 +98,15 @@ namespace {
[[nodiscard]] rpl::producer<TextWithEntities> PeerCustomStatus(
not_null<PeerData*> peer) {
const auto user = peer->asUser();
if (!user) {
if (peer->isChat()) {
return rpl::single(TextWithEntities());
}
const auto owner = &user->owner();
return user->session().changes().peerFlagsValue(
user,
const auto owner = &peer->owner();
return peer->session().changes().peerFlagsValue(
peer,
Data::PeerUpdate::Flag::EmojiStatus
) | rpl::map([=] {
const auto id = user->emojiStatusId();
const auto id = peer->emojiStatusId();
return id
? ResolveIsCustom(owner, id)
: rpl::single(TextWithEntities());

View File

@ -1410,13 +1410,12 @@ void Message::paintFromName(
const auto y = trect.top();
auto color = nameFg;
color.setAlpha(115);
const auto user = from->asUser();
const auto id = user ? user->emojiStatusId() : 0;
const auto id = from ? from->emojiStatusId() : 0;
if (_fromNameStatus->id != id) {
const auto that = const_cast<Message*>(this);
_fromNameStatus->custom = id
? std::make_unique<Ui::Text::LimitedLoopsEmoji>(
user->owner().customEmojiManager().create(
history()->owner().customEmojiManager().create(
id,
[=] { that->customEmojiRepaint(); }),
kPlayStatusLimit)
@ -3017,7 +3016,8 @@ void Message::validateFromNameText(PeerData *from) const {
from->name(),
Ui::NameTextOptions());
}
if (from->isPremium()) {
if (from->isPremium()
|| (from->isChannel() && from != history()->peer)) {
if (!_fromNameStatus) {
_fromNameStatus = std::make_unique<FromNameStatus>();
const auto size = st::emojiSize;

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/stickers/data_custom_emoji.h"
#include "info/profile/info_profile_values.h"
#include "info/profile/info_profile_emoji_status_panel.h"
@ -24,10 +25,16 @@ namespace {
[[nodiscard]] rpl::producer<Badge::Content> ContentForPeer(
not_null<PeerData*> peer) {
const auto statusOnlyForPremium = peer->isUser();
return rpl::combine(
BadgeValue(peer),
EmojiStatusIdValue(peer)
) | rpl::map([=](BadgeType badge, DocumentId emojiStatusId) {
if (statusOnlyForPremium) {
emojiStatusId = 0;
} else if (emojiStatusId && badge == BadgeType::None) {
badge = BadgeType::Premium;
}
return Badge::Content{ badge, emojiStatusId };
});
}
@ -91,9 +98,6 @@ void Badge::setContent(Content content) {
if (!(_allowed & content.badge)) {
content.badge = BadgeType::None;
}
if (content.badge != BadgeType::Premium) {
content.emojiStatusId = 0;
}
if (_content == content) {
return;
}

View File

@ -609,15 +609,14 @@ rpl::producer<BadgeType> BadgeValue(not_null<PeerData*> peer) {
}
rpl::producer<DocumentId> EmojiStatusIdValue(not_null<PeerData*> peer) {
if (const auto user = peer->asUser()) {
return user->session().changes().peerFlagsValue(
peer,
Data::PeerUpdate::Flag::EmojiStatus
) | rpl::map([=] { return user->emojiStatusId(); });
if (peer->isChat()) {
return rpl::single(DocumentId(0));
}
return rpl::single(DocumentId(0));
return peer->session().changes().peerFlagsValue(
peer,
Data::PeerUpdate::Flag::EmojiStatus
) | rpl::map([=] { return peer->emojiStatusId(); });
}
} // namespace Profile
} // namespace Info

View File

@ -132,7 +132,7 @@ int PeerBadge::drawGetWidth(
Expects(descriptor.customEmojiRepaint != nullptr);
const auto peer = descriptor.peer;
if ((peer->isScam() || peer->isFake()) && descriptor.scam) {
if (descriptor.scam && (peer->isScam() || peer->isFake())) {
const auto phrase = peer->isScam()
? tr::lng_scam_badge(tr::now)
: tr::lng_fake_badge(tr::now);
@ -159,27 +159,15 @@ int PeerBadge::drawGetWidth(
phrase,
phraseWidth);
return st::dialogsScamSkip + width;
} else if (peer->isVerified() && descriptor.verified) {
const auto iconw = descriptor.verified->width();
descriptor.verified->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
} else if (peer->isPremium()
&& descriptor.premium
} else if (descriptor.premium
&& peer->emojiStatusId()
&& (peer->isPremium() || peer->isChannel())
&& peer->session().premiumBadgesShown()) {
const auto id = peer->isUser() ? peer->asUser()->emojiStatusId() : 0;
const auto id = peer->emojiStatusId();
const auto iconw = descriptor.premium->width();
const auto iconx = rectForName.x()
+ qMin(nameWidth, rectForName.width() - iconw);
const auto icony = rectForName.y();
if (!id) {
_emojiStatus = nullptr;
descriptor.premium->paint(p, iconx, icony, outerWidth);
return iconw;
}
if (!_emojiStatus) {
_emojiStatus = std::make_unique<EmojiStatus>();
const auto size = st::emojiSize;
@ -205,6 +193,25 @@ int PeerBadge::drawGetWidth(
.paused = descriptor.paused || On(PowerSaving::kEmojiStatus),
});
return iconw - 4 * _emojiStatus->skip;
} else if (descriptor.verified && peer->isVerified()) {
const auto iconw = descriptor.verified->width();
descriptor.verified->paint(
p,
rectForName.x() + qMin(nameWidth, rectForName.width() - iconw),
rectForName.y(),
outerWidth);
return iconw;
} else if (descriptor.premium
&& peer->isPremium()
&& peer->session().premiumBadgesShown()) {
const auto id = peer->isChat() ? 0 : peer->emojiStatusId();
const auto iconw = descriptor.premium->width();
const auto iconx = rectForName.x()
+ qMin(nameWidth, rectForName.width() - iconw);
const auto icony = rectForName.y();
_emojiStatus = nullptr;
descriptor.premium->paint(p, iconx, icony, outerWidth);
return iconw;
}
return 0;
}