Plumb the adding of message edit text back in.
This should also improve edits where there is code or quotes.
This commit is contained in:
@@ -135,7 +135,23 @@ QString ChatBarCache::relationMessage() const
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (auto [event, _] = m_room->getEvent(m_relationId); event != nullptr) {
|
if (auto [event, _] = m_room->getEvent(m_relationId); event != nullptr) {
|
||||||
return EventHandler::markdownBody(event);
|
return EventHandler::rawMessageBody(*event);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<MessageComponent> ChatBarCache::relationComponents() const
|
||||||
|
{
|
||||||
|
if (!m_room) {
|
||||||
|
qCWarning(ChatBar) << "ChatBarCache:" << __FUNCTION__ << "called after room was deleted";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (m_relationId.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (auto [event, _] = m_room->getEvent(m_relationId); event != nullptr) {
|
||||||
|
TextHandler handler;
|
||||||
|
return TextHandler().textComponents(EventHandler::rawMessageBody(*event), EventHandler::messageBodyInputFormat(*event), m_room, event);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace Quotient
|
|||||||
class RoomMember;
|
class RoomMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MessageComponent;
|
||||||
class NeoChatRoom;
|
class NeoChatRoom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,13 +92,6 @@ class ChatBarCache : public QObject
|
|||||||
*/
|
*/
|
||||||
Q_PROPERTY(bool relationAuthorIsPresent READ relationAuthorIsPresent NOTIFY relationAuthorIsPresentChanged)
|
Q_PROPERTY(bool relationAuthorIsPresent READ relationAuthorIsPresent NOTIFY relationAuthorIsPresentChanged)
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The content of the related message.
|
|
||||||
*
|
|
||||||
* Will be QString() if no related message.
|
|
||||||
*/
|
|
||||||
Q_PROPERTY(QString relationMessage READ relationMessage NOTIFY relationIdChanged)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Whether the chat bar is replying in a thread.
|
* @brief Whether the chat bar is replying in a thread.
|
||||||
*/
|
*/
|
||||||
@@ -147,6 +141,7 @@ public:
|
|||||||
bool relationAuthorIsPresent() const;
|
bool relationAuthorIsPresent() const;
|
||||||
|
|
||||||
QString relationMessage() const;
|
QString relationMessage() const;
|
||||||
|
QList<MessageComponent> relationComponents() const;
|
||||||
|
|
||||||
bool isThreaded() const;
|
bool isThreaded() const;
|
||||||
QString threadId() const;
|
QString threadId() const;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
|
|
||||||
#include <Kirigami/Platform/PlatformTheme>
|
#include <Kirigami/Platform/PlatformTheme>
|
||||||
#include <qtextdocument.h>
|
|
||||||
|
|
||||||
#include "chatbarsyntaxhighlighter.h"
|
#include "chatbarsyntaxhighlighter.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
@@ -165,23 +164,52 @@ void ChatTextItemHelper::initialize()
|
|||||||
int finalCursorPos = cursor.position();
|
int finalCursorPos = cursor.position();
|
||||||
if (doc->isEmpty() && !m_initialFragment.isEmpty()) {
|
if (doc->isEmpty() && !m_initialFragment.isEmpty()) {
|
||||||
cursor.insertFragment(m_initialFragment);
|
cursor.insertFragment(m_initialFragment);
|
||||||
|
if (cursor.blockFormat().bottomMargin() > 0) {
|
||||||
|
auto blockFormat = cursor.blockFormat();
|
||||||
|
blockFormat.setBottomMargin(0);
|
||||||
|
cursor.setBlockFormat(blockFormat);
|
||||||
|
}
|
||||||
finalCursorPos = cursor.position();
|
finalCursorPos = cursor.position();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_fixedStartChars.isEmpty() && doc->characterAt(0) != m_fixedStartChars) {
|
if (!m_fixedStartChars.isEmpty()) {
|
||||||
cursor.movePosition(QTextCursor::Start);
|
cursor.movePosition(QTextCursor::Start);
|
||||||
cursor.insertText(m_fixedStartChars);
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, m_fixedStartChars.length());
|
||||||
finalCursorPos += m_fixedStartChars.length();
|
if (cursor.selectedText() != m_fixedStartChars) {
|
||||||
|
cursor.movePosition(QTextCursor::Start);
|
||||||
|
cursor.insertText(m_fixedStartChars);
|
||||||
|
finalCursorPos += m_fixedStartChars.length();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_fixedStartChars.isEmpty() && doc->characterAt(doc->characterCount()) != m_fixedStartChars) {
|
if (!m_fixedStartChars.isEmpty()) {
|
||||||
cursor.movePosition(QTextCursor::End);
|
cursor.movePosition(QTextCursor::End);
|
||||||
cursor.keepPositionOnInsert();
|
cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, m_fixedEndChars.length());
|
||||||
cursor.insertText(m_fixedEndChars);
|
if (cursor.selectedText() != m_fixedEndChars) {
|
||||||
|
cursor.keepPositionOnInsert();
|
||||||
|
cursor.insertText(m_fixedEndChars);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setCursorPosition(finalCursorPos);
|
setCursorPosition(finalCursorPos);
|
||||||
cursor.endEditBlock();
|
cursor.endEditBlock();
|
||||||
|
|
||||||
|
qWarning() << doc->toRawText();
|
||||||
|
const auto blockProperties = cursor.blockFormat().properties();
|
||||||
|
for (const auto &property : blockProperties.keys()) {
|
||||||
|
qWarning() << static_cast<QTextFormat::Property>(property) << blockProperties[property];
|
||||||
|
}
|
||||||
|
const auto textProperties = cursor.charFormat().properties();
|
||||||
|
for (const auto &property : textProperties.keys()) {
|
||||||
|
qWarning() << static_cast<QTextFormat::Property>(property) << textProperties[property];
|
||||||
|
}
|
||||||
|
const auto currentList = cursor.currentList();
|
||||||
|
if (currentList) {
|
||||||
|
const auto listProperties = currentList->format().properties();
|
||||||
|
for (const auto &property : listProperties.keys()) {
|
||||||
|
qWarning() << static_cast<QTextFormat::Property>(property) << listProperties[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_initializingChars = false;
|
m_initializingChars = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -402,9 +402,9 @@ QString TextHandler::stripBlockTags(QString string, const QString &tagType) cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is not a normal quotation mark but U+201C
|
// This is not a normal quotation mark but U+201C
|
||||||
string.insert(startQuotationIndex, u'“');
|
string.insert(startQuotationIndex, u"\""_s);
|
||||||
// This is U+201D
|
// This is U+201D
|
||||||
string.insert(endQuotationIndex, u'”');
|
string.insert(endQuotationIndex, u"\""_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
|
|||||||
@@ -13,8 +13,10 @@
|
|||||||
#include "enums/chatbartype.h"
|
#include "enums/chatbartype.h"
|
||||||
#include "enums/messagecomponenttype.h"
|
#include "enums/messagecomponenttype.h"
|
||||||
#include "enums/richformat.h"
|
#include "enums/richformat.h"
|
||||||
|
#include "messagecomponent.h"
|
||||||
#include "messagecontentmodel.h"
|
#include "messagecontentmodel.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
|
#include "texthandler.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -51,6 +53,18 @@ ChatBarMessageContentModel::ChatBarMessageContentModel(QObject *parent)
|
|||||||
textItem->setRoom(m_room);
|
textItem->setRoom(m_room);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// We can't guarantee whether room or type is intialised first so we have to handle.
|
||||||
|
if (!m_room || !unhandledTypeChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connectCache(m_room->cacheForType(*unhandledTypeChange));
|
||||||
|
unhandledTypeChange = std::nullopt;
|
||||||
|
const auto newCache = m_room->cacheForType(m_type);
|
||||||
|
if (newCache && newCache->isEditing()) {
|
||||||
|
initializeEdit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
initializeFromCache();
|
||||||
});
|
});
|
||||||
connect(this, &ChatBarMessageContentModel::typeChanged, this, [this](ChatBarType::Type oldType) {
|
connect(this, &ChatBarMessageContentModel::typeChanged, this, [this](ChatBarType::Type oldType) {
|
||||||
for (const auto &component : std::as_const(m_components)) {
|
for (const auto &component : std::as_const(m_components)) {
|
||||||
@@ -59,9 +73,15 @@ ChatBarMessageContentModel::ChatBarMessageContentModel(QObject *parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!m_room) {
|
if (!m_room) {
|
||||||
|
unhandledTypeChange = oldType;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
connectCache(m_room->cacheForType(oldType));
|
connectCache(m_room->cacheForType(oldType));
|
||||||
|
const auto newCache = m_room->cacheForType(m_type);
|
||||||
|
if (newCache && newCache->isEditing()) {
|
||||||
|
initializeEdit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
initializeFromCache();
|
initializeFromCache();
|
||||||
});
|
});
|
||||||
connect(m_markdownHelper, &ChatMarkdownHelper::unhandledBlockFormat, this, &ChatBarMessageContentModel::insertStyleAtCursor);
|
connect(m_markdownHelper, &ChatMarkdownHelper::unhandledBlockFormat, this, &ChatBarMessageContentModel::insertStyleAtCursor);
|
||||||
@@ -91,7 +111,7 @@ void ChatBarMessageContentModel::connectCache(ChatBarCache *oldCache)
|
|||||||
const auto currentCache = m_room->cacheForType(m_type);
|
const auto currentCache = m_room->cacheForType(m_type);
|
||||||
updateReplyModel();
|
updateReplyModel();
|
||||||
if (currentCache->isEditing()) {
|
if (currentCache->isEditing()) {
|
||||||
initializeFromCache();
|
initializeEdit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(m_room->cacheForType(m_type), &ChatBarCache::attachmentPathChanged, this, [this]() {
|
connect(m_room->cacheForType(m_type), &ChatBarCache::attachmentPathChanged, this, [this]() {
|
||||||
@@ -151,6 +171,38 @@ void ChatBarMessageContentModel::initializeFromCache()
|
|||||||
Q_EMIT focusRowChanged();
|
Q_EMIT focusRowChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatBarMessageContentModel::initializeEdit()
|
||||||
|
{
|
||||||
|
clearModel();
|
||||||
|
|
||||||
|
const auto currentCache = m_room->cacheForType(m_type);
|
||||||
|
auto components = currentCache->relationComponents();
|
||||||
|
if (components.isEmpty()) {
|
||||||
|
initializeModel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
std::ranges::for_each(components, [this](MessageComponent component) {
|
||||||
|
if (MessageComponentType::isTextType(component.type)) {
|
||||||
|
const auto textItemWrapper = new ChatTextItemHelper(this);
|
||||||
|
const auto initialFragment = component.type == MessageComponentType::Code ? QTextDocumentFragment::fromPlainText(component.display)
|
||||||
|
: QTextDocumentFragment::fromHtml(component.display);
|
||||||
|
textItemWrapper->setInitialFragment(initialFragment);
|
||||||
|
textItemWrapper->setRoom(m_room);
|
||||||
|
textItemWrapper->setType(m_type);
|
||||||
|
if (component.type == MessageComponentType::Quote) {
|
||||||
|
textItemWrapper->setFixedChars(u"\""_s, u"\""_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
component.attributes.insert(TextItemKey, QVariant::fromValue<ChatTextItemHelper *>(textItemWrapper));
|
||||||
|
connectTextItem(textItemWrapper);
|
||||||
|
}
|
||||||
|
m_components += component;
|
||||||
|
});
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
ChatBarType::Type ChatBarMessageContentModel::type() const
|
ChatBarType::Type ChatBarMessageContentModel::type() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
|
|||||||
@@ -130,10 +130,12 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ChatBarType::Type m_type = ChatBarType::None;
|
ChatBarType::Type m_type = ChatBarType::None;
|
||||||
|
std::optional<ChatBarType::Type> unhandledTypeChange = std::nullopt;
|
||||||
void connectCache(ChatBarCache *oldCache = nullptr);
|
void connectCache(ChatBarCache *oldCache = nullptr);
|
||||||
|
|
||||||
void initializeModel(const QString &initialText = {});
|
void initializeModel(const QString &initialText = {});
|
||||||
void initializeFromCache();
|
void initializeFromCache();
|
||||||
|
void initializeEdit();
|
||||||
|
|
||||||
std::optional<QString> getReplyEventId() override;
|
std::optional<QString> getReplyEventId() override;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user