mirror of https://github.com/Nheko-Reborn/nheko
commit
7beaf868ef
@ -0,0 +1,76 @@ |
|||||||
|
import QtQuick 2.6 |
||||||
|
import QtQuick.Controls 2.2 |
||||||
|
|
||||||
|
Flow { |
||||||
|
anchors.left: parent.left |
||||||
|
anchors.right: parent.right |
||||||
|
spacing: 4 |
||||||
|
|
||||||
|
property alias reactions: repeater.model |
||||||
|
|
||||||
|
Repeater { |
||||||
|
id: repeater |
||||||
|
|
||||||
|
AbstractButton { |
||||||
|
id: reaction |
||||||
|
text: model.key |
||||||
|
hoverEnabled: true |
||||||
|
implicitWidth: contentItem.childrenRect.width + contentItem.leftPadding*2 |
||||||
|
implicitHeight: contentItem.childrenRect.height |
||||||
|
|
||||||
|
ToolTip.visible: hovered |
||||||
|
ToolTip.text: model.users |
||||||
|
|
||||||
|
|
||||||
|
contentItem: Row { |
||||||
|
anchors.centerIn: parent |
||||||
|
spacing: reactionText.implicitHeight/4 |
||||||
|
leftPadding: reactionText.implicitHeight / 2 |
||||||
|
rightPadding: reactionText.implicitHeight / 2 |
||||||
|
|
||||||
|
TextMetrics { |
||||||
|
id: textMetrics |
||||||
|
font.family: settings.emoji_font_family |
||||||
|
elide: Text.ElideRight |
||||||
|
elideWidth: 150 |
||||||
|
text: reaction.text |
||||||
|
} |
||||||
|
|
||||||
|
Text { |
||||||
|
anchors.baseline: reactionCounter.baseline |
||||||
|
id: reactionText |
||||||
|
text: textMetrics.elidedText + (textMetrics.elidedText == textMetrics.text ? "" : "…") |
||||||
|
font.family: settings.emoji_font_family |
||||||
|
color: reaction.hovered ? colors.highlight : colors.text |
||||||
|
maximumLineCount: 1 |
||||||
|
} |
||||||
|
|
||||||
|
Rectangle { |
||||||
|
id: divider |
||||||
|
height: reactionCounter.implicitHeight * 1.4 |
||||||
|
width: 1 |
||||||
|
color: reaction.hovered ? colors.highlight : colors.text |
||||||
|
} |
||||||
|
|
||||||
|
Text { |
||||||
|
anchors.verticalCenter: divider.verticalCenter |
||||||
|
id: reactionCounter |
||||||
|
text: model.counter |
||||||
|
font: reaction.font |
||||||
|
color: reaction.hovered ? colors.highlight : colors.text |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
background: Rectangle { |
||||||
|
anchors.centerIn: parent |
||||||
|
implicitWidth: reaction.implicitWidth |
||||||
|
implicitHeight: reaction.implicitHeight |
||||||
|
border.color: (reaction.hovered || model.selfReacted )? colors.highlight : colors.text |
||||||
|
color: colors.base |
||||||
|
border.width: 1 |
||||||
|
radius: reaction.height / 2.0 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,98 @@ |
|||||||
|
#include "ReactionsModel.h" |
||||||
|
|
||||||
|
#include <Cache.h> |
||||||
|
#include <MatrixClient.h> |
||||||
|
|
||||||
|
QHash<int, QByteArray> |
||||||
|
ReactionsModel::roleNames() const |
||||||
|
{ |
||||||
|
return { |
||||||
|
{Key, "key"}, |
||||||
|
{Count, "counter"}, |
||||||
|
{Users, "users"}, |
||||||
|
{SelfReacted, "selfReacted"}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
int |
||||||
|
ReactionsModel::rowCount(const QModelIndex &) const |
||||||
|
{ |
||||||
|
return static_cast<int>(reactions.size()); |
||||||
|
} |
||||||
|
|
||||||
|
QVariant |
||||||
|
ReactionsModel::data(const QModelIndex &index, int role) const |
||||||
|
{ |
||||||
|
const int i = index.row(); |
||||||
|
if (i < 0 || i >= static_cast<int>(reactions.size())) |
||||||
|
return {}; |
||||||
|
|
||||||
|
switch (role) { |
||||||
|
case Key: |
||||||
|
return QString::fromStdString(reactions[i].key); |
||||||
|
case Count: |
||||||
|
return static_cast<int>(reactions[i].reactions.size()); |
||||||
|
case Users: { |
||||||
|
QString users; |
||||||
|
bool first = true; |
||||||
|
for (const auto &reaction : reactions[i].reactions) { |
||||||
|
if (!first) |
||||||
|
users += ", "; |
||||||
|
else |
||||||
|
first = false; |
||||||
|
users += QString::fromStdString( |
||||||
|
cache::displayName(room_id_, reaction.second.sender)); |
||||||
|
} |
||||||
|
return users; |
||||||
|
} |
||||||
|
case SelfReacted: |
||||||
|
for (const auto &reaction : reactions[i].reactions) |
||||||
|
if (reaction.second.sender == http::client()->user_id().to_string()) |
||||||
|
return true; |
||||||
|
return false; |
||||||
|
default: |
||||||
|
return {}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
ReactionsModel::addReaction(const std::string &room_id, |
||||||
|
const mtx::events::RoomEvent<mtx::events::msg::Reaction> &reaction) |
||||||
|
{ |
||||||
|
room_id_ = room_id; |
||||||
|
|
||||||
|
int idx = 0; |
||||||
|
for (auto &storedReactions : reactions) { |
||||||
|
if (storedReactions.key == reaction.content.relates_to.key) { |
||||||
|
storedReactions.reactions[reaction.event_id] = reaction; |
||||||
|
emit dataChanged(index(idx, 0), index(idx, 0)); |
||||||
|
return; |
||||||
|
} |
||||||
|
idx++; |
||||||
|
} |
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), idx, idx); |
||||||
|
reactions.push_back( |
||||||
|
KeyReaction{reaction.content.relates_to.key, {{reaction.event_id, reaction}}}); |
||||||
|
endInsertRows(); |
||||||
|
} |
||||||
|
|
||||||
|
void |
||||||
|
ReactionsModel::removeReaction(const mtx::events::RoomEvent<mtx::events::msg::Reaction> &reaction) |
||||||
|
{ |
||||||
|
int idx = 0; |
||||||
|
for (auto &storedReactions : reactions) { |
||||||
|
if (storedReactions.key == reaction.content.relates_to.key) { |
||||||
|
storedReactions.reactions.erase(reaction.event_id); |
||||||
|
|
||||||
|
if (storedReactions.reactions.size() == 0) { |
||||||
|
beginRemoveRows(QModelIndex(), idx, idx); |
||||||
|
reactions.erase(reactions.begin() + idx); |
||||||
|
endRemoveRows(); |
||||||
|
} else |
||||||
|
emit dataChanged(index(idx, 0), index(idx, 0)); |
||||||
|
return; |
||||||
|
} |
||||||
|
idx++; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QAbstractListModel> |
||||||
|
#include <QHash> |
||||||
|
|
||||||
|
#include <utility> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
#include <mtx/events/collections.hpp> |
||||||
|
|
||||||
|
class ReactionsModel : public QAbstractListModel |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit ReactionsModel(QObject *parent = nullptr) { Q_UNUSED(parent); } |
||||||
|
enum Roles |
||||||
|
{ |
||||||
|
Key, |
||||||
|
Count, |
||||||
|
Users, |
||||||
|
SelfReacted, |
||||||
|
}; |
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override; |
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
||||||
|
|
||||||
|
public slots: |
||||||
|
void addReaction(const std::string &room_id, |
||||||
|
const mtx::events::RoomEvent<mtx::events::msg::Reaction> &reaction); |
||||||
|
void removeReaction(const mtx::events::RoomEvent<mtx::events::msg::Reaction> &reaction); |
||||||
|
|
||||||
|
private: |
||||||
|
struct KeyReaction |
||||||
|
{ |
||||||
|
std::string key; |
||||||
|
std::map<std::string, mtx::events::RoomEvent<mtx::events::msg::Reaction>> reactions; |
||||||
|
}; |
||||||
|
std::string room_id_; |
||||||
|
std::vector<KeyReaction> reactions; |
||||||
|
}; |
Loading…
Reference in new issue