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.
This commit is contained in:
Smitty van Bodegom
2021-06-17 17:54:18 -04:00
parent 81d0db7f1e
commit 8474136f57
4 changed files with 37 additions and 2 deletions

View File

@@ -12,9 +12,11 @@ TextEdit {
id: contentLabel
readonly property var isEmoji: /^(<span style='.*'>)?(\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: "<style>
table {
@@ -35,6 +37,12 @@ a{
color: " + Kirigami.Theme.linkColor + ";
text-decoration: none;
}
" + (!spoilerRevealed ? "
[data-mx-spoiler] {
color: transparent;
background: " + Kirigami.Theme.textColor + ";
}
" : "") + "
</style>" + (isEmote ? "* <a href='https://matrix.to/#/" + author.id + "' style='color: " + author.color + "'>" + author.displayName + "</a> " : "") + textMessage + (isEdited ? (" <span style=\"color: " + Kirigami.Theme.disabledTextColor + "\">" + "<span style='font-size: " + Kirigami.Theme.defaultFont.pixelSize +"px'>" + i18n(" (edited)") + "</span>") : "")
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
}
}
}

View File

@@ -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<const RoomMessageEvent>(event)) {
if (e->hasTextContent() && e->content() && e->mimeType().name() == "text/html") {
auto htmlBody = static_cast<const Quotient::EventContent::TextContent *>(e->content())->body;
return htmlBody.contains("data-mx-spoiler");
}
}
}
return false;
}
QString NeoChatRoom::lastEventToString() const
{
if (auto event = lastEvent()) {

View File

@@ -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

View File

@@ -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) {