Reply to messages with images

Reply to messages with images (and technically any other attachment file type)
This commit is contained in:
James Graham
2025-03-22 11:16:50 +00:00
parent 9164660d19
commit 1ca4120fd9
4 changed files with 41 additions and 21 deletions

View File

@@ -163,15 +163,26 @@ QQC2.Control {
Layout.fillWidth: true Layout.fillWidth: true
} }
Loader { Loader {
id: paneLoader id: replyLoader
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing Layout.margins: Kirigami.Units.largeSpacing
Layout.preferredHeight: active ? item.implicitHeight : 0 Layout.preferredHeight: active ? item.implicitHeight : 0
active: visible active: visible
visible: root.currentRoom.mainCache.replyId.length > 0 || root.currentRoom.mainCache.attachmentPath.length > 0 visible: root.currentRoom.mainCache.replyId.length > 0
sourceComponent: root.currentRoom.mainCache.replyId.length > 0 ? replyPane : attachmentPane sourceComponent: replyPane
}
Loader {
id: attachLoader
Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing
Layout.preferredHeight: active ? item.implicitHeight : 0
active: visible
visible: root.currentRoom.mainCache.attachmentPath.length > 0
sourceComponent: attachmentPane
} }
RowLayout { RowLayout {
QQC2.ScrollView { QQC2.ScrollView {
@@ -349,7 +360,7 @@ QQC2.Control {
replyEventId: _private.chatBarCache.replyId replyEventId: _private.chatBarCache.replyId
replyAuthor: _private.chatBarCache.relationAuthor replyAuthor: _private.chatBarCache.relationAuthor
replyContentModel: _private.chatBarCache.relationEventContentModel replyContentModel: _private.chatBarCache.relationEventContentModel
Message.maxContentWidth: paneLoader.item.width Message.maxContentWidth: replyLoader.item.width
} }
QQC2.Button { QQC2.Button {
id: cancelButton id: cancelButton

View File

@@ -213,11 +213,14 @@ void ChatBarCache::setAttachmentPath(const QString &attachmentPath)
return; return;
} }
m_attachmentPath = attachmentPath; m_attachmentPath = attachmentPath;
Q_EMIT attachmentPathChanged();
#if (Quotient_VERSION_MINOR < 10 && Quotient_VERSION_PATCH < 3) || Quotient_VERSION_MINOR < 9
m_relationType = None; m_relationType = None;
const auto oldEventId = std::exchange(m_relationId, QString()); const auto oldEventId = std::exchange(m_relationId, QString());
delete m_relationContentModel; delete m_relationContentModel;
Q_EMIT attachmentPathChanged();
Q_EMIT relationIdChanged(oldEventId, m_relationId); Q_EMIT relationIdChanged(oldEventId, m_relationId);
#endif
} }
void ChatBarCache::clearRelations() void ChatBarCache::clearRelations()
@@ -302,8 +305,19 @@ void ChatBarCache::postMessage()
return; return;
} }
bool isReply = !replyId().isEmpty();
std::optional<Quotient::EventRelation> relatesTo = std::nullopt;
if (!threadId().isEmpty()) {
relatesTo = Quotient::EventRelation::replyInThread(threadId(), !isReply, isReply ? replyId() : threadId());
} else if (!editId().isEmpty()) {
relatesTo = Quotient::EventRelation::replace(editId());
} else if (isReply) {
relatesTo = Quotient::EventRelation::replyTo(replyId());
}
if (!attachmentPath().isEmpty()) { if (!attachmentPath().isEmpty()) {
room->uploadFile(QUrl(attachmentPath()), sendText()); room->uploadFile(QUrl(attachmentPath()), sendText(), relatesTo);
clearCache(); clearCache();
return; return;
} }
@@ -321,22 +335,12 @@ void ChatBarCache::postMessage()
return; return;
} }
bool isReply = !replyId().isEmpty();
const auto replyIt = room->findInTimeline(replyId()); const auto replyIt = room->findInTimeline(replyId());
if (replyIt == room->historyEdge()) { if (replyIt == room->historyEdge()) {
isReply = false; isReply = false;
} }
auto content = std::make_unique<Quotient::EventContent::TextContent>(sendText, u"text/html"_s); auto content = std::make_unique<Quotient::EventContent::TextContent>(sendText, u"text/html"_s);
std::optional<Quotient::EventRelation> relatesTo = std::nullopt;
if (!threadId().isEmpty()) {
relatesTo = Quotient::EventRelation::replyInThread(threadId(), !isReply, isReply ? replyId() : threadId());
} else if (!editId().isEmpty()) {
relatesTo = Quotient::EventRelation::replace(editId());
} else if (isReply) {
relatesTo = Quotient::EventRelation::replyTo(replyId());
}
room->post<Quotient::RoomMessageEvent>(text(), *std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result), std::move(content), relatesTo); room->post<Quotient::RoomMessageEvent>(text(), *std::get<std::optional<Quotient::RoomMessageEvent::MsgType>>(result), std::move(content), relatesTo);
clearCache(); clearCache();

View File

@@ -221,12 +221,12 @@ void NeoChatRoom::setFileUploadingProgress(int value)
Q_EMIT fileUploadingProgressChanged(); Q_EMIT fileUploadingProgressChanged();
} }
void NeoChatRoom::uploadFile(const QUrl &url, const QString &body) void NeoChatRoom::uploadFile(const QUrl &url, const QString &body, std::optional<EventRelation> relatesTo)
{ {
doUploadFile(url, body); doUploadFile(url, body, relatesTo);
} }
QCoro::Task<void> NeoChatRoom::doUploadFile(QUrl url, QString body) QCoro::Task<void> NeoChatRoom::doUploadFile(QUrl url, QString body, std::optional<EventRelation> relatesTo)
{ {
if (url.isEmpty()) { if (url.isEmpty()) {
co_return; co_return;
@@ -250,7 +250,12 @@ QCoro::Task<void> NeoChatRoom::doUploadFile(QUrl url, QString body)
} else { } else {
content = new EventContent::FileContent(url, fileInfo.size(), mime, fileInfo.fileName()); content = new EventContent::FileContent(url, fileInfo.size(), mime, fileInfo.fileName());
} }
#if Quotient_VERSION_MINOR > 9 || (Quotient_VERSION_MINOR == 9 && Quotient_VERSION_PATCH > 2)
QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr<EventContent::FileContentBase>(content), relatesTo);
#else
QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr<EventContent::FileContentBase>(content)); QString txnId = postFile(body.isEmpty() ? url.fileName() : body, std::unique_ptr<EventContent::FileContentBase>(content));
#endif
setHasFileUploading(true); setHasFileUploading(true);
connect(this, &Room::fileTransferCompleted, [this, txnId](const QString &id, FileSourceInfo) { connect(this, &Room::fileTransferCompleted, [this, txnId](const QString &id, FileSourceInfo) {
if (id == txnId) { if (id == txnId) {

View File

@@ -636,7 +636,7 @@ private:
void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override; void onRedaction(const Quotient::RoomEvent &prevEvent, const Quotient::RoomEvent &after) override;
QCoro::Task<void> doDeleteMessagesByUser(const QString &user, QString reason); QCoro::Task<void> doDeleteMessagesByUser(const QString &user, QString reason);
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString()); QCoro::Task<void> doUploadFile(QUrl url, QString body = QString(), std::optional<Quotient::EventRelation> relatesTo = std::nullopt);
std::unique_ptr<Quotient::RoomEvent> m_cachedEvent; std::unique_ptr<Quotient::RoomEvent> m_cachedEvent;
@@ -694,7 +694,7 @@ public Q_SLOTS:
* @param url the location of the file to be uploaded. * @param url the location of the file to be uploaded.
* @param body the caption that is to be given to the file. * @param body the caption that is to be given to the file.
*/ */
void uploadFile(const QUrl &url, const QString &body = QString()); void uploadFile(const QUrl &url, const QString &body = QString(), std::optional<Quotient::EventRelation> relatesTo = std::nullopt);
/** /**
* @brief Accept an invitation for the local user to join the room. * @brief Accept an invitation for the local user to join the room.