From 8474136f57d5ba97adfbbf405b65cb7b8d93b786 Mon Sep 17 00:00:00 2001 From: Smitty van Bodegom Date: Thu, 17 Jun 2021 17:54:18 -0400 Subject: [PATCH] Support displaying spoilers This adds support for displaying recieved spoilers, but not sending them. Spoilers are displayed as a black rectangle, and can be clicked on to be revealed. If the last message in a channel was a spoiler, it is not shown on the left sidebar. The spoiler blackening is done in CSS, but to check if a message contains a spoiler for determining if it should cause a different cursor to be displayed and if it should be shown in the sidebar, a simple check of if the message contains "data-mx-spoiler" is used. --- .../NeoChat/Component/Timeline/TextDelegate.qml | 16 ++++++++++++++-- src/neochatroom.cpp | 13 +++++++++++++ src/neochatroom.h | 7 +++++++ src/roomlistmodel.cpp | 3 +++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/imports/NeoChat/Component/Timeline/TextDelegate.qml b/imports/NeoChat/Component/Timeline/TextDelegate.qml index 37b08b962..4e40d96cd 100644 --- a/imports/NeoChat/Component/Timeline/TextDelegate.qml +++ b/imports/NeoChat/Component/Timeline/TextDelegate.qml @@ -12,9 +12,11 @@ TextEdit { id: contentLabel readonly property var isEmoji: /^()?(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])+(<\/span>)?$/ + readonly property var hasSpoiler: /data-mx-spoiler/g property bool isEmote: false property string textMessage: model.display + property bool spoilerRevealed: !hasSpoiler.test(textMessage) text: "" + (isEmote ? "* " + author.displayName + " " : "") + textMessage + (isEdited ? (" " + "" + i18n(" (edited)") + "") : "") color: Kirigami.Theme.textColor @@ -55,7 +63,11 @@ a{ MouseArea { anchors.fill: parent - acceptedButtons: Qt.NoButton - cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.IBeamCursor + acceptedButtons: spoilerRevealed ? Qt.NoButton : Qt.LeftButton + cursorShape: (parent.hoveredLink || !spoilerRevealed) ? Qt.PointingHandCursor : Qt.IBeamCursor + + TapHandler { + onTapped: spoilerRevealed = true + } } } diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index e3d98d655..6acead447 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -147,6 +147,19 @@ const RoomMessageEvent *NeoChatRoom::lastEvent(bool ignoreStateEvent) const return nullptr; } +bool NeoChatRoom::lastEventIsSpoiler() const +{ + if (auto event = lastEvent()) { + if (auto e = eventCast(event)) { + if (e->hasTextContent() && e->content() && e->mimeType().name() == "text/html") { + auto htmlBody = static_cast(e->content())->body; + return htmlBody.contains("data-mx-spoiler"); + } + } + } + return false; +} + QString NeoChatRoom::lastEventToString() const { if (auto event = lastEvent()) { diff --git a/src/neochatroom.h b/src/neochatroom.h index 4feab4dce..bf8ca9f45 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -47,8 +47,15 @@ public: /// Convenient way to get the last event but in a string format. /// /// \see lastEvent + /// \see lastEventIsSpoiler [[nodiscard]] QString lastEventToString() const; + /// Convenient way to check if the last event looks like it has spoilers. + /// + /// \see lastEvent + /// \see lastEventToString + [[nodiscard]] bool lastEventIsSpoiler() const; + /// Convenient way to get the QDateTime of the last event. /// /// \see lastEvent diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index c35e96a5b..9e84c825e 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -364,6 +364,9 @@ QVariant RoomListModel::data(const QModelIndex &index, int role) const return room->highlightCount(); } if (role == LastEventRole) { + if (room->lastEventIsSpoiler()) { + return QString(); + } return room->lastEventToString(); } if (role == LastActiveTimeRole) {