mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 19:08:58 +03:00
Add reaction/redaction for in-line Reactions
This commit is contained in:
parent
1c521d1711
commit
5228861b88
8 changed files with 65 additions and 14 deletions
|
@ -1,7 +1,21 @@
|
||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
|
|
||||||
|
// This class is for showing Reactions in the timeline row, not for
|
||||||
|
// adding new reactions via the emoji picker
|
||||||
Flow {
|
Flow {
|
||||||
|
id: reactionFlow
|
||||||
|
// Signal for when a reaction is picked / unpicked
|
||||||
|
signal picked(string room_id, string event_id, string key, string selfReactedEvent)
|
||||||
|
|
||||||
|
// highlight colors for selfReactedEvent background
|
||||||
|
property real highlightHue: colors.highlight.hslHue
|
||||||
|
property real highlightSat: colors.highlight.hslSaturation
|
||||||
|
property real highlightLight: colors.highlight.hslLightness
|
||||||
|
|
||||||
|
property string eventId
|
||||||
|
property string roomId
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
@ -11,7 +25,7 @@ Flow {
|
||||||
Repeater {
|
Repeater {
|
||||||
id: repeater
|
id: repeater
|
||||||
|
|
||||||
AbstractButton {
|
delegate: AbstractButton {
|
||||||
id: reaction
|
id: reaction
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
implicitWidth: contentItem.childrenRect.width + contentItem.leftPadding*2
|
implicitWidth: contentItem.childrenRect.width + contentItem.leftPadding*2
|
||||||
|
@ -20,6 +34,11 @@ Flow {
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
ToolTip.text: model.users
|
ToolTip.text: model.users
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
console.debug("Picked " + model.key + "in response to " + reactionFlow.eventId + " in room " + reactionFlow.roomId + ". selfReactedEvent: " + model.selfReactedEvent)
|
||||||
|
reactionFlow.picked(reactionFlow.roomId, reactionFlow.eventId, model.key, model.selfReactedEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
contentItem: Row {
|
contentItem: Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
@ -48,7 +67,7 @@ Flow {
|
||||||
id: divider
|
id: divider
|
||||||
height: reactionCounter.implicitHeight * 1.4
|
height: reactionCounter.implicitHeight * 1.4
|
||||||
width: 1
|
width: 1
|
||||||
color: reaction.hovered ? colors.highlight : colors.text
|
color: (reaction.hovered || model.selfReactedEvent !== '') ? colors.highlight : colors.text
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
@ -62,10 +81,11 @@ Flow {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
implicitWidth: reaction.implicitWidth
|
implicitWidth: reaction.implicitWidth
|
||||||
implicitHeight: reaction.implicitHeight
|
implicitHeight: reaction.implicitHeight
|
||||||
border.color: (reaction.hovered || model.selfReacted )? colors.highlight : colors.text
|
border.color: (reaction.hovered || model.selfReactedEvent !== '') ? colors.highlight : colors.text
|
||||||
color: colors.base
|
color: model.selfReactedEvent !== '' ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.20) : colors.base
|
||||||
border.width: 1
|
border.width: 1
|
||||||
radius: reaction.height / 2.0
|
radius: reaction.height / 2.0
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,13 @@ MouseArea {
|
||||||
}
|
}
|
||||||
|
|
||||||
Reactions {
|
Reactions {
|
||||||
|
id: reactionRow
|
||||||
reactions: model.reactions
|
reactions: model.reactions
|
||||||
|
roomId: model.roomId
|
||||||
|
eventId: model.id
|
||||||
|
Component.onCompleted: {
|
||||||
|
reactionRow.picked.connect(timelineManager.reactToMessage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ Page {
|
||||||
property var systemInactive: SystemPalette { colorGroup: SystemPalette.Disabled }
|
property var systemInactive: SystemPalette { colorGroup: SystemPalette.Disabled }
|
||||||
property var inactiveColors: currentInactivePalette ? currentInactivePalette : systemInactive
|
property var inactiveColors: currentInactivePalette ? currentInactivePalette : systemInactive
|
||||||
property int avatarSize: 40
|
property int avatarSize: 40
|
||||||
|
property real highlightHue: colors.highlight.hslHue
|
||||||
|
property real highlightSat: colors.highlight.hslSaturation
|
||||||
|
property real highlightLight: colors.highlight.hslLightness
|
||||||
|
|
||||||
palette: colors
|
palette: colors
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ Popup {
|
||||||
property alias model: gridView.model
|
property alias model: gridView.model
|
||||||
property var textArea
|
property var textArea
|
||||||
property string emojiCategory: "people"
|
property string emojiCategory: "people"
|
||||||
|
property real highlightHue: colors.highlight.hslHue
|
||||||
|
property real highlightSat: colors.highlight.hslSaturation
|
||||||
|
property real highlightLight: colors.highlight.hslLightness
|
||||||
|
|
||||||
id: emojiPopup
|
id: emojiPopup
|
||||||
|
|
||||||
|
@ -39,6 +42,8 @@ Popup {
|
||||||
focus: true
|
focus: true
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
|
||||||
|
onPicked: emojiPopup.close()
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: columnView
|
id: columnView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -98,7 +103,7 @@ Popup {
|
||||||
color: "#80000000"
|
color: "#80000000"
|
||||||
source: parent.contentItem
|
source: parent.contentItem
|
||||||
}
|
}
|
||||||
// TODO: emit a signal and maybe add favorites at some point?
|
// TODO: maybe add favorites at some point?
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.debug("Picked " + model.unicode + "in response to " + emojiPopup.event_id + " in room " + emojiPopup.room_id)
|
console.debug("Picked " + model.unicode + "in response to " + emojiPopup.event_id + " in room " + emojiPopup.room_id)
|
||||||
emojiPopup.picked(emojiPopup.room_id, emojiPopup.event_id, model.unicode)
|
emojiPopup.picked(emojiPopup.room_id, emojiPopup.event_id, model.unicode)
|
||||||
|
@ -191,11 +196,8 @@ Popup {
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
property real highlightHue: colors.highlight.hslHue
|
|
||||||
property real highlightSat: colors.highlight.hslSaturation
|
|
||||||
property real highlightLight: colors.highlight.hslLightness
|
|
||||||
|
|
||||||
color: emojiPopup.model.category === model.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.25) : 'transparent'
|
color: emojiPopup.model.category === model.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.20) : 'transparent'
|
||||||
radius: 5
|
radius: 5
|
||||||
border.color: emojiPopup.model.category === model.category ? colors.highlight : 'transparent'
|
border.color: emojiPopup.model.category === model.category ? colors.highlight : 'transparent'
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ ReactionsModel::roleNames() const
|
||||||
{Key, "key"},
|
{Key, "key"},
|
||||||
{Count, "counter"},
|
{Count, "counter"},
|
||||||
{Users, "users"},
|
{Users, "users"},
|
||||||
{SelfReacted, "selfReacted"},
|
{SelfReactedEvent, "selfReactedEvent"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ ReactionsModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
case SelfReacted:
|
case SelfReactedEvent:
|
||||||
for (const auto &reaction : reactions[i].reactions)
|
for (const auto &reaction : reactions[i].reactions)
|
||||||
if (reaction.second.sender == http::client()->user_id().to_string())
|
if (reaction.second.sender == http::client()->user_id().to_string())
|
||||||
return true;
|
return QString::fromStdString(reaction.second.event_id);
|
||||||
return false;
|
return QStringLiteral("");
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
Key,
|
Key,
|
||||||
Count,
|
Count,
|
||||||
Users,
|
Users,
|
||||||
SelfReacted,
|
SelfReactedEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
|
@ -290,6 +290,22 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
|
||||||
timeline_->sendMessage(emote);
|
timeline_->sendMessage(emote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::reactToMessage(const QString &roomId,
|
||||||
|
const QString &reactedEvent,
|
||||||
|
const QString &reactionKey,
|
||||||
|
const QString &selfReactedEvent)
|
||||||
|
{
|
||||||
|
// If selfReactedEvent is empty, that means we haven't previously reacted
|
||||||
|
if (selfReactedEvent.isEmpty()) {
|
||||||
|
queueReactionMessage(roomId, reactedEvent, reactionKey);
|
||||||
|
// Otherwise, we have previously reacted and the reaction should be redacted
|
||||||
|
} else {
|
||||||
|
auto model = models.value(roomId);
|
||||||
|
model->redactEvent(selfReactedEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::queueReactionMessage(const QString &roomId,
|
TimelineViewManager::queueReactionMessage(const QString &roomId,
|
||||||
const QString &reactedEvent,
|
const QString &reactedEvent,
|
||||||
|
|
|
@ -61,6 +61,10 @@ public slots:
|
||||||
void queueReactionMessage(const QString &roomId,
|
void queueReactionMessage(const QString &roomId,
|
||||||
const QString &reactedEvent,
|
const QString &reactedEvent,
|
||||||
const QString &reaction);
|
const QString &reaction);
|
||||||
|
void reactToMessage(const QString &roomId,
|
||||||
|
const QString &reactedEvent,
|
||||||
|
const QString &reactionKey,
|
||||||
|
const QString &selfReactedEvent);
|
||||||
void queueTextMessage(const QString &msg);
|
void queueTextMessage(const QString &msg);
|
||||||
void queueEmoteMessage(const QString &msg);
|
void queueEmoteMessage(const QString &msg);
|
||||||
void queueImageMessage(const QString &roomid,
|
void queueImageMessage(const QString &roomid,
|
||||||
|
|
Loading…
Reference in a new issue