Compare commits

..

1 Commits

Author SHA1 Message Date
Joshua Goins
1bf23c491a Don't erase existing reply-to relationships when editing messages
Signed-off-by: Joshua Goins <josh@redstrate.com>
2023-01-04 23:36:30 -05:00
13 changed files with 77 additions and 101 deletions

View File

@@ -1,13 +1,13 @@
# Copyright (C) YEAR This file is copyright: # Copyright (C) YEAR This file is copyright:
# This file is distributed under the same license as the neochat package. # This file is distributed under the same license as the neochat package.
# Vit Pelcak <vit@pelcak.org>, 2021, 2022, 2023. # Vit Pelcak <vit@pelcak.org>, 2021, 2022.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: neochat\n" "Project-Id-Version: neochat\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n" "Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2023-01-04 00:48+0000\n" "POT-Creation-Date: 2023-01-04 00:48+0000\n"
"PO-Revision-Date: 2023-01-04 10:14+0100\n" "PO-Revision-Date: 2022-02-11 15:44+0100\n"
"Last-Translator: Vit Pelcak <vit@pelcak.org>\n" "Last-Translator: Vit Pelcak <vit@pelcak.org>\n"
"Language-Team: Czech <kde-i18n-doc@kde.org>\n" "Language-Team: Czech <kde-i18n-doc@kde.org>\n"
"Language: cs\n" "Language: cs\n"
@@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Lokalize 22.12.0\n" "X-Generator: Lokalize 21.12.2\n"
#: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50 #: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50
#: src/actionsmodel.cpp:60 src/actionsmodel.cpp:80 src/actionsmodel.cpp:100 #: src/actionsmodel.cpp:60 src/actionsmodel.cpp:80 src/actionsmodel.cpp:100
@@ -1830,7 +1830,7 @@ msgstr "Označit jako přečtený"
#, kde-format #, kde-format
msgctxt "@action:inmenu" msgctxt "@action:inmenu"
msgid "Copy Address to Clipboard" msgid "Copy Address to Clipboard"
msgstr "Kopírovat adresu do schránky" msgstr ""
#: src/qml/Menu/RoomListContextMenu.qml:65 #: src/qml/Menu/RoomListContextMenu.qml:65
#, kde-format #, kde-format

View File

@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 21.12.3\n" "X-Generator: Lokalize 21.12.3\n"
#: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50 #: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50

View File

@@ -2393,9 +2393,10 @@ msgid "No Topic"
msgstr "Sem Tópico" msgstr "Sem Tópico"
#: src/qml/Panel/RoomDrawer.qml:171 #: src/qml/Panel/RoomDrawer.qml:171
#, kde-format #, fuzzy, kde-format
#| msgid "Options:"
msgid "Options" msgid "Options"
msgstr "Opções" msgstr "Opções:"
#: src/qml/Panel/RoomDrawer.qml:179 #: src/qml/Panel/RoomDrawer.qml:179
#, kde-format #, kde-format

View File

@@ -16,8 +16,8 @@ msgstr ""
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && n"
"%100==4 ? 3 : 0);\n" "%100<=4 ? 2 : 3);\n"
"X-Generator: Poedit 3.2.2\n" "X-Generator: Poedit 3.2.2\n"
#: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50 #: src/actionsmodel.cpp:30 src/actionsmodel.cpp:40 src/actionsmodel.cpp:50

View File

@@ -159,7 +159,7 @@ if(ANDROID)
"zoom-out" "zoom-out"
"image-rotate-left-symbolic" "image-rotate-left-symbolic"
"image-rotate-right-symbolic" "image-rotate-right-symbolic"
"channel-secure-symbolic" "channel-insecure-symbolic"
"download" "download"
"smiley" "smiley"
"tools-check-spelling" "tools-check-spelling"

View File

@@ -52,8 +52,8 @@ QString Clipboard::saveImage(QString localPath) const
} }
QDir dir; QDir dir;
if (!dir.exists(QFileInfo(url.fileName()).absoluteFilePath())) { if (!dir.exists(localPath)) {
dir.mkpath(QFileInfo(url.fileName()).absoluteFilePath()); dir.mkpath(localPath);
} }
image.save(url.toLocalFile()); image.save(url.toLocalFile());

View File

@@ -937,12 +937,24 @@ QVariant MessageEventModel::getLastLocalUserMessageEventId()
if (content.contains("m.new_content")) { if (content.contains("m.new_content")) {
// The message has been edited so we have to return the id of the original message instead of the replacement // The message has been edited so we have to return the id of the original message instead of the replacement
eventId = content["m.relates_to"].toObject()["event_id"].toString(); eventId = content["m.relates_to"].toObject()["event_id"].toString();
e = eventCast<const RoomMessageEvent>(m_currentRoom->findInTimeline(eventId)->event());
if (!e) {
return {};
}
content = e->contentJson();
} else { } else {
// For any message that isn't an edit return the id of the current message // For any message that isn't an edit return the id of the current message
eventId = (*it)->id(); eventId = (*it)->id();
} }
targetMessage.insert("event_id", eventId); targetMessage.insert("event_id", eventId);
targetMessage.insert("formattedBody", content["formatted_body"].toString()); targetMessage.insert("formattedBody", content["formatted_body"].toString());
// keep reply relationship
if (content.contains("m.relates_to")) {
targetMessage.insert("m.relates_to", content["m.relates_to"].toObject());
}
// Need to get the message from the original eventId or body will have * on the front // Need to get the message from the original eventId or body will have * on the front
QModelIndex idx = index(eventIDToIndex(eventId), 0); QModelIndex idx = index(eventIDToIndex(eventId), 0);
targetMessage.insert("message", idx.data(Qt::UserRole + 2)); targetMessage.insert("message", idx.data(Qt::UserRole + 2));

View File

@@ -739,13 +739,25 @@ void NeoChatRoom::postHtmlMessage(const QString &text, const QString &html, Mess
} }
if (isEdit) { if (isEdit) {
QJsonObject content{{"body", text}, {"msgtype", msgTypeToString(type)}, {"format", "org.matrix.custom.html"}, {"formatted_body", html}};
if (isReply) {
content["m.relates_to"] =
QJsonObject {
{"m.in_reply_to",
QJsonObject {
{"event_id", replyEventId}
}
}
};
}
QJsonObject json{ QJsonObject json{
{"type", "m.room.message"}, {"type", "m.room.message"},
{"msgtype", msgTypeToString(type)}, {"msgtype", msgTypeToString(type)},
{"body", "* " + text}, {"body", "* " + text},
{"format", "org.matrix.custom.html"}, {"format", "org.matrix.custom.html"},
{"formatted_body", html}, {"formatted_body", html},
{"m.new_content", QJsonObject{{"body", text}, {"msgtype", msgTypeToString(type)}, {"format", "org.matrix.custom.html"}, {"formatted_body", html}}}, {"m.new_content", content},
{"m.relates_to", QJsonObject{{"rel_type", "m.replace"}, {"event_id", relateToEventId}}}}; {"m.relates_to", QJsonObject{{"rel_type", "m.replace"}, {"event_id", relateToEventId}}}};
postJson("m.room.message", json); postJson("m.room.message", json);

View File

@@ -85,7 +85,6 @@ QQC2.ToolBar {
Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.colorSet: Kirigami.Theme.View
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
Kirigami.SpellChecking.enabled: true
color: Kirigami.Theme.textColor color: Kirigami.Theme.textColor
selectionColor: Kirigami.Theme.highlightColor selectionColor: Kirigami.Theme.highlightColor
@@ -130,6 +129,9 @@ QQC2.ToolBar {
} else if (event.key === Qt.Key_Up && inputField.text.length === 0) { } else if (event.key === Qt.Key_Up && inputField.text.length === 0) {
let editEvent = messageEventModel.getLastLocalUserMessageEventId() let editEvent = messageEventModel.getLastLocalUserMessageEventId()
if (editEvent) { if (editEvent) {
if(editEvent["m.relates_to"]) {
currentRoom.chatBoxReplyId = editEvent["m.relates_to"]["m.in_reply_to"]["event_id"];
}
currentRoom.chatBoxEditId = editEvent["event_id"] currentRoom.chatBoxEditId = editEvent["event_id"]
} }
} else if (event.key === Qt.Key_Up && completionMenu.visible) { } else if (event.key === Qt.Key_Up && completionMenu.visible) {

View File

@@ -15,6 +15,7 @@ Loader {
required property var author required property var author
required property string message required property string message
required property string eventId required property string eventId
property string replyEventId
property var eventType property var eventType
property string formattedBody: "" property string formattedBody: ""
required property string source required property string source
@@ -29,7 +30,7 @@ Loader {
icon.name: "document-edit" icon.name: "document-edit"
onTriggered: { onTriggered: {
currentRoom.chatBoxEditId = eventId; currentRoom.chatBoxEditId = eventId;
currentRoom.chatBoxReplyId = ""; currentRoom.chatBoxReplyId = replyEventId;
} }
visible: author.id === Controller.activeConnection.localUserId && (loadRoot.eventType === MessageEventModel.Emote || loadRoot.eventType === MessageEventModel.Message) visible: author.id === Controller.activeConnection.localUserId && (loadRoot.eventType === MessageEventModel.Emote || loadRoot.eventType === MessageEventModel.Message)
}, },

View File

@@ -537,7 +537,7 @@ Kirigami.ScrollablePage {
icon.name: "document-edit" icon.name: "document-edit"
onClicked: { onClicked: {
currentRoom.chatBoxEditId = hoverActions.event.eventId; currentRoom.chatBoxEditId = hoverActions.event.eventId;
currentRoom.chatBoxReplyId = ""; currentRoom.chatBoxReplyId = hoverActions.event.replyId;
chatBox.focusInputField(); chatBox.focusInputField();
} }
} }
@@ -682,6 +682,7 @@ Kirigami.ScrollablePage {
author: event.author, author: event.author,
message: event.display, message: event.display,
eventId: event.eventId, eventId: event.eventId,
replyEventId: event.replyId,
formattedBody: event.formattedBody, formattedBody: event.formattedBody,
source: event.source, source: event.source,
eventType: event.eventType, eventType: event.eventType,

View File

@@ -117,23 +117,6 @@ Kirigami.OverlayDrawer {
name: room ? room.displayName : "" name: room ? room.displayName : ""
source: room ? ("image://mxc/" + room.avatarMediaId) : "" source: room ? ("image://mxc/" + room.avatarMediaId) : ""
Rectangle {
visible: room.usesEncryption
color: Kirigami.Theme.backgroundColor
width: Kirigami.Units.gridUnit
height: Kirigami.Units.gridUnit
anchors.bottom: parent.bottom
anchors.right: parent.right
radius: width / 2
Kirigami.Icon {
source: "channel-secure-symbolic"
anchors.fill: parent
}
}
} }
ColumnLayout { ColumnLayout {
@@ -215,6 +198,18 @@ Kirigami.OverlayDrawer {
}) })
} }
} }
Kirigami.BasicListItem {
id: inviteButton
Layout.alignment: Qt.AlignRight
icon: "list-add-user"
text: i18n("Invite user to room")
onClicked: {
applicationWindow().pageStack.layers.push("qrc:/InviteUserPage.qml", {room: room})
roomDrawer.close();
}
}
Kirigami.BasicListItem { Kirigami.BasicListItem {
id: favouriteButton id: favouriteButton
@@ -223,34 +218,24 @@ Kirigami.OverlayDrawer {
onClicked: room.isFavourite ? room.removeTag("m.favourite") : room.addTag("m.favourite", 1.0) onClicked: room.isFavourite ? room.removeTag("m.favourite") : room.addTag("m.favourite", 1.0)
} }
Kirigami.BasicListItem {
id: encryptButton
icon: "channel-insecure-symbolic"
enabled: roomDrawer.room.canEncryptRoom
visible: !roomDrawer.room.usesEncryption && Controller.encryptionSupported
text: i18n("Enable encryption")
onClicked: {
let dialog = confirmEncryptionDialog.createObject(applicationWindow(), {room: roomDrawer.room});
roomDrawer.close();
dialog.open();
}
}
Kirigami.ListSectionHeader { Kirigami.ListSectionHeader {
label: i18n("Members") label: i18n("Members")
activeFocusOnTab: false activeFocusOnTab: false
spacing: 0
QQC2.ToolButton {
id: memberSearchToggle
checkable: true
icon.name: "search"
QQC2.ToolTip.text: i18n("Search user in room")
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
}
QQC2.ToolButton {
visible: roomDrawer.room.canSendState("invite")
icon.name: "list-add-user"
onClicked: {
applicationWindow().pageStack.layers.push("qrc:/InviteUserPage.qml", {room: roomDrawer.room})
roomDrawer.close();
}
QQC2.ToolTip.text: i18n("Invite user to room")
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
}
QQC2.Label { QQC2.Label {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
@@ -260,7 +245,6 @@ Kirigami.OverlayDrawer {
Kirigami.SearchField { Kirigami.SearchField {
id: userListSearchField id: userListSearchField
visible: memberSearchToggle.checked
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing - 1 Layout.leftMargin: Kirigami.Units.largeSpacing - 1
@@ -366,4 +350,10 @@ Kirigami.OverlayDrawer {
UserDetailDialog {} UserDetailDialog {}
} }
Component {
id: confirmEncryptionDialog
ConfirmEncryptionDialog {}
}
} }

View File

@@ -22,29 +22,6 @@ Kirigami.ScrollablePage {
rightPadding: 0 rightPadding: 0
ColumnLayout { ColumnLayout {
MobileForm.FormCard {
visible: Controller.encryptionSupported
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18nc("@option:check", "Encryption")
}
MobileForm.FormSwitchDelegate {
id: enableEncryptionSwitch
text: i18n("Enable encryption")
description: i18nc("option:check", "Once enabled, encryption cannot be disabled.")
enabled: room.canEncryptRoom
checked: room.usesEncryption
onToggled: if (checked) {
let dialog = confirmEncryptionDialog.createObject(applicationWindow(), {room: room});
dialog.open();
}
}
}
}
MobileForm.FormCard { MobileForm.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true Layout.fillWidth: true
@@ -155,25 +132,5 @@ Kirigami.ScrollablePage {
} }
} }
} }
Component {
id: confirmEncryptionDialog
ConfirmEncryptionDialog {
onClosed: {
// At the point this is executed, the state in the room is not yet changed.
// The value will be updated when room.onEncryption() emitted.
// This is in case if user simply closed the dialog.
enableEncryptionSwitch.checked = false
}
}
}
Connections {
target: room
onEncryption: {
enableEncryptionSwitch.checked = room.usesEncryption
}
}
} }