Inline Edits
Edit text messages inline instead of in the chatbar
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
#include "models/actionsmodel.h"
|
#include "models/actionsmodel.h"
|
||||||
#include "models/customemojimodel.h"
|
#include "models/customemojimodel.h"
|
||||||
#include "neochatconfig.h"
|
#include "neochatconfig.h"
|
||||||
|
#include "neochatroom.h"
|
||||||
#include "neochatuser.h"
|
#include "neochatuser.h"
|
||||||
#include "roommanager.h"
|
#include "roommanager.h"
|
||||||
|
|
||||||
@@ -58,9 +59,9 @@ void ActionsHandler::setRoom(NeoChatRoom *room)
|
|||||||
Q_EMIT roomChanged();
|
Q_EMIT roomChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionsHandler::handleMessage()
|
void ActionsHandler::handleNewMessage()
|
||||||
{
|
{
|
||||||
checkEffects();
|
checkEffects(m_room->chatBoxText());
|
||||||
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
|
if (!m_room->chatBoxAttachmentPath().isEmpty()) {
|
||||||
QUrl url(m_room->chatBoxAttachmentPath());
|
QUrl url(m_room->chatBoxAttachmentPath());
|
||||||
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
auto path = url.isLocalFile() ? url.toLocalFile() : url.toString();
|
||||||
@@ -69,13 +70,39 @@ void ActionsHandler::handleMessage()
|
|||||||
m_room->setChatBoxText({});
|
m_room->setChatBoxText({});
|
||||||
return;
|
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();
|
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()) {
|
if (mention.text.isEmpty() || mention.id.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -83,11 +110,16 @@ void ActionsHandler::handleMessage()
|
|||||||
mention.cursor.position() - mention.cursor.anchor(),
|
mention.cursor.position() - mention.cursor.anchor(),
|
||||||
QStringLiteral("[%1](https://matrix.to/#/%2)").arg(mention.text, mention.id));
|
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()) {
|
if (NeoChatConfig::allowQuickEdit()) {
|
||||||
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
|
QRegularExpression sed("^s/([^/]*)/([^/]*)(/g)?$");
|
||||||
auto match = sed.match(m_room->chatBoxText());
|
auto match = sed.match(text);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
const QString regex = match.captured(1);
|
const QString regex = match.captured(1);
|
||||||
const QString replacement = match.captured(2).toHtmlEscaped();
|
const QString replacement = match.captured(2).toHtmlEscaped();
|
||||||
@@ -146,13 +178,13 @@ void ActionsHandler::handleMessage()
|
|||||||
if (handledText.length() == 0) {
|
if (handledText.length() == 0) {
|
||||||
return;
|
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;
|
std::optional<QString> effect = std::nullopt;
|
||||||
const auto &text = m_room->chatBoxText();
|
|
||||||
if (text.contains("\u2744")) {
|
if (text.contains("\u2744")) {
|
||||||
effect = QLatin1String("snowflake");
|
effect = QLatin1String("snowflake");
|
||||||
} else if (text.contains("\u1F386")) {
|
} else if (text.contains("\u1F386")) {
|
||||||
|
|||||||
@@ -33,14 +33,22 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
|
|
||||||
/// \brief Post a message.
|
/**
|
||||||
///
|
* @brief Pre-process text and send message.
|
||||||
/// This also interprets commands if any.
|
*/
|
||||||
void handleMessage();
|
void handleNewMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pre-process text and send edit.
|
||||||
|
*/
|
||||||
|
void handleEdit();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NeoChatRoom *m_room = nullptr;
|
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);
|
QString markdownToHTML(const QString &markdown);
|
||||||
|
|||||||
@@ -108,11 +108,16 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
|
|||||||
static QPointer<NeoChatRoom> previousRoom = nullptr;
|
static QPointer<NeoChatRoom> previousRoom = nullptr;
|
||||||
if (previousRoom) {
|
if (previousRoom) {
|
||||||
disconnect(previousRoom, &NeoChatRoom::chatBoxTextChanged, this, nullptr);
|
disconnect(previousRoom, &NeoChatRoom::chatBoxTextChanged, this, nullptr);
|
||||||
|
disconnect(previousRoom, &NeoChatRoom::editTextChanged, this, nullptr);
|
||||||
}
|
}
|
||||||
previousRoom = m_room;
|
previousRoom = m_room;
|
||||||
connect(m_room, &NeoChatRoom::chatBoxTextChanged, this, [this]() {
|
connect(m_room, &NeoChatRoom::chatBoxTextChanged, this, [this]() {
|
||||||
int start = completionStartIndex();
|
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]() {
|
connect(this, &ChatDocumentHandler::documentChanged, this, [this]() {
|
||||||
@@ -123,7 +128,7 @@ ChatDocumentHandler::ChatDocumentHandler(QObject *parent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int start = completionStartIndex();
|
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
|
#else
|
||||||
const auto cursor = cursorPosition();
|
const auto cursor = cursorPosition();
|
||||||
#endif
|
#endif
|
||||||
const auto &text = m_room->chatBoxText();
|
const auto &text = getText();
|
||||||
auto start = std::min(cursor, text.size()) - 1;
|
auto start = std::min(cursor, text.size()) - 1;
|
||||||
while (start > -1) {
|
while (start > -1) {
|
||||||
if (text.at(start) == QLatin1Char(' ')) {
|
if (text.at(start) == QLatin1Char(' ')) {
|
||||||
@@ -150,6 +155,20 @@ int ChatDocumentHandler::completionStartIndex() const
|
|||||||
return start;
|
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
|
QQuickTextDocument *ChatDocumentHandler::document() const
|
||||||
{
|
{
|
||||||
return m_document;
|
return m_document;
|
||||||
@@ -204,7 +223,7 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
|
if (m_completionModel->autoCompletionType() == CompletionModel::User) {
|
||||||
auto name = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Text).toString();
|
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 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);
|
auto at = text.lastIndexOf(QLatin1Char('@'), cursorPosition() - 1);
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -213,11 +232,11 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor);
|
cursor.setPosition(cursor.position() + name.size(), QTextCursor::KeepAnchor);
|
||||||
cursor.setKeepPositionOnInsert(true);
|
cursor.setKeepPositionOnInsert(true);
|
||||||
m_room->mentions()->push_back({cursor, name, 0, 0, id});
|
pushMention({cursor, name, 0, 0, id});
|
||||||
m_highlighter->rehighlight();
|
m_highlighter->rehighlight();
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Command) {
|
||||||
auto command = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
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('/'));
|
auto at = text.lastIndexOf(QLatin1Char('/'));
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -225,7 +244,7 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.insertText(QStringLiteral("/%1 ").arg(command));
|
cursor.insertText(QStringLiteral("/%1 ").arg(command));
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Room) {
|
||||||
auto alias = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::Subtitle).toString();
|
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);
|
auto at = text.lastIndexOf(QLatin1Char('#'), cursorPosition() - 1);
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -234,11 +253,11 @@ void ChatDocumentHandler::complete(int index)
|
|||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor);
|
cursor.setPosition(cursor.position() + alias.size(), QTextCursor::KeepAnchor);
|
||||||
cursor.setKeepPositionOnInsert(true);
|
cursor.setKeepPositionOnInsert(true);
|
||||||
m_room->mentions()->push_back({cursor, alias, 0, 0, alias});
|
pushMention({cursor, alias, 0, 0, alias});
|
||||||
m_highlighter->rehighlight();
|
m_highlighter->rehighlight();
|
||||||
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
|
} else if (m_completionModel->autoCompletionType() == CompletionModel::Emoji) {
|
||||||
auto shortcode = m_completionModel->data(m_completionModel->index(index, 0), CompletionModel::ReplacedText).toString();
|
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(':'));
|
auto at = text.lastIndexOf(QLatin1Char(':'));
|
||||||
QTextCursor cursor(document()->textDocument());
|
QTextCursor cursor(document()->textDocument());
|
||||||
cursor.setPosition(at);
|
cursor.setPosition(at);
|
||||||
@@ -281,3 +300,27 @@ void ChatDocumentHandler::setSelectionEnd(int position)
|
|||||||
m_selectionEnd = position;
|
m_selectionEnd = position;
|
||||||
Q_EMIT selectionEndChanged();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "models/completionmodel.h"
|
#include "models/completionmodel.h"
|
||||||
#include "models/userlistmodel.h"
|
#include "models/userlistmodel.h"
|
||||||
|
#include "neochatroom.h"
|
||||||
|
|
||||||
class QTextDocument;
|
class QTextDocument;
|
||||||
class NeoChatRoom;
|
class NeoChatRoom;
|
||||||
@@ -17,6 +18,14 @@ class SyntaxHighlighter;
|
|||||||
class ChatDocumentHandler : public QObject
|
class ChatDocumentHandler : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
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(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
|
||||||
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
|
Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
|
||||||
Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
|
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(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:
|
public:
|
||||||
explicit ChatDocumentHandler(QObject *parent = nullptr);
|
explicit ChatDocumentHandler(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] bool isEdit() const;
|
||||||
|
void setIsEdit(bool edit);
|
||||||
|
|
||||||
[[nodiscard]] QQuickTextDocument *document() const;
|
[[nodiscard]] QQuickTextDocument *document() const;
|
||||||
void setDocument(QQuickTextDocument *document);
|
void setDocument(QQuickTextDocument *document);
|
||||||
|
|
||||||
@@ -49,6 +61,7 @@ public:
|
|||||||
void updateCompletions();
|
void updateCompletions();
|
||||||
CompletionModel *completionModel() const;
|
CompletionModel *completionModel() const;
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void isEditChanged();
|
||||||
void documentChanged();
|
void documentChanged();
|
||||||
void cursorPositionChanged();
|
void cursorPositionChanged();
|
||||||
void roomChanged();
|
void roomChanged();
|
||||||
@@ -59,6 +72,8 @@ Q_SIGNALS:
|
|||||||
private:
|
private:
|
||||||
int completionStartIndex() const;
|
int completionStartIndex() const;
|
||||||
|
|
||||||
|
bool m_isEdit;
|
||||||
|
|
||||||
QQuickTextDocument *m_document;
|
QQuickTextDocument *m_document;
|
||||||
|
|
||||||
NeoChatRoom *m_room = nullptr;
|
NeoChatRoom *m_room = nullptr;
|
||||||
@@ -68,6 +83,9 @@ private:
|
|||||||
int m_selectionStart;
|
int m_selectionStart;
|
||||||
int m_selectionEnd;
|
int m_selectionEnd;
|
||||||
|
|
||||||
|
QString getText() const;
|
||||||
|
void pushMention(const Mention mention) const;
|
||||||
|
|
||||||
SyntaxHighlighter *m_highlighter = nullptr;
|
SyntaxHighlighter *m_highlighter = nullptr;
|
||||||
|
|
||||||
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;
|
CompletionModel::AutoCompletionType m_completionType = CompletionModel::None;
|
||||||
|
|||||||
@@ -1626,6 +1626,17 @@ void NeoChatRoom::setChatBoxText(const QString &text)
|
|||||||
Q_EMIT chatBoxTextChanged();
|
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
|
QString NeoChatRoom::chatBoxReplyId() const
|
||||||
{
|
{
|
||||||
return m_chatBoxReplyId;
|
return m_chatBoxReplyId;
|
||||||
@@ -1702,6 +1713,11 @@ QVector<Mention> *NeoChatRoom::mentions()
|
|||||||
return &m_mentions;
|
return &m_mentions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<Mention> *NeoChatRoom::editMentions()
|
||||||
|
{
|
||||||
|
return &m_editMentions;
|
||||||
|
}
|
||||||
|
|
||||||
QString NeoChatRoom::savedText() const
|
QString NeoChatRoom::savedText() const
|
||||||
{
|
{
|
||||||
return m_savedText;
|
return m_savedText;
|
||||||
|
|||||||
@@ -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
|
// 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)
|
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 chatBoxReplyId READ chatBoxReplyId WRITE setChatBoxReplyId NOTIFY chatBoxReplyIdChanged)
|
||||||
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
|
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
|
||||||
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
|
||||||
@@ -271,6 +276,9 @@ public:
|
|||||||
QString chatBoxText() const;
|
QString chatBoxText() const;
|
||||||
void setChatBoxText(const QString &text);
|
void setChatBoxText(const QString &text);
|
||||||
|
|
||||||
|
QString editText() const;
|
||||||
|
void setEditText(const QString &text);
|
||||||
|
|
||||||
QString chatBoxReplyId() const;
|
QString chatBoxReplyId() const;
|
||||||
void setChatBoxReplyId(const QString &replyId);
|
void setChatBoxReplyId(const QString &replyId);
|
||||||
|
|
||||||
@@ -288,6 +296,11 @@ public:
|
|||||||
|
|
||||||
QVector<Mention> *mentions();
|
QVector<Mention> *mentions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vector of mentions in the current edit text.
|
||||||
|
*/
|
||||||
|
QVector<Mention> *editMentions();
|
||||||
|
|
||||||
QString savedText() const;
|
QString savedText() const;
|
||||||
void setSavedText(const QString &savedText);
|
void setSavedText(const QString &savedText);
|
||||||
|
|
||||||
@@ -337,10 +350,12 @@ private:
|
|||||||
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
|
QCoro::Task<void> doUploadFile(QUrl url, QString body = QString());
|
||||||
|
|
||||||
QString m_chatBoxText;
|
QString m_chatBoxText;
|
||||||
|
QString m_editText;
|
||||||
QString m_chatBoxReplyId;
|
QString m_chatBoxReplyId;
|
||||||
QString m_chatBoxEditId;
|
QString m_chatBoxEditId;
|
||||||
QString m_chatBoxAttachmentPath;
|
QString m_chatBoxAttachmentPath;
|
||||||
QVector<Mention> m_mentions;
|
QVector<Mention> m_mentions;
|
||||||
|
QVector<Mention> m_editMentions;
|
||||||
QString m_savedText;
|
QString m_savedText;
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
QCache<QString, PollHandler> m_polls;
|
QCache<QString, PollHandler> m_polls;
|
||||||
@@ -363,6 +378,7 @@ Q_SIGNALS:
|
|||||||
void pushNotificationStateChanged(PushNotificationState::State state);
|
void pushNotificationStateChanged(PushNotificationState::State state);
|
||||||
void showMessage(MessageType messageType, const QString &message);
|
void showMessage(MessageType messageType, const QString &message);
|
||||||
void chatBoxTextChanged();
|
void chatBoxTextChanged();
|
||||||
|
void editTextChanged();
|
||||||
void chatBoxReplyIdChanged();
|
void chatBoxReplyIdChanged();
|
||||||
void chatBoxEditIdChanged();
|
void chatBoxEditIdChanged();
|
||||||
void chatBoxAttachmentPathChanged();
|
void chatBoxAttachmentPathChanged();
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ QQC2.Control {
|
|||||||
|
|
||||||
property alias textField: textField
|
property alias textField: textField
|
||||||
property bool isReplying: currentRoom.chatBoxReplyId.length > 0
|
property bool isReplying: currentRoom.chatBoxReplyId.length > 0
|
||||||
property bool isEditing: currentRoom.chatBoxEditId.length > 0
|
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser
|
||||||
property bool replyPaneVisible: isReplying || isEditing
|
|
||||||
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser ?? currentRoom.chatBoxEditUser
|
|
||||||
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
|
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
|
||||||
|
|
||||||
signal messageSent()
|
signal messageSent()
|
||||||
@@ -122,7 +120,7 @@ QQC2.Control {
|
|||||||
leftPadding: LayoutMirroring.enabled ? actionsRow.width : (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing)
|
leftPadding: LayoutMirroring.enabled ? actionsRow.width : (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing)
|
||||||
rightPadding: LayoutMirroring.enabled ? (root.width > chatBoxMaxWidth ? 0 : Kirigami.Units.largeSpacing) : actionsRow.width
|
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
|
verticalAlignment: TextEdit.AlignVCenter
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
readOnly: (currentRoom.usesEncryption && !Controller.encryptionSupported)
|
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)
|
anchors.rightMargin: root.width > chatBoxMaxWidth ? 0 : (chatBarScrollView.QQC2.ScrollBar.vertical.visible ? Kirigami.Units.largeSpacing * 3.5 : Kirigami.Units.largeSpacing)
|
||||||
|
|
||||||
active: visible
|
active: visible
|
||||||
visible: root.replyPaneVisible || root.attachmentPaneVisible
|
visible: root.isReplying || root.attachmentPaneVisible
|
||||||
sourceComponent: root.replyPaneVisible ? replyPane : attachmentPane
|
sourceComponent: root.isReplying ? replyPane : attachmentPane
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
id: replyPane
|
id: replyPane
|
||||||
@@ -207,8 +205,7 @@ QQC2.Control {
|
|||||||
userName: root.replyUser ? root.replyUser.displayName : ""
|
userName: root.replyUser ? root.replyUser.displayName : ""
|
||||||
userColor: root.replyUser ? root.replyUser.color : ""
|
userColor: root.replyUser ? root.replyUser.color : ""
|
||||||
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : ""
|
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : ""
|
||||||
isReply: root.isReplying
|
text: currentRoom.chatBoxReplyMessage
|
||||||
text: isEditing ? currentRoom.chatBoxEditMessage : currentRoom.chatBoxReplyMessage
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
@@ -263,14 +260,13 @@ QQC2.Control {
|
|||||||
anchors.right: parent.right
|
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)
|
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
|
display: QQC2.AbstractButton.IconOnly
|
||||||
action: Kirigami.Action {
|
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"
|
icon.name: "dialog-close"
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
currentRoom.chatBoxReplyId = "";
|
currentRoom.chatBoxReplyId = "";
|
||||||
currentRoom.chatBoxEditId = "";
|
|
||||||
currentRoom.chatBoxAttachmentPath = "";
|
currentRoom.chatBoxAttachmentPath = "";
|
||||||
root.forceActiveFocus()
|
root.forceActiveFocus()
|
||||||
}
|
}
|
||||||
@@ -356,15 +352,6 @@ QQC2.Control {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: currentRoom
|
|
||||||
function onChatBoxEditIdChanged() {
|
|
||||||
if (currentRoom.chatBoxEditMessage.length > 0) {
|
|
||||||
textField.text = currentRoom.chatBoxEditMessage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatDocumentHandler {
|
ChatDocumentHandler {
|
||||||
id: documentHandler
|
id: documentHandler
|
||||||
document: textField.textDocument
|
document: textField.textDocument
|
||||||
@@ -398,12 +385,11 @@ QQC2.Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function postMessage() {
|
function postMessage() {
|
||||||
actionsHandler.handleMessage();
|
actionsHandler.handleNewMessage();
|
||||||
repeatTimer.stop()
|
repeatTimer.stop()
|
||||||
currentRoom.markAllMessagesAsRead();
|
currentRoom.markAllMessagesAsRead();
|
||||||
textField.clear();
|
textField.clear();
|
||||||
currentRoom.chatBoxReplyId = "";
|
currentRoom.chatBoxReplyId = "";
|
||||||
currentRoom.chatBoxEditId = "";
|
|
||||||
messageSent()
|
messageSent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ QQC2.Popup {
|
|||||||
connection: Controller.activeConnection
|
connection: Controller.activeConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
required property var chatDocumentHandler
|
property var chatDocumentHandler
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
chatDocumentHandler.completionModel.roomListModel = roomListModel;
|
chatDocumentHandler.completionModel.roomListModel = roomListModel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ GridLayout {
|
|||||||
property string userName
|
property string userName
|
||||||
property color userColor: Kirigami.Theme.highlightColor
|
property color userColor: Kirigami.Theme.highlightColor
|
||||||
property var userAvatar: ""
|
property var userAvatar: ""
|
||||||
property bool isReply
|
|
||||||
property var text
|
property var text
|
||||||
|
|
||||||
rows: 3
|
rows: 3
|
||||||
@@ -30,7 +29,7 @@ GridLayout {
|
|||||||
Layout.columnSpan: 3
|
Layout.columnSpan: 3
|
||||||
topPadding: Kirigami.Units.smallSpacing
|
topPadding: Kirigami.Units.smallSpacing
|
||||||
|
|
||||||
text: isReply ? i18n("Replying to:") : i18n("Editing message:")
|
text: i18n("Replying to:")
|
||||||
}
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: verticalBorder
|
id: verticalBorder
|
||||||
|
|||||||
@@ -21,8 +21,14 @@ TimelineContainer {
|
|||||||
RichLabel {
|
RichLabel {
|
||||||
id: label
|
id: label
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
visible: currentRoom.chatBoxEditId !== model.eventId
|
||||||
isEmote: messageDelegate.isEmote
|
isEmote: messageDelegate.isEmote
|
||||||
}
|
}
|
||||||
|
MessageEditComponent {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
messageId: model.eventId
|
||||||
|
visible: currentRoom.chatBoxEditId === model.eventId
|
||||||
|
}
|
||||||
Loader {
|
Loader {
|
||||||
id: linkPreviewLoader
|
id: linkPreviewLoader
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|||||||
149
src/qml/Component/Timeline/MessageEditComponent.qml
Normal file
149
src/qml/Component/Timeline/MessageEditComponent.qml
Normal 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 = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -540,7 +540,6 @@ Kirigami.ScrollablePage {
|
|||||||
onClicked: {
|
onClicked: {
|
||||||
currentRoom.chatBoxEditId = hoverActions.event.eventId;
|
currentRoom.chatBoxEditId = hoverActions.event.eventId;
|
||||||
currentRoom.chatBoxReplyId = "";
|
currentRoom.chatBoxReplyId = "";
|
||||||
chatBox.chatBar.forceActiveFocus();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QQC2.Button {
|
QQC2.Button {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
<file alias="PollDelegate.qml">qml/Component/Timeline/PollDelegate.qml</file>
|
<file alias="PollDelegate.qml">qml/Component/Timeline/PollDelegate.qml</file>
|
||||||
<file alias="MimeComponent.qml">qml/Component/Timeline/MimeComponent.qml</file>
|
<file alias="MimeComponent.qml">qml/Component/Timeline/MimeComponent.qml</file>
|
||||||
<file alias="StateComponent.qml">qml/Component/Timeline/StateComponent.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="LoginStep.qml">qml/Component/Login/LoginStep.qml</file>
|
||||||
<file alias="Login.qml">qml/Component/Login/Login.qml</file>
|
<file alias="Login.qml">qml/Component/Login/Login.qml</file>
|
||||||
<file alias="Password.qml">qml/Component/Login/Password.qml</file>
|
<file alias="Password.qml">qml/Component/Login/Password.qml</file>
|
||||||
|
|||||||
@@ -125,6 +125,9 @@ void RoomManager::openRoomForActiveConnection()
|
|||||||
|
|
||||||
void RoomManager::enterRoom(NeoChatRoom *room)
|
void RoomManager::enterRoom(NeoChatRoom *room)
|
||||||
{
|
{
|
||||||
|
if (m_currentRoom && !m_currentRoom->chatBoxEditId().isEmpty()) {
|
||||||
|
m_currentRoom->setChatBoxEditId("");
|
||||||
|
}
|
||||||
if (m_currentRoom && m_chatDocumentHandler) {
|
if (m_currentRoom && m_chatDocumentHandler) {
|
||||||
// We're doing these things here because it is critical that they are switched at the same time
|
// 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());
|
m_currentRoom->setSavedText(m_chatDocumentHandler->document()->textDocument()->toPlainText());
|
||||||
|
|||||||
Reference in New Issue
Block a user