Inline Edits

Edit text messages inline instead of in the chatbar
This commit is contained in:
James Graham
2023-02-12 13:46:23 +00:00
parent aaa26571d1
commit 5482aad7ba
14 changed files with 327 additions and 51 deletions

View File

@@ -17,6 +17,7 @@
#include "models/actionsmodel.h"
#include "models/customemojimodel.h"
#include "neochatconfig.h"
#include "neochatroom.h"
#include "neochatuser.h"
#include "roommanager.h"
@@ -58,9 +59,9 @@ void ActionsHandler::setRoom(NeoChatRoom *room)
Q_EMIT roomChanged();
}
void ActionsHandler::handleMessage()
void ActionsHandler::handleNewMessage()
{
checkEffects();
checkEffects(m_room->chatBoxText());
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
QUrl url(m_room->chatBoxAttachmentPath());
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
@@ -69,13 +70,39 @@ void ActionsHandler::handleMessage()
m_room->setChatBoxText({});
return;
}
QString handledText = m_room->chatBoxText();
std::sort(m_room->mentions()->begin(), m_room->mentions()->end(), [](const auto &a, const auto &b) -> bool {
QString handledText = m_room->chatBoxText();
handledText = handleMentions(handledText);
handleMessage(m_room->chatBoxText(), handledText);
}
void ActionsHandler::handleEdit()
{
checkEffects(m_room->editText());
QString handledText = m_room->editText();
handledText = handleMentions(handledText, true);
handleMessage(m_room->editText(), handledText, true);
}
QString ActionsHandler::handleMentions(QString handledText, const bool &isEdit)
{
if (!m_room) {
return QString();
}
QVector<Mention> *mentions;
if (isEdit) {
mentions = m_room->editMentions();
} else {
mentions = m_room->mentions();
}
std::sort(mentions->begin(), mentions->end(), [](const auto &a, const auto &b) -> bool {
return a.cursor.anchor() > b.cursor.anchor();
});
for (const auto &mention : *m_room->mentions()) {
for (const auto &mention : *mentions) {
if (mention.text.isEmpty() || mention.id.isEmpty()) {
continue;
}
@@ -83,11 +110,16 @@ void ActionsHandler::handleMessage()
mention.cursor.position() - mention.cursor.anchor(),
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text, mention.id));
}
m_room->mentions()->clear();
mentions->clear();
return handledText;
}
void ActionsHandler::handleMessage(const QString &text, QString handledText, const bool &isEdit)
{
if (NeoChatConfig::allowQuickEdit()) {
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
auto match = sed.match(m_room->chatBoxText());
auto match = sed.match(text);
if (match.hasMatch()) {
const QString regex = match.captured(1);
const QString replacement = match.captured(2).toHtmlEscaped();
@@ -146,13 +178,13 @@ void ActionsHandler::handleMessage()
if (handledText.length() == 0) {
return;
}
m_room->postMessage(m_room->chatBoxText(), handledText, messageType, m_room->chatBoxReplyId(), m_room->chatBoxEditId());
m_room->postMessage(text, handledText, messageType, m_room->chatBoxReplyId(), isEdit ? m_room->chatBoxEditId() : "");
}
void ActionsHandler::checkEffects()
void ActionsHandler::checkEffects(const QString &text)
{
std::optional<QString> effect = std::nullopt;
const auto &text = m_room->chatBoxText();
if (text.contains("\u2744")) {
effect = QLatin1String("snowflake");
} else if (text.contains("\u1F386")) {

View File

@@ -33,14 +33,22 @@ Q_SIGNALS:
public Q_SLOTS:
/// \brief Post a message.
///
/// This also interprets commands if any.
void handleMessage();
/**
* @brief Pre-process text and send message.
*/
void handleNewMessage();
/**
* @brief Pre-process text and send edit.
*/
void handleEdit();
private:
NeoChatRoom *m_room = nullptr;
void checkEffects();
void checkEffects(const QString &text);
QString handleMentions(QString handledText, const bool &isEdit = false);
void handleMessage(const QString &text, QString handledText, const bool &isEdit = false);
};
QString markdownToHTML(const QString &markdown);

View File

@@ -108,11 +108,16 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
static QPointer<NeoChatRoom> previousRoom = nullptr;
if (previousRoom) {
disconnect(previousRoom, &NeoChatRoom::chatBoxTextChanged, this, nullptr);
disconnect(previousRoom, &NeoChatRoom::editTextChanged, this, nullptr);
}
previousRoom = m_room;
connect(m_room, &NeoChatRoom::chatBoxTextChanged, this, [this]() {
int start = completionStartIndex();
m_completionModel->setText(m_room->chatBoxText().mid(start, cursorPosition() - start), m_room->chatBoxText().mid(start));
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
});
connect(m_room, &NeoChatRoom::editTextChanged, this, [this]() {
int start = completionStartIndex();
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
});
});
connect(this, &ChatDocumentHandler::documentChanged, this, [this]() {
@@ -123,7 +128,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
return;
}
int start = completionStartIndex();
m_completionModel->setText(m_room->chatBoxText().mid(start, cursorPosition() - start), m_room->chatBoxText().mid(start));
m_completionModel->setText(getText().mid(start, cursorPosition() - start), getText().mid(start));
});
}
@@ -138,7 +143,7 @@ int ChatDocumentHandler::completionStartIndex() const
#else
const auto cursor = cursorPosition();
#endif
const auto &text = m_room->chatBoxText();
const auto &text = getText();
auto start = std::min(cursor, text.size()) - 1;
while (start > -1) {
if (text.at(start) == QLatin1Char(' ')) {
@@ -150,6 +155,20 @@ int ChatDocumentHandler::completionStartIndex() const
return start;
}
bool ChatDocumentHandler::isEdit() const
{
return m_isEdit;
}
void ChatDocumentHandler::setIsEdit(bool edit)
{
if (edit == m_isEdit) {
return;
}
m_isEdit = edit;
Q_EMIT isEditChanged();
}
QQuickTextDocument *ChatDocumentHandler::document() const
{
return m_document;
@@ -204,7 +223,7 @@ void ChatDocumentHandler::complete(int index)
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
auto id = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = m_room->chatBoxText();
auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1);
QTextCursor cursor(document()->textDocument());
cursor.setPosition(at);
@@ -213,11 +232,11 @@ void ChatDocumentHandler::complete(int index)
cursor.setPosition(at);
cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor);
cursor.setKeepPositionOnInsert(true);
m_room->mentions()->push_back({cursor, name, 0, 0, id});
pushMention({cursor, name, 0, 0, id});
m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = m_room->chatBoxText();
auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('/'));
QTextCursor cursor(document()->textDocument());
cursor.setPosition(at);
@@ -225,7 +244,7 @@ void ChatDocumentHandler::complete(int index)
cursor.insertText(QStringLiteral("/%1 ").arg(command));
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
auto text = m_room->chatBoxText();
auto text = getText();
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
QTextCursor cursor(document()->textDocument());
cursor.setPosition(at);
@@ -234,11 +253,11 @@ void ChatDocumentHandler::complete(int index)
cursor.setPosition(at);
cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor);
cursor.setKeepPositionOnInsert(true);
m_room->mentions()->push_back({cursor, alias, 0, 0, alias});
pushMention({cursor, alias, 0, 0, alias});
m_highlighter->rehighlight();
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
auto text = m_room->chatBoxText();
auto text = getText();
auto at = text.lastIndexOf(QLatin1Char(':'));
QTextCursor cursor(document()->textDocument());
cursor.setPosition(at);
@@ -281,3 +300,27 @@ void ChatDocumentHandler::setSelectionEnd(int position)
m_selectionEnd = position;
Q_EMIT selectionEndChanged();
}
QString ChatDocumentHandler::getText() const
{
if (!m_room) {
return QString();
}
if (m_isEdit) {
return m_room->editText();
} else {
return m_room->chatBoxText();
}
}
void ChatDocumentHandler::pushMention(const Mention mention) const
{
if (!m_room) {
return;
}
if (m_isEdit) {
m_room->editMentions()->push_back(mention);
} else {
m_room->mentions()->push_back(mention);
}
}

View File

@@ -9,6 +9,7 @@
#include "models/completionmodel.h"
#include "models/userlistmodel.h"
#include "neochatroom.h"
class QTextDocument;
class NeoChatRoom;
@@ -17,6 +18,14 @@ class SyntaxHighlighter;
class ChatDocumentHandler : public QObject
{
Q_OBJECT
/**
* @brief Is the instance being used to handle an edit message.
*
* This is needed to ensure that the text and mentions are saved and retrieved
* from the correct parameters in the assigned room.
*/
Q_PROPERTY(bool isEdit READ isEdit WRITE setIsEdit NOTIFY isEditChanged)
Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
@@ -24,11 +33,14 @@ class ChatDocumentHandler : public QObject
Q_PROPERTY(CompletionModel *completionModel READ completionModel NOTIFY completionModelChanged)
Q_PROPERTY(NeoChatRoom *room READ room NOTIFY roomChanged)
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
public:
explicit ChatDocumentHandler(QObject *parent = nullptr);
[[nodiscard]] bool isEdit() const;
void setIsEdit(bool edit);
[[nodiscard]] QQuickTextDocument *document() const;
void setDocument(QQuickTextDocument *document);
@@ -49,6 +61,7 @@ public:
void updateCompletions();
CompletionModel *completionModel() const;
Q_SIGNALS:
void isEditChanged();
void documentChanged();
void cursorPositionChanged();
void roomChanged();
@@ -59,6 +72,8 @@ Q_SIGNALS:
private:
int completionStartIndex() const;
bool m_isEdit;
QQuickTextDocument *m_document;
NeoChatRoom *m_room = nullptr;
@@ -68,6 +83,9 @@ private:
int m_selectionStart;
int m_selectionEnd;
QString getText() const;
void pushMention(const Mention mention) const;
SyntaxHighlighter *m_highlighter = nullptr;
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;

View File

@@ -1626,6 +1626,17 @@ void NeoChatRoom::setChatBoxText(const QString &text)
Q_EMIT chatBoxTextChanged();
}
QString NeoChatRoom::editText() const
{
return m_editText;
}
void NeoChatRoom::setEditText(const QString &text)
{
m_editText = text;
Q_EMIT editTextChanged();
}
QString NeoChatRoom::chatBoxReplyId() const
{
return m_chatBoxReplyId;
@@ -1702,6 +1713,11 @@ QVector<Mention> *NeoChatRoom::mentions()
return &m_mentions;
}
QVector<Mention> *NeoChatRoom::editMentions()
{
return &m_editMentions;
}
QString NeoChatRoom::savedText() const
{
return m_savedText;

View File

@@ -79,6 +79,11 @@ class NeoChatRoom : public Quotient::Room
// Due to problems with QTextDocument, unlike the other properties here, chatBoxText is *not* used to store the text when switching rooms
Q_PROPERTY(QString chatBoxText READ chatBoxText WRITE setChatBoxText NOTIFY chatBoxTextChanged)
/**
* @brief The text for any message currently being edited in the room.
*/
Q_PROPERTY(QString editText READ editText WRITE setEditText NOTIFY editTextChanged)
Q_PROPERTY(QString chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
@@ -271,6 +276,9 @@ public:
QString chatBoxText() const;
void setChatBoxText(const QString &text);
QString editText() const;
void setEditText(const QString &text);
QString chatBoxReplyId() const;
void setChatBoxReplyId(const QString &replyId);
@@ -288,6 +296,11 @@ public:
QVector<Mention> *mentions();
/**
* @brief Vector of mentions in the current edit text.
*/
QVector<Mention> *editMentions();
QString savedText() const;
void setSavedText(const QString &savedText);
@@ -337,10 +350,12 @@ private:
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
QString m_chatBoxText;
QString m_editText;
QString m_chatBoxReplyId;
QString m_chatBoxEditId;
QString m_chatBoxAttachmentPath;
QVector<Mention> m_mentions;
QVector<Mention> m_editMentions;
QString m_savedText;
#ifdef QUOTIENT_07
QCache<QString, PollHandler> m_polls;
@@ -363,6 +378,7 @@ Q_SIGNALS:
void pushNotificationStateChanged(PushNotificationState::State state);
void showMessage(MessageType messageType, const QString &message);
void chatBoxTextChanged();
void editTextChanged();
void chatBoxReplyIdChanged();
void chatBoxEditIdChanged();
void chatBoxAttachmentPathChanged();

View File

@@ -14,9 +14,7 @@ QQC2.Control {
property alias textField: textField
property bool isReplying: currentRoom.chatBoxReplyId.length > 0
property bool isEditing: currentRoom.chatBoxEditId.length > 0
property bool replyPaneVisible: isReplying || isEditing
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser ?? currentRoom.chatBoxEditUser
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
signal messageSent()
@@ -122,7 +120,7 @@ QQC2.Control {
leftPadding: LayoutMirroring.enabled ? actionsRow.width : (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing)
rightPadding: LayoutMirroring.enabled ? (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing) : actionsRow.width
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : currentRoom.chatBoxEditId.length > 0 ? i18n("Edit Message") : currentRoom.usesEncryption ? i18n("Send an encrypted message…") : currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
placeholderText: readOnly ? i18n("This room is encrypted. Build libQuotient with encryption enabled to send encrypted messages.") : currentRoom.usesEncryption ? i18n("Send an encrypted message…") : currentRoom.chatBoxAttachmentPath.length > 0 ? i18n("Set an attachment caption...") : i18n("Send a message…")
verticalAlignment: TextEdit.AlignVCenter
wrapMode: Text.Wrap
readOnly: (currentRoom.usesEncryption && !Controller.encryptionSupported)
@@ -198,8 +196,8 @@ QQC2.Control {
anchors.rightMargin: root.width > chatBoxMaxWidth ? 0 : (chatBarScrollView.QQC2.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 3.5 : Kirigami.Units.largeSpacing)
active: visible
visible: root.replyPaneVisible || root.attachmentPaneVisible
sourceComponent: root.replyPaneVisible ? replyPane : attachmentPane
visible: root.isReplying || root.attachmentPaneVisible
sourceComponent: root.isReplying ? replyPane : attachmentPane
}
Component {
id: replyPane
@@ -207,8 +205,7 @@ QQC2.Control {
userName: root.replyUser ? root.replyUser.displayName : ""
userColor: root.replyUser ? root.replyUser.color : ""
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : ""
isReply: root.isReplying
text: isEditing ? currentRoom.chatBoxEditMessage : currentRoom.chatBoxReplyMessage
text: currentRoom.chatBoxReplyMessage
}
}
Component {
@@ -263,14 +260,13 @@ QQC2.Control {
anchors.right: parent.right
anchors.rightMargin: (root.width - chatBoxMaxWidth) / 2 + Kirigami.Units.largeSpacing + (chatBarScrollView.QQC2.ScrollBar.vertical.visible && !(root.width > chatBoxMaxWidth) ? Kirigami.Units.largeSpacing * 2.5 : 0)
visible: root.replyPaneVisible
visible: root.isReplying
display: QQC2.AbstractButton.IconOnly
action: Kirigami.Action {
text: root.isReplying ? i18nc("@action:button", "Cancel reply") : i18nc("@action:button", "Cancel edit")
text: i18nc("@action:button", "Cancel reply")
icon.name: "dialog-close"
onTriggered: {
currentRoom.chatBoxReplyId = "";
currentRoom.chatBoxEditId = "";
currentRoom.chatBoxAttachmentPath = "";
root.forceActiveFocus()
}
@@ -356,15 +352,6 @@ QQC2.Control {
}
}
Connections {
target: currentRoom
function onChatBoxEditIdChanged() {
if (currentRoom.chatBoxEditMessage.length > 0) {
textField.text = currentRoom.chatBoxEditMessage
}
}
}
ChatDocumentHandler {
id: documentHandler
document: textField.textDocument
@@ -398,12 +385,11 @@ QQC2.Control {
}
function postMessage() {
actionsHandler.handleMessage();
actionsHandler.handleNewMessage();
repeatTimer.stop()
currentRoom.markAllMessagesAsRead();
textField.clear();
currentRoom.chatBoxReplyId = "";
currentRoom.chatBoxEditId = "";
messageSent()
}
}

View File

@@ -22,7 +22,7 @@ QQC2.Popup {
connection: Controller.activeConnection
}
required property var chatDocumentHandler
property var chatDocumentHandler
Component.onCompleted: {
chatDocumentHandler.completionModel.roomListModel = roomListModel;
}

View File

@@ -15,7 +15,6 @@ GridLayout {
property string userName
property color userColor: Kirigami.Theme.highlightColor
property var userAvatar: ""
property bool isReply
property var text
rows: 3
@@ -30,7 +29,7 @@ GridLayout {
Layout.columnSpan: 3
topPadding: Kirigami.Units.smallSpacing
text: isReply ? i18n("Replying to:") : i18n("Editing message:")
text: i18n("Replying to:")
}
Rectangle {
id: verticalBorder

View File

@@ -21,8 +21,14 @@ TimelineContainer {
RichLabel {
id: label
Layout.fillWidth: true
visible: currentRoom.chatBoxEditId !== model.eventId
isEmote: messageDelegate.isEmote
}
MessageEditComponent {
Layout.fillWidth: true
messageId: model.eventId
visible: currentRoom.chatBoxEditId === model.eventId
}
Loader {
id: linkPreviewLoader
Layout.fillWidth: true

View File

@@ -0,0 +1,149 @@
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.15 as Kirigami
import org.kde.neochat 1.0
QQC2.TextArea {
id: root
property string messageId
Layout.fillWidth: true
Layout.minimumHeight: editButtons.height + topPadding + bottomPadding
Layout.preferredWidth: editTextMetrics.advanceWidth + rightPadding + Kirigami.Units.smallSpacing + Kirigami.Units.gridUnit
rightPadding: editButtons.width + editButtons.anchors.rightMargin * 2
color: Kirigami.Theme.textColor
verticalAlignment: TextEdit.AlignVCenter
wrapMode: Text.Wrap
onVisibleChanged: {
if (visible) {
forceActiveFocus();
root.cursorPosition = root.length;
}
}
onTextChanged: {
currentRoom.editText = text
}
Keys.onEnterPressed: {
if (completionMenu.visible) {
completionMenu.complete()
} else if (event.modifiers & Qt.ShiftModifier) {
root.insert(cursorPosition, "\n")
} else {
root.postEdit();
}
}
Keys.onReturnPressed: {
if (completionMenu.visible) {
completionMenu.complete()
} else if (event.modifiers & Qt.ShiftModifier) {
root.insert(cursorPosition, "\n")
} else {
root.postEdit();
}
}
Keys.onTabPressed: {
if (completionMenu.visible) {
completionMenu.complete()
}
}
Keys.onPressed: {
if (event.key === Qt.Key_Up && completionMenu.visible) {
completionMenu.decrementIndex()
} else if (event.key === Qt.Key_Down && completionMenu.visible) {
completionMenu.incrementIndex()
}
}
/**
* This is anchored like this so that control expands properly as the edited
* text grows in length.
*/
RowLayout {
id: editButtons
anchors.verticalCenter: root.verticalCenter
anchors.right: root.right
anchors.rightMargin: Kirigami.Units.smallSpacing
spacing: 0
QQC2.ToolButton {
display: QQC2.AbstractButton.IconOnly
action: Kirigami.Action {
text: i18nc("@action:button", "Confirm edit")
icon.name: "checkmark"
onTriggered: {
root.postEdit();
}
}
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
}
QQC2.ToolButton {
display: QQC2.AbstractButton.IconOnly
action: Kirigami.Action {
text: i18nc("@action:button", "Cancel edit")
icon.name: "dialog-close"
onTriggered: {
currentRoom.chatBoxEditId = "";
}
shortcut: "Escape"
}
QQC2.ToolTip.text: text
QQC2.ToolTip.visible: hovered
}
}
Connections {
target: currentRoom
function onChatBoxEditIdChanged() {
if (currentRoom.chatBoxEditId == messageId && currentRoom.chatBoxEditMessage.length > 0) {
root.text = currentRoom.chatBoxEditMessage
}
}
}
CompletionMenu {
id: completionMenu
height: implicitHeight
y: -height - 5
z: 10
chatDocumentHandler: documentHandler
Behavior on height {
NumberAnimation {
property: "height"
duration: Kirigami.Units.shortDuration
easing.type: Easing.OutCubic
}
}
}
ChatDocumentHandler {
id: documentHandler
isEdit: true
document: root.textDocument
cursorPosition: root.cursorPosition
selectionStart: root.selectionStart
selectionEnd: root.selectionEnd
room: currentRoom // We don't care about saving for edits so this is OK.
}
TextMetrics {
id: editTextMetrics
text: root.text
}
function postEdit() {
actionsHandler.handleEdit();
root.clear();
currentRoom.chatBoxEditId = "";
}
}

View File

@@ -540,7 +540,6 @@ Kirigami.ScrollablePage {
onClicked: {
currentRoom.chatBoxEditId = hoverActions.event.eventId;
currentRoom.chatBoxReplyId = "";
chatBox.chatBar.forceActiveFocus();
}
}
QQC2.Button {

View File

@@ -47,6 +47,7 @@
<file alias="PollDelegate.qml">qml/Component/Timeline/PollDelegate.qml</file>
<file alias="MimeComponent.qml">qml/Component/Timeline/MimeComponent.qml</file>
<file alias="StateComponent.qml">qml/Component/Timeline/StateComponent.qml</file>
<file alias="MessageEditComponent.qml">qml/Component/Timeline/MessageEditComponent.qml</file>
<file alias="LoginStep.qml">qml/Component/Login/LoginStep.qml</file>
<file alias="Login.qml">qml/Component/Login/Login.qml</file>
<file alias="Password.qml">qml/Component/Login/Password.qml</file>

View File

@@ -125,6 +125,9 @@ void RoomManager::openRoomForActiveConnection()
void RoomManager::enterRoom(NeoChatRoom *room)
{
if (m_currentRoom && !m_currentRoom->chatBoxEditId().isEmpty()) {
m_currentRoom->setChatBoxEditId("");
}
if (m_currentRoom && m_chatDocumentHandler) {
// We're doing these things here because it is critical that they are switched at the same time
m_currentRoom->setSavedText(m_chatDocumentHandler->document()->textDocument()->toPlainText());