From 2618ee3d750eb351631f0e0a04b983226cd099c9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 31 Aug 2022 17:51:41 +0400 Subject: [PATCH] Paint two-loops of custom emoji statuses. --- Telegram/SourceFiles/dialogs/dialogs.style | 1 - .../view/history_view_context_menu.cpp | 42 +++--- .../history/view/history_view_message.cpp | 120 ++++++++++++++---- .../history/view/history_view_message.h | 2 + .../controls/who_reacted_context_action.cpp | 16 ++- .../ui/controls/who_reacted_context_action.h | 4 +- Telegram/SourceFiles/ui/unread_badge.cpp | 14 +- Telegram/lib_ui | 2 +- 8 files changed, 153 insertions(+), 48 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index b68f8c58d..7ba4b8941 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -246,7 +246,6 @@ dialogsVerifiedIconActive: icon { dialogsPremiumIcon: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }}; dialogsPremiumIconOver: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBgOver }}; dialogsPremiumIconActive: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBgActive }}; -dialogsPremiumIconOffset: point(5px, 0px); historySendingIcon: icon {{ "dialogs/dialogs_sending", historySendingOutIconFg, point(5px, 5px) }}; historySendingInvertedIcon: icon {{ "dialogs/dialogs_sending", historySendingInvertedIconFg, point(5px, 5px) }}; diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 279889223..dfc3a03bb 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -1172,6 +1172,9 @@ void ShowWhoReactedMenu( const Data::ReactionId &id, not_null controller, rpl::lifetime &lifetime) { + struct State { + int addedToBottom = 0; + }; const auto participantChosen = [=](uint64 id) { controller->showPeerInfo(PeerId(id)); }; @@ -1194,6 +1197,7 @@ void ShowWhoReactedMenu( Data::ReactedMenuFactory(&controller->session()), participantChosen, showAllChosen); + const auto state = lifetime.make_state(); Api::WhoReacted( item, id, @@ -1203,7 +1207,7 @@ void ShowWhoReactedMenu( return !content.unknown; }) | rpl::start_with_next([=, &lifetime](Ui::WhoReadContent &&content) { const auto creating = !*menu; - const auto refill = [=] { + const auto refillTop = [=] { if (activeNonQuick) { (*menu)->addAction(tr::lng_context_set_as_quick(tr::now), [=] { reactions->setFavorite(id); @@ -1211,26 +1215,34 @@ void ShowWhoReactedMenu( (*menu)->addSeparator(); } }; + const auto appendBottom = [=] { + state->addedToBottom = 0; + if (const auto custom = id.custom()) { + if (const auto set = owner->document(custom)->sticker()) { + if (set->set.id) { + state->addedToBottom = 2; + AddEmojiPacksAction( + menu->get(), + { set->set }, + EmojiPacksSource::Reaction, + controller); + } + } + } + }; if (creating) { *menu = base::make_unique_q( context, st::whoReadMenu); (*menu)->lifetime().add(base::take(lifetime)); - refill(); - } - filler->populate(menu->get(), content); - - if (const auto custom = id.custom()) { - if (const auto set = owner->document(custom)->sticker()) { - if (set->set.id) { - AddEmojiPacksAction( - menu->get(), - { set->set }, - EmojiPacksSource::Reaction, - controller); - } - } + refillTop(); } + filler->populate( + menu->get(), + content, + refillTop, + state->addedToBottom, + appendBottom); if (creating) { (*menu)->popup(position); } diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index ced6a2be1..e746edb68 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { namespace { +constexpr auto kPlayStatusLimit = 2; const auto kPsaTooltipPrefix = "cloud_lng_tooltip_psa_"; std::optional ExtractController( @@ -234,6 +235,13 @@ struct Message::CommentsButton { int rightActionCountWidth = 0; }; +struct Message::FromNameStatus { + DocumentId id = 0; + std::unique_ptr custom; + Ui::Text::CustomEmojiColored colored; + int skip = 0; +}; + LogEntryOriginal::LogEntryOriginal() = default; LogEntryOriginal::LogEntryOriginal(LogEntryOriginal &&other) @@ -277,8 +285,9 @@ Message::Message( } Message::~Message() { - if (_comments) { + if (_comments || (_fromNameStatus && _fromNameStatus->custom)) { _comments = nullptr; + _fromNameStatus = nullptr; checkHeavyPart(); } } @@ -547,6 +556,9 @@ QSize Message::performCountOptimalSize() { : item->hiddenSenderInfo()->nameText(); auto namew = st::msgPadding.left() + name.maxWidth() + + (_fromNameStatus + ? st::dialogsPremiumIcon.width() + : 0) + st::msgPadding.right(); if (via && !displayForwardedFrom()) { namew += st::msgServiceFont->spacew + via->maxWidth; @@ -1087,32 +1099,71 @@ void Message::paintFromName( availableWidth -= st::msgPadding.right() + rightWidth; } - p.setFont(st::msgNameFont); const auto stm = context.messageStyle(); - - const auto nameText = [&]() -> const Ui::Text::String * { - const auto from = item->displayFrom(); - const auto service = (context.outbg || item->isPost()); - const auto st = context.st; + const auto from = item->displayFrom(); + const auto info = from ? nullptr : item->hiddenSenderInfo(); + Assert(from || info); + const auto service = (context.outbg || item->isPost()); + const auto st = context.st; + const auto nameFg = !service + ? FromNameFg(context, from ? from->id : info->colorPeerId) + : item->isSponsored() + ? st->boxTextFgGood() + : stm->msgServiceFg; + const auto nameText = [&] { if (from) { - p.setPen(!service - ? FromNameFg(context, from->id) - : item->isSponsored() - ? st->boxTextFgGood() - : stm->msgServiceFg); validateFromNameText(from); - return &_fromName; - } else if (const auto info = item->hiddenSenderInfo()) { - p.setPen(!service - ? FromNameFg(context, info->colorPeerId) - : item->isSponsored() - ? st->boxTextFgGood() - : stm->msgServiceFg); - return &info->nameText(); - } else { - Unexpected("Corrupt sender information in message."); + return static_cast(&_fromName); } + return &info->nameText(); }(); + const auto statusWidth = _fromNameStatus ? st::dialogsPremiumIcon.width() : 0; + if (statusWidth && availableWidth > statusWidth) { + const auto x = availableLeft + + std::min(availableWidth - statusWidth, nameText->maxWidth()); + const auto y = trect.top(); + const auto color = QColor( + nameFg->c.red(), + nameFg->c.green(), + nameFg->c.blue(), + nameFg->c.alpha() * 115 / 255); + const auto user = from->asUser(); + const auto id = user ? user->emojiStatusId() : 0; + if (_fromNameStatus->id != id) { + const auto that = const_cast(this); + _fromNameStatus->custom = id + ? std::make_unique( + user->owner().customEmojiManager().create( + id, + [=] { that->customEmojiRepaint(); }), + kPlayStatusLimit) + : nullptr; + if (id && !_fromNameStatus->id) { + history()->owner().registerHeavyViewPart(that); + } else if (!id && _fromNameStatus->id) { + that->checkHeavyPart(); + } + _fromNameStatus->id = id; + } + if (_fromNameStatus->custom) { + clearCustomEmojiRepaint(); + _fromNameStatus->colored.color = color; + _fromNameStatus->custom->paint(p, { + .preview = color, + .colored = &_fromNameStatus->colored, + .now = context.now, + .position = QPoint( + x - 2 * _fromNameStatus->skip, + y + _fromNameStatus->skip), + .paused = delegate()->elementIsGifPaused(), + }); + } else { + st::dialogsPremiumIcon.paint(p, x, y, width(), color); + } + availableWidth -= statusWidth; + } + p.setFont(st::msgNameFont); + p.setPen(nameFg); nameText->drawElided(p, availableLeft, trect.top(), availableWidth); const auto skipWidth = nameText->maxWidth() + st::msgServiceFont->spacew; availableLeft += skipWidth; @@ -1382,7 +1433,9 @@ void Message::toggleCommentsButtonRipple(bool pressed) { } bool Message::hasHeavyPart() const { - return _comments || Element::hasHeavyPart(); + return _comments + || (_fromNameStatus && _fromNameStatus->custom) + || Element::hasHeavyPart(); } void Message::unloadHeavyPart() { @@ -1391,6 +1444,9 @@ void Message::unloadHeavyPart() { _reactions->unloadCustomEmoji(); } _comments = nullptr; + if (_fromNameStatus) { + _fromNameStatus->custom = nullptr; + } } bool Message::showForwardsFromSender( @@ -2245,7 +2301,13 @@ void Message::refreshReactions() { } void Message::validateFromNameText(PeerData *from) const { - const auto version = from ? from->nameVersion() : 0; + if (!from) { + if (_fromNameStatus) { + _fromNameStatus = nullptr; + } + return; + } + const auto version = from->nameVersion(); if (_fromNameVersion < version) { _fromNameVersion = version; _fromName.setText( @@ -2253,6 +2315,16 @@ void Message::validateFromNameText(PeerData *from) const { from->name(), Ui::NameTextOptions()); } + if (from->isPremium()) { + if (!_fromNameStatus) { + _fromNameStatus = std::make_unique(); + const auto size = st::emojiSize; + const auto emoji = Ui::Text::AdjustCustomEmojiSize(size); + _fromNameStatus->skip = (size - emoji) / 2; + } + } else if (_fromNameStatus) { + _fromNameStatus = nullptr; + } } void Message::itemDataChanged() { diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index 11617b817..039427966 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -151,6 +151,7 @@ protected: private: struct CommentsButton; + struct FromNameStatus; void initLogEntryOriginal(); void initPsa(); @@ -258,6 +259,7 @@ private: mutable std::unique_ptr _comments; mutable Ui::Text::String _fromName; + mutable std::unique_ptr _fromNameStatus; Ui::Text::String _rightBadge; mutable int _fromNameVersion = 0; int _bubbleWidthLimit = 0; diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp index 129b6b008..a767d8709 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp @@ -636,7 +636,9 @@ void WhoReactedListMenu::clear() { void WhoReactedListMenu::populate( not_null menu, const WhoReadContent &content, - Fn refillTopActions) { + Fn refillTopActions, + int addedToBottom, + Fn appendBottomActions) { const auto reactions = ranges::count_if( content.participants, [](const auto &p) { return !p.customEntityData.isEmpty(); }); @@ -649,6 +651,7 @@ void WhoReactedListMenu::populate( if (refillTopActions) { refillTopActions(); } + addedToBottom = 0; } auto index = 0; const auto append = [&](EntryData &&data) { @@ -661,7 +664,12 @@ void WhoReactedListMenu::populate( menu->menu()->st(), std::move(data)); _actions.push_back(item.get()); - menu->addAction(std::move(item)); + const auto count = int(menu->actions().size()); + if (addedToBottom > 0 && addedToBottom <= count) { + menu->insertAction(count - addedToBottom, std::move(item)); + } else { + menu->addAction(std::move(item)); + } } ++index; }; @@ -682,7 +690,9 @@ void WhoReactedListMenu::populate( .callback = _showAllChosen, }); } - + if (!addedToBottom && appendBottomActions) { + appendBottomActions(); + } } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h index 9e2ea9108..46d2cecf9 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h @@ -65,7 +65,9 @@ public: void populate( not_null menu, const WhoReadContent &content, - Fn refillTopActions = nullptr); + Fn refillTopActions = nullptr, + int addedToBottom = 0, + Fn appendBottomActions = nullptr); private: class EntryAction; diff --git a/Telegram/SourceFiles/ui/unread_badge.cpp b/Telegram/SourceFiles/ui/unread_badge.cpp index 6f529dd2d..0a485c59a 100644 --- a/Telegram/SourceFiles/ui/unread_badge.cpp +++ b/Telegram/SourceFiles/ui/unread_badge.cpp @@ -17,6 +17,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_dialogs.h" namespace Ui { +namespace { + +constexpr auto kPlayStatusLimit = 2; + +} // namespace void UnreadBadge::setText(const QString &text, bool active) { _text = text; @@ -177,11 +182,14 @@ int PeerBadge::drawGetWidth( >(); } if (_emojiStatus->id != id) { + using namespace Ui::Text; auto &manager = peer->session().data().customEmojiManager(); _emojiStatus->id = id; - _emojiStatus->emoji = manager.create( - id, - descriptor.customEmojiRepaint); + _emojiStatus->emoji = std::make_unique( + manager.create( + id, + descriptor.customEmojiRepaint), + kPlayStatusLimit); } _emojiStatus->colored->color = (*descriptor.premiumFg)->c; _emojiStatus->emoji->paint(p, { diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 51657b3c8..a5766cb1f 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 51657b3c8a643c9ca2721029fd48f63390417042 +Subproject commit a5766cb1f6bfcd208814b0b71322128ecb47039a