From 805a5d73b6180bd9226d7d44bc6db15a57d2660c Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 16 Dec 2023 22:43:35 +0000 Subject: [PATCH] Show emoji statuses in channels. --- .../SourceFiles/data/data_emoji_statuses.cpp | 8 ++-- .../SourceFiles/data/data_emoji_statuses.h | 4 +- Telegram/SourceFiles/data/data_peer.cpp | 19 +++++++++ Telegram/SourceFiles/data/data_peer.h | 5 +++ Telegram/SourceFiles/data/data_session.cpp | 5 +++ Telegram/SourceFiles/data/data_user.cpp | 18 -------- Telegram/SourceFiles/data/data_user.h | 6 --- .../view/history_view_contact_status.cpp | 11 +++-- .../history/view/history_view_message.cpp | 8 ++-- .../info/profile/info_profile_badge.cpp | 10 +++-- .../info/profile/info_profile_values.cpp | 13 +++--- Telegram/SourceFiles/ui/unread_badge.cpp | 41 +++++++++++-------- 12 files changed, 81 insertions(+), 67 deletions(-) diff --git a/Telegram/SourceFiles/data/data_emoji_statuses.cpp b/Telegram/SourceFiles/data/data_emoji_statuses.cpp index a394edc0cc..961fcde83a 100644 --- a/Telegram/SourceFiles/data/data_emoji_statuses.cpp +++ b/Telegram/SourceFiles/data/data_emoji_statuses.cpp @@ -104,19 +104,19 @@ rpl::producer<> EmojiStatuses::defaultUpdates() const { } void EmojiStatuses::registerAutomaticClear( - not_null user, + not_null 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); diff --git a/Telegram/SourceFiles/data/data_emoji_statuses.h b/Telegram/SourceFiles/data/data_emoji_statuses.h index 29bd8491c4..cf0e54d767 100644 --- a/Telegram/SourceFiles/data/data_emoji_statuses.h +++ b/Telegram/SourceFiles/data/data_emoji_statuses.h @@ -51,7 +51,7 @@ public: void set(DocumentId id, TimeId until = 0); [[nodiscard]] bool setting() const; - void registerAutomaticClear(not_null user, TimeId until); + void registerAutomaticClear(not_null peer, TimeId until); using Groups = std::vector; [[nodiscard]] rpl::producer emojiGroupsValue() const; @@ -102,7 +102,7 @@ private: mtpRequestId _sentRequestId = 0; - base::flat_map, TimeId> _clearing; + base::flat_map, TimeId> _clearing; base::Timer _clearingTimer; GroupsType _emojiGroups; diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 0f34729164..746407a5f1 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -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); diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 1ff2676d72..8f553f9dba 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -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 _nameWords; // for filtering base::flat_set _nameFirstLetters; + DocumentId _emojiStatusId = 0; uint64 _backgroundEmojiId = 0; crl::time _lastFullUpdate = 0; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 342308c8cc..eaea5ba615 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -854,6 +854,11 @@ not_null 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) { diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 33dd42ca50..b90da3934d 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -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 & { return _unavailableReasons; diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index 96811051ee..3286612605 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -76,7 +76,6 @@ public: UserData(not_null 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 { diff --git a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp index dffcdde954..85985a49ee 100644 --- a/Telegram/SourceFiles/history/view/history_view_contact_status.cpp +++ b/Telegram/SourceFiles/history/view/history_view_contact_status.cpp @@ -98,16 +98,15 @@ namespace { [[nodiscard]] rpl::producer PeerCustomStatus( not_null 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()); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 35546b013e..dd26f7564e 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -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(this); _fromNameStatus->custom = id ? std::make_unique( - 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(); const auto size = st::emojiSize; diff --git a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp index 1cbcef23ee..91002f6eca 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_badge.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_badge.cpp @@ -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 ContentForPeer( not_null 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; } diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index e5dc793793..3ea355cff3 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -609,15 +609,14 @@ rpl::producer BadgeValue(not_null peer) { } rpl::producer EmojiStatusIdValue(not_null 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 diff --git a/Telegram/SourceFiles/ui/unread_badge.cpp b/Telegram/SourceFiles/ui/unread_badge.cpp index 62e03a5b2e..32321d5fda 100644 --- a/Telegram/SourceFiles/ui/unread_badge.cpp +++ b/Telegram/SourceFiles/ui/unread_badge.cpp @@ -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(); 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; }