diff --git a/Telegram/SourceFiles/api/api_who_reacted.cpp b/Telegram/SourceFiles/api/api_who_reacted.cpp index c493a3d821..c656b3c936 100644 --- a/Telegram/SourceFiles/api/api_who_reacted.cpp +++ b/Telegram/SourceFiles/api/api_who_reacted.cpp @@ -52,12 +52,14 @@ inline bool operator==( struct PeersWithReactions { std::vector list; int fullReactionsCount = 0; + int fullReadCount = 0; bool unknown = false; }; inline bool operator==( const PeersWithReactions &a, const PeersWithReactions &b) noexcept { return (a.fullReactionsCount == b.fullReactionsCount) + && (a.fullReadCount == b.fullReadCount) && (a.list == b.list) && (a.unknown == b.unknown); } @@ -249,6 +251,7 @@ struct State { .list = peers.list | ranges::views::transform([](PeerId peer) { return PeerWithReaction{.peer = peer }; }) | ranges::to_vector, + .fullReadCount = int(peers.list.size()), .unknown = peers.unknown, }; } @@ -324,6 +327,7 @@ struct State { return PeersWithReactions{ .unknown = true }; } auto &list = reacted.list; + reacted.fullReadCount = int(read.list.size()); for (const auto &peer : read.list) { if (!ranges::contains(list, peer, &PeerWithReaction::peer)) { list.push_back({ .peer = peer }); @@ -540,10 +544,12 @@ rpl::producer WhoReacted( consumer.put_next(Ui::WhoReadContent{ .type = state->current.type, .fullReactionsCount = state->current.fullReactionsCount, + .fullReadCount = state->current.fullReadCount, .unknown = true, }); return; } + state->current.fullReadCount = peers.fullReadCount; state->current.fullReactionsCount = peers.fullReactionsCount; if (UpdateUserpics(state, item, peers.list)) { RegenerateParticipants(state, small, large); diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp index 1cfaa4ab5c..ed860da293 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.cpp @@ -16,6 +16,54 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat.h" #include "styles/style_menu_icons.h" +namespace Lang { +namespace { + +struct StringWithReacted { + QString text; + int seen = 0; +}; + +} // namespace + +template +struct StartReplacements; + +template <> +struct StartReplacements { + static inline StringWithReacted Call(QString &&langString) { + return { std::move(langString) }; + } +}; + +template +struct ReplaceTag; + +template <> +struct ReplaceTag { + static StringWithReacted Call( + StringWithReacted &&original, + ushort tag, + const StringWithReacted &replacement); +}; + +StringWithReacted ReplaceTag::Call( + StringWithReacted &&original, + ushort tag, + const StringWithReacted &replacement) { + const auto offset = FindTagReplacementPosition(original.text, tag); + if (offset < 0) { + return std::move(original); + } + original.text = ReplaceTag::Call( + std::move(original.text), + tag, + replacement.text + '/' + QString::number(original.seen)); + return std::move(original); +} + +} // namespace Lang + namespace Ui { namespace { @@ -80,6 +128,18 @@ TextParseOptions MenuTextOptions = { Qt::LayoutDirectionAuto, // dir }; +[[nodiscard]] QString FormatReactedString(int reacted, int seen) { + const auto projection = [&](const QString &text) { + return Lang::StringWithReacted{ text, seen }; + }; + return tr::lng_context_seen_reacted( + tr::now, + lt_count_short, + reacted, + projection + ).text; +} + Action::Action( not_null parentMenu, rpl::producer content, @@ -177,10 +237,12 @@ void Action::resolveMinWidth() { ? tr::lng_context_seen_text(tr::now, lt_count, 999) : QString(); const auto maxReacted = (_content.fullReactionsCount > 0) - ? tr::lng_context_seen_reacted( - tr::now, - lt_count_short, - _content.fullReactionsCount) + ? (!maxText.isEmpty() + ? FormatReactedString(_content.fullReactionsCount, 999) + : tr::lng_context_seen_reacted( + tr::now, + lt_count_short, + _content.fullReactionsCount)) : QString(); const auto maxTextWidth = std::max(width(maxText), width(maxReacted)); const auto maxWidth = st::defaultWhoRead.itemPadding.left() @@ -297,6 +359,11 @@ void Action::refreshText() { ? tr::lng_context_seen_loading(tr::now) : (usersCount == 1) ? _content.participants.front().name + : (_content.fullReactionsCount > 0 + && _content.fullReactionsCount <= _content.fullReadCount) + ? FormatReactedString( + _content.fullReactionsCount, + _content.fullReadCount) : (_content.type == WhoReadType::Reacted || (count > 0 && _content.fullReactionsCount > usersCount)) ? (count diff --git a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h index aa82c6fbc8..8addbd0010 100644 --- a/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h +++ b/Telegram/SourceFiles/ui/controls/who_reacted_context_action.h @@ -42,6 +42,7 @@ struct WhoReadContent { WhoReadType type = WhoReadType::Seen; QString singleReaction; int fullReactionsCount = 0; + int fullReadCount = 0; bool unknown = false; };