Skip to content
Snippets Groups Projects
Verified Commit 76b40f45 authored by Nicolas Werner's avatar Nicolas Werner
Browse files

Working text messages in delegate rework

parent 4d8b8c3b
No related branches found
No related tags found
No related merge requests found
......@@ -2,24 +2,24 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.5
import QtQuick.Controls 2.3
import im.nheko 1.0
import QtQuick
import QtQuick.Controls
import im.nheko
TextEdit {
TextArea {
id: r
property alias cursorShape: cs.cursorShape
//leftInset: 0
//bottomInset: 0
//rightInset: 0
//topInset: 0
//leftPadding: 0
//bottomPadding: 0
//rightPadding: 0
//topPadding: 0
//background: null
leftInset: 0
bottomInset: 0
rightInset: 0
topInset: 0
leftPadding: 0
bottomPadding: 0
rightPadding: 0
topPadding: 0
background: null
ToolTip.text: hoveredLink
ToolTip.visible: hoveredLink || false
......@@ -39,9 +39,9 @@ TextEdit {
}
onLinkActivated: Nheko.openLink(link)
//// propagate events up
//onPressAndHold: (event) => event.accepted = false
//onPressed: (event) => event.accepted = (event.button == Qt.LeftButton)
// propagate events up
onPressAndHold: (event) => event.accepted = false
onPressed: (event) => event.accepted = (event.button == Qt.LeftButton)
NhekoCursorShape {
id: cs
......
......@@ -63,28 +63,160 @@ Item {
id: wrapper
ListView.delayRemove: true
width: chat.delegateMaxWidth
height: main?.height ?? 10
height: Math.max((section.item?.height ?? 0) + gridContainer.implicitHeight, 10)
anchors.horizontalCenter: ListView.view.contentItem.horizontalCenter
room: chatRoot.roommodel
required property var day
required property bool isSender
required property bool isStateEvent
//required property var previousMessageDay
//required property bool previousMessageIsStateEvent
//required property string previousMessageUserId
required property int index
property var previousMessageDay: (index + 1) >= chat.count ? 0 : chat.model.dataByIndex(index + 1, Room.Day)
property bool previousMessageIsStateEvent: (index + 1) >= chat.count ? true : chat.model.dataByIndex(index + 1, Room.IsStateEvent)
property string previousMessageUserId: (index + 1) >= chat.count ? "" : chat.model.dataByIndex(index + 1, Room.UserId)
required property date timestamp
required property string userId
required property string userName
required property string threadId
data: [
Loader {
id: section
property var day: wrapper.day
property bool isSender: wrapper.isSender
property bool isStateEvent: wrapper.isStateEvent
property int parentWidth: wrapper.width
property var previousMessageDay: wrapper.previousMessageDay
property bool previousMessageIsStateEvent: wrapper.previousMessageIsStateEvent
property string previousMessageUserId: wrapper.previousMessageUserId
property date timestamp: wrapper.timestamp
property string userId: wrapper.userId
property string userName: wrapper.userName
active: previousMessageUserId !== userId || previousMessageDay !== day || previousMessageIsStateEvent !== isStateEvent
//asynchronous: true
sourceComponent: sectionHeader
visible: status == Loader.Ready
z: 4
},
GridLayout {
id: gridContainer
width: wrapper.width
y: section.visible && section.active ? section.y + section.height : 0
ColumnLayout {
id: contentColumn
Layout.fillWidth: true
Layout.leftMargin: (wrapper.isStateEvent || Settings.smallAvatars ? 0 : (Nheko.avatarSize + 8)) + (wrapper.threadId ? 6 : 0) // align bubble with section header
AbstractButton {
id: replyRow
visible: wrapper.reply
Layout.fillWidth: true
Layout.maximumHeight: timelineView.height / 8
Layout.preferredWidth: replyRowLay.implicitWidth
Layout.preferredHeight: replyRowLay.implicitHeight
property color userColor: TimelineManager.userColor(wrapper.reply?.userId ?? '', palette.base)
clip: true
contentItem: RowLayout {
id: replyRowLay
anchors.fill: parent
Rectangle {
id: replyLine
Layout.fillHeight: true
color: replyRow.userColor
Layout.preferredWidth: 4
}
ColumnLayout {
AbstractButton {
id: replyUserButton
Layout.fillWidth: true
contentItem: ElidedLabel {
id: userName_
fullText: wrapper.reply?.userName ?? ''
color: replyRow.userColor
textFormat: Text.RichText
width: parent.width
elideWidth: width
}
onClicked: room.openUserProfile(wrapper.reply?.userId)
}
data: [
replyUserButton,
wrapper.reply,
]
}
}
background: Rectangle {
width: replyRow.implicitContentWidth
color: Qt.tint(palette.base, Qt.hsla(replyRow.userColor.hslHue, 0.5, replyRow.userColor.hslLightness, 0.1))
}
}
data: [
replyRow, wrapper.main,
]
}
Rectangle {
color: 'yellow'
Layout.preferredWidth: 100
Layout.preferredHeight: 20
Layout.alignment: Qt.AlignRight | Qt.AlignTop
}
},
Rectangle {
width: Math.min(contentColumn.implicitWidth, contentColumn.width)
height: contentColumn.implicitHeight
color: "blue"
opacity: 0.2
}
]
EventDelegateChoice {
roleValues: [
MtxEvent.TextMessage,
MtxEvent.NoticeMessage,
]
TextArea {
required property string body
TextMessage {
id: textMes
keepFullText: true
required property string userId
required property string userName
Layout.fillWidth: true
//Layout.maximumWidth: implicitWidth
width: parent.width
text: body
}
}
EventDelegateChoice {
roleValues: [
]
TextArea {
width: parent.width
text: "Unsupported"
MatrixText {
Layout.fillWidth: true
required property string typeString
text: "Unsupported: " + typeString
required property string userId
required property string userName
}
}
}
......
......@@ -3,17 +3,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import ".."
import QtQuick.Controls 2.3
import im.nheko 1.0
import QtQuick.Controls
import QtQuick.Layouts
import im.nheko
MatrixText {
required property string body
required property bool isOnlyEmoji
required property bool isReply
required property bool keepFullText
required property string formatted
required property string formattedBody
property string copyText: selectedText ? getText(selectionStart, selectionEnd) : body
property int metadataWidth
property int metadataWidth: 100
property bool fitsMetadata: false //positionAt(width,height-4) == positionAt(width-metadataWidth-10, height-4)
// table border-collapse doesn't seem to work
......@@ -38,9 +40,8 @@ MatrixText {
background-color: " + palette.text + ";
}" : "") + // TODO(Nico): Figure out how to support mobile
"</style>
" + formatted.replace(/<del>/g, "<s>").replace(/<\/del>/g, "</s>").replace(/<strike>/g, "<s>").replace(/<\/strike>/g, "</s>")
width: parent?.width ?? 0
height: !keepFullText ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : implicitHeight
" + formattedBody.replace(/<del>/g, "<s>").replace(/<\/del>/g, "</s>").replace(/<strike>/g, "<s>").replace(/<\/strike>/g, "</s>")
Layout.maximumHeight: !keepFullText ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : implicitHeight
clip: !keepFullText
selectByMouse: !Settings.mobileMode && !isReply
enabled: !Settings.mobileMode
......
......@@ -85,6 +85,7 @@ EventDelegateChooser::componentComplete()
{
QQuickItem::componentComplete();
// eventIncubator.reset(eventIndex);
// eventIncubator.forceCompletion();
}
void
......@@ -104,6 +105,7 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
QHash<int, int> roleToPropIdx;
std::vector<QModelRoleData> roles;
bool isReplyNeeded = false;
// Workaround for https://bugreports.qt.io/browse/QTBUG-98846
QHash<QString, RequiredPropertyKey> requiredProperties;
......@@ -121,7 +123,10 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
if (!prop.isRequired() && !requiredProperties.contains(prop.name()))
continue;
if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
if (prop.name() == std::string_view("isReply")) {
isReplyNeeded = true;
roleToPropIdx.insert(-1, i);
} else if (auto role = nameToRole.find(prop.name()); role != nameToRole.end()) {
roleToPropIdx.insert(*role, i);
roles.emplace_back(*role);
......@@ -134,13 +139,26 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
nhlog::ui()->debug("Querying data for id {}", currentId.toStdString());
chooser.room_->multiData(currentId, forReply ? chooser.eventId_ : QString(), roles);
QVariantMap rolesToSet;
for (const auto &role : roles) {
const auto &roleName = roleNames[role.role()];
nhlog::ui()->critical("Setting role {}, {}", role.role(), roleName.toStdString());
nhlog::ui()->critical("Setting role {}, {} to {}",
role.role(),
roleName.toStdString(),
role.data().toString().toStdString());
nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[role.role()]).name());
mo->property(roleToPropIdx[role.role()]).write(obj, role.data());
rolesToSet.insert(roleName, role.data());
if (const auto &req = requiredProperties.find(roleName); req != requiredProperties.end())
QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req);
}
if (isReplyNeeded) {
const auto roleName = QByteArray("isReply");
nhlog::ui()->critical("Setting role {} to {}", roleName.toStdString(), forReply);
nhlog::ui()->critical("Setting {}", mo->property(roleToPropIdx[-1]).name());
mo->property(roleToPropIdx[-1]).write(obj, forReply);
if (const auto &req = requiredProperties.find(roleName); req != requiredProperties.end())
QQmlIncubatorPrivate::get(this)->requiredProperties()->remove(*req);
......
......@@ -54,6 +54,7 @@ class EventDelegateChooser : public QQuickItem
public:
Q_PROPERTY(QQmlListProperty<EventDelegateChoice> choices READ choices CONSTANT FINAL)
Q_PROPERTY(QQuickItem *main READ main NOTIFY mainChanged FINAL)
Q_PROPERTY(QQuickItem *reply READ reply NOTIFY replyChanged FINAL)
Q_PROPERTY(TimelineModel *room READ room WRITE setRoom NOTIFY roomChanged REQUIRED FINAL)
Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged REQUIRED FINAL)
Q_PROPERTY(QString replyTo READ replyTo WRITE setReplyTo NOTIFY replyToChanged REQUIRED FINAL)
......@@ -64,6 +65,10 @@ public:
{
return qobject_cast<QQuickItem *>(eventIncubator.object());
}
[[nodiscard]] QQuickItem *reply() const
{
return qobject_cast<QQuickItem *>(replyIncubator.object());
}
void setRoom(TimelineModel *m)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment