diff --git a/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp b/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp index 94b14444c..a6603f317 100644 --- a/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp +++ b/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp @@ -18,8 +18,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_message.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_react_animation.h" +#include "core/click_handler_types.h" +#include "main/main_session.h" #include "lottie/lottie_icon.h" +#include "data/data_session.h" #include "data/data_message_reactions.h" +#include "window/window_session_controller.h" #include "styles/style_chat.h" #include "styles/style_dialogs.h" @@ -107,6 +111,10 @@ TextState BottomInfo::textState( not_null item, QPoint position) const { auto result = TextState(item); + if (const auto link = revokeReactionLink(item, position)) { + result.link = link; + return result; + } const auto inTime = QRect( width() - _dateWidth, 0, @@ -119,6 +127,75 @@ TextState BottomInfo::textState( return result; } +ClickHandlerPtr BottomInfo::revokeReactionLink( + not_null item, + QPoint position) const { + if (_reactions.empty()) { + return nullptr; + } + auto left = 0; + auto top = 0; + auto available = width(); + if (height() != minHeight()) { + available = std::min(available, _reactionsMaxWidth); + left += width() - available; + top += st::msgDateFont->height; + } + auto x = left; + auto y = top; + auto widthLeft = available; + for (const auto &reaction : _reactions) { + const auto chosen = (reaction.emoji == _data.chosenReaction); + const auto add = (reaction.countTextWidth > 0) + ? st::reactionInfoDigitSkip + : st::reactionInfoBetween; + const auto width = st::reactionInfoSize + + (reaction.countTextWidth > 0 + ? (st::reactionInfoSkip + reaction.countTextWidth) + : 0); + if (x > left && widthLeft < width) { + x = left; + y += st::msgDateFont->height; + widthLeft = available; + } + const auto image = QRect( + x, + y, + st::reactionInfoSize, + st::msgDateFont->height); + if (chosen && image.contains(position)) { + if (!_revokeLink) { + _revokeLink = revokeReactionLink(item); + } + return _revokeLink; + } + x += width + add; + widthLeft -= width + add; + } + return nullptr; +} + +ClickHandlerPtr BottomInfo::revokeReactionLink( + not_null item) const { + const auto itemId = item->fullId(); + const auto sessionId = item->history()->session().uniqueId(); + return std::make_shared([=]( + ClickContext context) { + const auto my = context.other.value(); + if (const auto controller = my.sessionWindow.get()) { + if (controller->session().uniqueId() == sessionId) { + auto &owner = controller->session().data(); + if (const auto item = owner.message(itemId)) { + const auto chosen = item->chosenReaction(); + if (!chosen.isEmpty()) { + item->toggleReaction(chosen); + } + } + } + } + }); +} + bool BottomInfo::isSignedAuthorElided() const { return _authorElided; } @@ -463,6 +540,7 @@ BottomInfo::Data BottomInfoDataFromMessage(not_null message) { result.date = message->dateTime(); if (message->embedReactionsInBottomInfo()) { result.reactions = item->reactions(); + result.chosenReaction = item->chosenReaction(); } if (message->hasOutLayout()) { result.flags |= Flag::OutLayout; diff --git a/Telegram/SourceFiles/history/view/history_view_bottom_info.h b/Telegram/SourceFiles/history/view/history_view_bottom_info.h index 73041f844..7d7fb9093 100644 --- a/Telegram/SourceFiles/history/view/history_view_bottom_info.h +++ b/Telegram/SourceFiles/history/view/history_view_bottom_info.h @@ -48,6 +48,7 @@ public: QDateTime date; QString author; base::flat_map reactions; + QString chosenReaction; std::optional views; std::optional replies; Flags flags; @@ -110,6 +111,11 @@ private: void setReactionCount(Reaction &reaction, int count); [[nodiscard]] Reaction prepareReactionWithEmoji(const QString &emoji); + [[nodiscard]] ClickHandlerPtr revokeReactionLink( + not_null item, + QPoint position) const; + [[nodiscard]] ClickHandlerPtr revokeReactionLink( + not_null item) const; const not_null<::Data::Reactions*> _reactionsOwner; Data _data; @@ -117,6 +123,7 @@ private: Ui::Text::String _views; Ui::Text::String _replies; std::vector _reactions; + mutable ClickHandlerPtr _revokeLink; mutable std::unique_ptr _reactionAnimation; int _reactionsMaxWidth = 0; int _dateWidth = 0;