Add reaction/redaction for in-line Reactions

This commit is contained in:
Joseph Donofry 2020-05-21 21:21:35 -04:00
parent 1c521d1711
commit 5228861b88
No known key found for this signature in database
GPG key ID: E8A1D78EF044B0CB
8 changed files with 65 additions and 14 deletions

View file

@ -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
} }

View file

@ -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)
}
} }
} }

View file

@ -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

View file

@ -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'
} }

View file

@ -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 {};
} }

View file

@ -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;

View file

@ -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,

View file

@ -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,