Apply all the required styling in cpp

Apply all the required styling to show links, table, spoilers, etc in cpp. This also updates the method of revealing spoilers so now you can click to reveal then click again to hide.
This commit is contained in:
James Graham
2025-08-20 17:10:44 +01:00
parent 4498d4457b
commit 0d63fce59a
9 changed files with 297 additions and 107 deletions

View File

@@ -16,6 +16,11 @@ import org.kde.neochat
TextEdit {
id: root
/**
* @brief The index of the delegate in the model.
*/
required property int index
/**
* @brief The matrix ID of the message event.
*/
@@ -35,90 +40,28 @@ TextEdit {
*/
required property string display
/**
* @brief The attributes of the component.
*/
required property var componentAttributes
/**
* @brief Whether the message contains a spoiler
*/
readonly property var hasSpoiler: root.componentAttributes?.hasSpoiler ?? false
/**
* @brief Whether this message is replying to another.
*/
property bool isReply: false
/**
* @brief Regex for detecting a message with a spoiler.
*/
readonly property var hasSpoiler: /data-mx-spoiler/g
/**
* @brief Whether a spoiler should be revealed.
*/
property bool spoilerRevealed: !hasSpoiler.test(display)
/**
* @brief The color of spoiler blocks, to be theme-agnostic.
*/
property color spoilerBlockColor: Kirigami.ColorUtils.tintWithAlpha("#232629", Kirigami.Theme.textColor, 0.15)
Layout.fillWidth: true
Layout.fillHeight: true
Layout.maximumWidth: Message.maxContentWidth
ListView.onReused: Qt.binding(() => !hasSpoiler.test(display))
persistentSelection: true
text: "<style>
table {
width:100%;
border-width: 1px;
border-collapse: collapse;
border-style: solid;
}
code {
background-color:" + Kirigami.Theme.alternateBackgroundColor + ";
}
table th,
table td {
border: 1px solid black;
padding: 3px;
}
blockquote {
margin: 0;
}
blockquote table {
width: 100%;
border-width: 0;
background-color:" + Kirigami.Theme.alternateBackgroundColor + ";
}
blockquote td {
width: 100%;
padding: " + Kirigami.Units.largeSpacing + ";
}
pre {
white-space: pre-wrap
}
a{
color: " + Kirigami.Theme.linkColor + ";
text-decoration: none;
}
[data-mx-spoiler] a {
background: " + root.spoilerBlockColor + ";
}
[data-mx-spoiler] {
background: " + root.spoilerBlockColor + ";
}
" + (!spoilerRevealed ? "
[data-mx-spoiler] a {
color: transparent;
}
[data-mx-spoiler] {
color: transparent;
}
" : "
[data-mx-spoiler] a {
color: white;
}
[data-mx-spoiler] {
color: white;
}
") + "
</style>" + display
text: display
color: Kirigami.Theme.textColor
selectedTextColor: Kirigami.Theme.highlightedTextColor
@@ -133,7 +76,6 @@ a{
textFormat: Text.RichText
onLinkActivated: link => {
spoilerRevealed = true;
RoomManager.resolveResource(link, "join");
}
onHoveredLinkChanged: if (hoveredLink.length > 0 && hoveredLink !== "1") {
@@ -143,11 +85,11 @@ a{
}
HoverHandler {
cursorShape: (root.hoveredLink || !spoilerRevealed) ? Qt.PointingHandCursor : Qt.IBeamCursor
cursorShape: root.hoveredLink || (!(root.componentAttributes?.spoilerRevealed ?? false) && root.hasSpoiler) ? Qt.PointingHandCursor : Qt.IBeamCursor
}
TapHandler {
enabled: !root.hoveredLink && !spoilerRevealed
onTapped: spoilerRevealed = true
enabled: !root.hoveredLink && root.hasSpoiler
onTapped: root.Message.contentModel.toggleSpoiler(root.Message.contentFilterModel.mapToSource(root.Message.contentFilterModel.index(root.index, 0)))
}
TapHandler {
enabled: !root.hoveredLink

View File

@@ -9,6 +9,7 @@
#include "contentprovider.h"
#include "enums/messagecomponenttype.h"
#include "neochatconnection.h"
#include "texthandler.h"
using namespace Quotient;
@@ -17,6 +18,11 @@ MessageContentModel::MessageContentModel(NeoChatRoom *room, MessageContentModel
, m_room(room)
, m_eventId(eventId)
{
m_theme = static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true));
if (m_theme) {
connect(m_theme, &Kirigami::Platform::PlatformTheme::colorsChanged, this, &MessageContentModel::updateSpoilers);
}
initializeModel();
}
@@ -277,4 +283,40 @@ void MessageContentModel::closeLinkPreview(int row)
}
}
void MessageContentModel::updateSpoilers()
{
for (auto it = m_components.begin(); it != m_components.end(); ++it) {
updateSpoiler(index(it - m_components.begin()));
}
}
void MessageContentModel::updateSpoiler(const QModelIndex &index)
{
const auto row = index.row();
if (row < 0 || row >= rowCount()) {
qWarning() << __FUNCTION__ << "called with row" << row << "which does not exist. m_components.size() =" << m_components.size();
return;
}
const auto spoilerRevealed = m_components[row].attributes.value("spoilerRevealed"_L1, false).toBool();
m_components[row].display = TextHandler::updateSpoilerText(this, m_components[row].display, spoilerRevealed);
Q_EMIT dataChanged(index, index, {DisplayRole});
}
void MessageContentModel::toggleSpoiler(QModelIndex index)
{
const auto row = index.row();
if (row < 0 || row >= rowCount()) {
qWarning() << __FUNCTION__ << "called with row" << row << "which does not exist. m_components.size() =" << m_components.size();
return;
}
if (m_components[row].type != MessageComponentType::Text) {
return;
}
const auto spoilerRevealed = !m_components[row].attributes.value("spoilerRevealed"_L1, false).toBool();
m_components[row].attributes["spoilerRevealed"_L1] = spoilerRevealed;
Q_EMIT dataChanged(index, index, {ComponentAttributesRole});
updateSpoiler(index);
}
#include "moc_messagecontentmodel.cpp"

View File

@@ -7,6 +7,7 @@
#include <QQmlEngine>
#include <QImageReader>
#include <Kirigami/Platform/PlatformTheme>
#ifndef Q_OS_ANDROID
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Repository>
@@ -101,6 +102,11 @@ public:
*/
Q_INVOKABLE void closeLinkPreview(int row);
/**
* @brief Toggle spoiler for the component at the given row.
*/
Q_INVOKABLE void toggleSpoiler(QModelIndex index);
Q_SIGNALS:
void authorChanged();
@@ -232,4 +238,8 @@ private:
QList<QUrl> m_removedLinkPreviews;
MessageComponent linkPreviewComponent(const QUrl &link);
Kirigami::Platform::PlatformTheme *m_theme = nullptr;
void updateSpoilers();
void updateSpoiler(const QModelIndex &index);
};