mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Toggle reactions from the list under the message.
This commit is contained in:
parent
b5edaf4c23
commit
2991c3c17f
7 changed files with 93 additions and 6 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue