Toggle reactions from the list under the message.

This commit is contained in:
John Preston 2021-12-21 13:23:59 +00:00
parent b5edaf4c23
commit 2991c3c17f
7 changed files with 93 additions and 6 deletions

View File

@ -276,6 +276,10 @@ void MessageReactions::add(const QString &reaction) {
_item->history()->owner().requestItemResize(_item);
}
void MessageReactions::remove() {
add(QString());
}
void MessageReactions::set(
const QVector<MTPReactionCount> &list,
bool ignoreChosen) {
@ -313,6 +317,10 @@ const base::flat_map<QString, int> &MessageReactions::list() const {
return _list;
}
bool MessageReactions::empty() const {
return _list.empty();
}
QString MessageReactions::chosen() const {
return _chosen;
}

View File

@ -90,9 +90,11 @@ public:
explicit MessageReactions(not_null<HistoryItem*> item);
void add(const QString &reaction);
void remove();
void set(const QVector<MTPReactionCount> &list, bool ignoreChosen);
[[nodiscard]] const base::flat_map<QString, int> &list() const;
[[nodiscard]] QString chosen() const;
[[nodiscard]] bool empty() const;
private:
void sendRequest();

View File

@ -756,6 +756,21 @@ void HistoryItem::addReaction(const QString &reaction) {
history()->owner().notifyItemDataChange(this);
}
void HistoryItem::toggleReaction(const QString &reaction) {
if (!_reactions) {
_reactions = std::make_unique<Data::MessageReactions>(this);
_reactions->add(reaction);
} else if (_reactions->chosen() == reaction) {
_reactions->remove();
if (_reactions->empty()) {
_reactions = nullptr;
}
} else {
_reactions->add(reaction);
}
history()->owner().notifyItemDataChange(this);
}
void HistoryItem::updateReactions(const MTPMessageReactions &reactions) {
reactions.match([&](const MTPDmessageReactions &data) {
if (data.vresults().v.isEmpty()) {

View File

@ -393,6 +393,7 @@ public:
[[nodiscard]] bool canReact() const;
void addReaction(const QString &reaction);
void toggleReaction(const QString &reaction);
void updateReactions(const MTPMessageReactions &reactions);
[[nodiscard]] const base::flat_map<QString, int> &reactions() const;
[[nodiscard]] QString chosenReaction() const;

View File

@ -1258,6 +1258,15 @@ TextState Message::textState(
g.setHeight(g.height() - st::msgBotKbButton.margin - keyboardHeight);
}
if (_reactions && !reactionsInBubble) {
const auto reactionsHeight = st::mediaInBubbleSkip + _reactions->height();
g.setHeight(g.height() - reactionsHeight);
const auto reactionsPosition = QPoint(g.left(), g.top() + g.height() + st::mediaInBubbleSkip);
if (_reactions->getState(point - reactionsPosition, &result)) {
return result;
}
}
if (drawBubble()) {
const auto inBubble = g.contains(point);
auto entry = logEntryOriginal();
@ -1299,6 +1308,10 @@ TextState Message::textState(
const auto reactionsHeight = _reactions->height()
+ st::mediaInBubbleSkip;
trect.setHeight(trect.height() - reactionsHeight);
const auto reactionsPosition = QPoint(trect.left(), trect.top() + trect.height() + st::mediaInBubbleSkip);
if (_reactions->getState(point - reactionsPosition, &result)) {
return result;
}
}
if (mediaOnBottom) {
trect.setHeight(trect.height()
@ -1934,13 +1947,27 @@ void Message::refreshReactions() {
return;
}
using namespace Reactions;
auto data = InlineListDataFromMessage(this);
auto reactionsData = InlineListDataFromMessage(this);
if (!_reactions) {
const auto handlerFactory = [=](QString emoji) {
const auto fullId = data()->fullId();
return std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto controller = my.sessionWindow.get()) {
const auto &data = controller->session().data();
if (const auto item = data.message(fullId)) {
item->toggleReaction(emoji);
}
}
});
};
_reactions = std::make_unique<InlineList>(
&item->history()->owner().reactions(),
std::move(data));
handlerFactory,
std::move(reactionsData));
} else {
_reactions->update(std::move(data), width());
_reactions->update(std::move(reactionsData), width());
}
}

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_message.h"
#include "history/history.h"
#include "history/view/history_view_message.h"
#include "history/view/history_view_cursor_state.h"
#include "data/data_message_reactions.h"
#include "lang/lang_tag.h"
#include "ui/chat/chat_style.h"
@ -23,8 +24,12 @@ constexpr auto kOutNonChosenOpacity = 0.18;
} // namespace
InlineList::InlineList(not_null<::Data::Reactions*> owner, Data &&data)
InlineList::InlineList(
not_null<::Data::Reactions*> owner,
Fn<ClickHandlerPtr(QString)> handlerFactory,
Data &&data)
: _owner(owner)
, _handlerFactory(std::move(handlerFactory))
, _data(std::move(data)) {
layout();
}
@ -206,6 +211,27 @@ void InlineList::paint(
}
}
bool InlineList::getState(
QPoint point,
not_null<TextState*> outResult) const {
const auto left = (_data.flags & InlineListData::Flag::InBubble)
? st::reactionBottomInBubbleLeft
: 0;
if (!QRect(left, 0, width() - left, height()).contains(point)) {
return false;
}
for (const auto &button : _buttons) {
if (button.geometry.contains(point)) {
if (!button.link) {
button.link = _handlerFactory(button.emoji);
}
outResult->link = button.link;
return true;
}
}
return false;
}
InlineListData InlineListDataFromMessage(not_null<Message*> message) {
using Flag = InlineListData::Flag;
const auto item = message->message();

View File

@ -20,6 +20,7 @@ struct ChatPaintContext;
namespace HistoryView {
using PaintContext = Ui::ChatPaintContext;
class Message;
struct TextState;
} // namespace HistoryView
namespace HistoryView::Reactions {
@ -40,7 +41,10 @@ struct InlineListData {
class InlineList final : public Object {
public:
using Data = InlineListData;
InlineList(not_null<::Data::Reactions*> owner, Data &&data);
InlineList(
not_null<::Data::Reactions*> owner,
Fn<ClickHandlerPtr(QString)> handlerFactory,
Data &&data);
void update(Data &&data, int availableWidth);
QSize countCurrentSize(int newWidth) override;
@ -53,13 +57,16 @@ public:
const PaintContext &context,
int outerWidth,
const QRect &clip) const;
[[nodiscard]] bool getState(
QPoint point,
not_null<TextState*> outResult) const;
private:
struct Button {
QRect geometry;
mutable QImage image;
mutable ClickHandlerPtr link;
QString emoji;
ClickHandlerPtr link;
QString countText;
int count = 0;
int countTextWidth = 0;
@ -74,6 +81,7 @@ private:
QSize countOptimalSize() override;
const not_null<::Data::Reactions*> _owner;
const Fn<ClickHandlerPtr(QString)> _handlerFactory;
Data _data;
std::vector<Button> _buttons;
QSize _skipBlock;