@@ -15,6 +15,7 @@ import NeoChat.Menu.Timeline 1.0
|
|||||||
Image {
|
Image {
|
||||||
id: img
|
id: img
|
||||||
|
|
||||||
|
property var content: model.content
|
||||||
readonly property bool isAnimated: contentType === "image/gif"
|
readonly property bool isAnimated: contentType === "image/gif"
|
||||||
|
|
||||||
property bool openOnFinished: false
|
property bool openOnFinished: false
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import NeoChat.Component.Timeline 1.0
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: replyButton
|
id: replyButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
implicitHeight: replyName.implicitHeight + replyText.implicitHeight + Kirigami.Units.largeSpacing
|
implicitHeight: replyName.implicitHeight + (loader.item ? loader.item.height : 0) + Kirigami.Units.largeSpacing
|
||||||
implicitWidth: Math.min(bubbleMaxWidth, Math.max(replyText.implicitWidth, replyName.implicitWidth)) + Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3
|
implicitWidth: Math.min(bubbleMaxWidth, Math.max((loader.item ? loader.item.width : 0), replyName.implicitWidth)) + Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 3
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
parent.Layout.fillWidth = true;
|
parent.Layout.fillWidth = true;
|
||||||
parent.Layout.preferredWidth = Qt.binding(function() { return implicitWidth; })
|
parent.Layout.preferredWidth = Qt.binding(function() { return implicitWidth; })
|
||||||
@@ -56,18 +56,48 @@ MouseArea {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
}
|
}
|
||||||
|
|
||||||
TextDelegate {
|
Loader {
|
||||||
id: replyText
|
id: loader
|
||||||
anchors {
|
anchors.top: replyName.bottom
|
||||||
left: avatatReply.right
|
sourceComponent: {
|
||||||
top: replyName.bottom
|
switch (reply.type) {
|
||||||
leftMargin: Kirigami.Units.smallSpacing
|
case "image":
|
||||||
topMargin: Kirigami.Units.smallSpacing
|
case "sticker":
|
||||||
right: parent.right
|
return imageComponent;
|
||||||
rightMargin: Kirigami.Units.smallSpacing
|
case "message":
|
||||||
|
return textComponent;
|
||||||
|
// TODO support more types
|
||||||
|
default:
|
||||||
|
return textComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: textComponent
|
||||||
|
TextDelegate {
|
||||||
|
id: replyText
|
||||||
|
textMessage: reply.display
|
||||||
|
textFormat: Text.RichText
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
width: Math.min(implicitWidth, bubbleMaxWidth) - Kirigami.Units.smallSpacing * 5 - avatatReply.width
|
||||||
|
x: Kirigami.Units.smallSpacing * 3 + avatatReply.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: imageComponent
|
||||||
|
Image {
|
||||||
|
readonly property var content: reply.content
|
||||||
|
readonly property bool isThumbnail: !(content.info.thumbnail_info == null || content.thumbnailMediaId == null)
|
||||||
|
// readonly property var info: isThumbnail ? content.info.thumbnail_info : content.info
|
||||||
|
readonly property var info: content.info
|
||||||
|
readonly property string mediaId: isThumbnail ? content.thumbnailMediaId : content.mediaId
|
||||||
|
source: "image://mxc/" + mediaId
|
||||||
|
|
||||||
|
width: bubbleMaxWidth * 0.75 - Kirigami.Units.smallSpacing * 5 - avatatReply.width
|
||||||
|
height: reply.content.info.h / reply.content.info.w * width
|
||||||
|
x: Kirigami.Units.smallSpacing * 3 + avatatReply.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
textMessage: reply.display
|
|
||||||
textFormat: Text.RichText
|
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -559,9 +559,56 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
};
|
};
|
||||||
const auto &replyEvt = **replyIt;
|
const auto &replyEvt = **replyIt;
|
||||||
|
|
||||||
return QVariantMap{{"eventId", replyEventId},
|
QString type;
|
||||||
{"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)},
|
if (auto e = eventCast<const RoomMessageEvent>(&replyEvt)) {
|
||||||
{"author", userAtEvent(static_cast<NeoChatUser *>(m_currentRoom->user(replyEvt.senderId())), m_currentRoom, evt)}};
|
switch (e->msgtype()) {
|
||||||
|
case MessageEventType::Emote:
|
||||||
|
type = "emote";
|
||||||
|
break;
|
||||||
|
case MessageEventType::Notice:
|
||||||
|
type = "notice";
|
||||||
|
break;
|
||||||
|
case MessageEventType::Image:
|
||||||
|
type = "image";
|
||||||
|
break;
|
||||||
|
case MessageEventType::Audio:
|
||||||
|
type = "audio";
|
||||||
|
break;
|
||||||
|
case MessageEventType::Video:
|
||||||
|
type = "video";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (e->hasFileContent()) {
|
||||||
|
type = "file";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
type = "message";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (is<const StickerEvent>(replyEvt)) {
|
||||||
|
type = "sticker";
|
||||||
|
} else {
|
||||||
|
type = "other";
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant content;
|
||||||
|
if (auto e = eventCast<const RoomMessageEvent>(&replyEvt)) {
|
||||||
|
// Cannot use e.contentJson() here because some
|
||||||
|
// EventContent classes inject values into the copy of the
|
||||||
|
// content JSON stored in EventContent::Base
|
||||||
|
content = e->hasFileContent() ? QVariant::fromValue(e->content()->originalJson) : QVariant();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (auto e = eventCast<const StickerEvent>(&replyEvt)) {
|
||||||
|
content = QVariant::fromValue(e->image().originalJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariantMap{
|
||||||
|
{"eventId", replyEventId},
|
||||||
|
{"display", m_currentRoom->eventToString(replyEvt, Qt::RichText)},
|
||||||
|
{"content", content},
|
||||||
|
{"type", type},
|
||||||
|
{"author", userAtEvent(static_cast<NeoChatUser *>(m_currentRoom->user(replyEvt.senderId())), m_currentRoom, evt)}};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == ShowAuthorRole) {
|
if (role == ShowAuthorRole) {
|
||||||
|
|||||||
Reference in New Issue
Block a user