Port state events and images
This commit is contained in:
parent
76b40f452b
commit
eab8731f5b
@ -191,13 +191,19 @@ Item {
|
|||||||
roleValues: [
|
roleValues: [
|
||||||
MtxEvent.TextMessage,
|
MtxEvent.TextMessage,
|
||||||
MtxEvent.NoticeMessage,
|
MtxEvent.NoticeMessage,
|
||||||
|
MtxEvent.ElementEffectMessage,
|
||||||
|
MtxEvent.UnknownMessage,
|
||||||
]
|
]
|
||||||
TextMessage {
|
TextMessage {
|
||||||
id: textMes
|
|
||||||
|
|
||||||
keepFullText: true
|
keepFullText: true
|
||||||
required property string userId
|
required property string userId
|
||||||
required property string userName
|
required property string userName
|
||||||
|
required property string formattedBody
|
||||||
|
required property int type
|
||||||
|
|
||||||
|
color: type == MtxEvent.NoticeMessage ? palette.buttonText : palette.text
|
||||||
|
font.italic: type == MtxEvent.NoticeMessage
|
||||||
|
formatted: formattedBody
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
//Layout.maximumWidth: implicitWidth
|
//Layout.maximumWidth: implicitWidth
|
||||||
@ -205,6 +211,80 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EventDelegateChoice {
|
||||||
|
roleValues: [
|
||||||
|
MtxEvent.EmoteMessage,
|
||||||
|
]
|
||||||
|
TextMessage {
|
||||||
|
keepFullText: true
|
||||||
|
required property string userId
|
||||||
|
required property string userName
|
||||||
|
required property string formattedBody
|
||||||
|
|
||||||
|
formatted: TimelineManager.escapeEmoji(userName) + " " + formattedBody
|
||||||
|
|
||||||
|
color: TimelineManager.userColor(userId, palette.base)
|
||||||
|
font.italic: true
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
//Layout.maximumWidth: implicitWidth
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDelegateChoice {
|
||||||
|
roleValues: [
|
||||||
|
MtxEvent.CanonicalAlias,
|
||||||
|
MtxEvent.ServerAcl,
|
||||||
|
MtxEvent.Name,
|
||||||
|
MtxEvent.Topic,
|
||||||
|
MtxEvent.Avatar,
|
||||||
|
MtxEvent.PinnedEvents,
|
||||||
|
MtxEvent.ImagePackInRoom,
|
||||||
|
MtxEvent.SpaceParent,
|
||||||
|
MtxEvent.RoomCreate,
|
||||||
|
MtxEvent.PowerLevels,
|
||||||
|
MtxEvent.PolicyRuleUser,
|
||||||
|
MtxEvent.PolicyRuleRoom,
|
||||||
|
MtxEvent.PolicyRuleServer,
|
||||||
|
MtxEvent.RoomJoinRules,
|
||||||
|
MtxEvent.RoomHistoryVisibility,
|
||||||
|
MtxEvent.RoomGuestAccess,
|
||||||
|
]
|
||||||
|
TextMessage {
|
||||||
|
keepFullText: true
|
||||||
|
|
||||||
|
required property string userId
|
||||||
|
required property string userName
|
||||||
|
required property string formattedStateEvent
|
||||||
|
|
||||||
|
isOnlyEmoji: false
|
||||||
|
text: formattedStateEvent
|
||||||
|
formatted: ''
|
||||||
|
body: ''
|
||||||
|
|
||||||
|
color: palette.buttonText
|
||||||
|
font.italic: true
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
//Layout.maximumWidth: implicitWidth
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventDelegateChoice {
|
||||||
|
roleValues: [
|
||||||
|
MtxEvent.ImageMessage,
|
||||||
|
MtxEvent.Sticker,
|
||||||
|
]
|
||||||
|
ImageMessage {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
containerHeight: timelineView.height
|
||||||
|
Layout.maximumWidth: tempWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EventDelegateChoice {
|
EventDelegateChoice {
|
||||||
roleValues: [
|
roleValues: [
|
||||||
]
|
]
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import QtQuick 2.15
|
import QtQuick
|
||||||
import QtQuick.Window 2.15
|
import QtQuick.Window
|
||||||
import QtQuick.Controls 2.3
|
import QtQuick.Controls
|
||||||
import im.nheko 1.0
|
import QtQuick.Layouts
|
||||||
|
import im.nheko
|
||||||
|
|
||||||
AbstractButton {
|
AbstractButton {
|
||||||
required property int type
|
required property int type
|
||||||
@ -17,13 +18,13 @@ AbstractButton {
|
|||||||
required property string filename
|
required property string filename
|
||||||
required property bool isReply
|
required property bool isReply
|
||||||
required property string eventId
|
required property string eventId
|
||||||
|
required property int containerHeight
|
||||||
property double divisor: isReply ? 5 : 3
|
property double divisor: isReply ? 5 : 3
|
||||||
|
|
||||||
property int tempWidth: originalWidth < 1? 400: originalWidth
|
property int tempWidth: originalWidth < 1? 400: originalWidth
|
||||||
|
|
||||||
implicitWidth: Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1))
|
Layout.preferredWidth: Math.round(tempWidth*Math.min((containerHeight/divisor)/(tempWidth*proportionalHeight), 1))
|
||||||
width: Math.min(parent?.width ?? 2000,implicitWidth)
|
Layout.preferredHeight: width*proportionalHeight
|
||||||
height: width*proportionalHeight
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
|
state: (img.status != Image.Ready || timeline.privacyScreen.active) ? "BlurhashVisible" : "ImageVisible"
|
||||||
|
@ -175,6 +175,7 @@ Item {
|
|||||||
isReply: d.isReply
|
isReply: d.isReply
|
||||||
eventId: d.eventId
|
eventId: d.eventId
|
||||||
metadataWidth: d.metadataWidth
|
metadataWidth: d.metadataWidth
|
||||||
|
containerHeight: timelineView.height
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -193,6 +194,7 @@ Item {
|
|||||||
isReply: d.isReply
|
isReply: d.isReply
|
||||||
eventId: d.eventId
|
eventId: d.eventId
|
||||||
metadataWidth: d.metadataWidth
|
metadataWidth: d.metadataWidth
|
||||||
|
containerHeight: timelineView.height
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ MatrixText {
|
|||||||
required property bool isOnlyEmoji
|
required property bool isOnlyEmoji
|
||||||
required property bool isReply
|
required property bool isReply
|
||||||
required property bool keepFullText
|
required property bool keepFullText
|
||||||
required property string formattedBody
|
required property string formatted
|
||||||
|
|
||||||
property string copyText: selectedText ? getText(selectionStart, selectionEnd) : body
|
property string copyText: selectedText ? getText(selectionStart, selectionEnd) : body
|
||||||
property int metadataWidth: 100
|
property int metadataWidth: 100
|
||||||
@ -40,7 +40,7 @@ MatrixText {
|
|||||||
background-color: " + palette.text + ";
|
background-color: " + palette.text + ";
|
||||||
}" : "") + // TODO(Nico): Figure out how to support mobile
|
}" : "") + // TODO(Nico): Figure out how to support mobile
|
||||||
"</style>
|
"</style>
|
||||||
" + formattedBody.replace(/<del>/g, "<s>").replace(/<\/del>/g, "</s>").replace(/<strike>/g, "<s>").replace(/<\/strike>/g, "</s>")
|
" + formatted.replace(/<del>/g, "<s>").replace(/<\/del>/g, "</s>").replace(/<strike>/g, "<s>").replace(/<\/strike>/g, "</s>")
|
||||||
Layout.maximumHeight: !keepFullText ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : implicitHeight
|
Layout.maximumHeight: !keepFullText ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : implicitHeight
|
||||||
clip: !keepFullText
|
clip: !keepFullText
|
||||||
selectByMouse: !Settings.mobileMode && !isReply
|
selectByMouse: !Settings.mobileMode && !isReply
|
||||||
|
@ -843,8 +843,8 @@ EventStore::get(const std::string &id,
|
|||||||
nhlog::net()->error(
|
nhlog::net()->error(
|
||||||
"Failed to retrieve event with id {}, which was "
|
"Failed to retrieve event with id {}, which was "
|
||||||
"requested to show the replyTo for event {}",
|
"requested to show the replyTo for event {}",
|
||||||
relatedTo,
|
id,
|
||||||
id);
|
relatedTo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
emit eventFetched(id, relatedTo, timeline);
|
emit eventFetched(id, relatedTo, timeline);
|
||||||
|
@ -532,6 +532,7 @@ TimelineModel::roleNames() const
|
|||||||
{IsOnlyEmoji, "isOnlyEmoji"},
|
{IsOnlyEmoji, "isOnlyEmoji"},
|
||||||
{Body, "body"},
|
{Body, "body"},
|
||||||
{FormattedBody, "formattedBody"},
|
{FormattedBody, "formattedBody"},
|
||||||
|
{FormattedStateEvent, "formattedStateEvent"},
|
||||||
{IsSender, "isSender"},
|
{IsSender, "isSender"},
|
||||||
{UserId, "userId"},
|
{UserId, "userId"},
|
||||||
{UserName, "userName"},
|
{UserName, "userName"},
|
||||||
@ -694,6 +695,76 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
|||||||
|
|
||||||
return QVariant(utils::replaceEmoji(utils::linkifyMessage(formattedBody_)));
|
return QVariant(utils::replaceEmoji(utils::linkifyMessage(formattedBody_)));
|
||||||
}
|
}
|
||||||
|
case FormattedStateEvent: {
|
||||||
|
if (mtx::accessors::is_state_event(event)) {
|
||||||
|
return std::visit(
|
||||||
|
[this](const auto &e) {
|
||||||
|
constexpr auto t = mtx::events::state_content_to_type<decltype(e.content)>;
|
||||||
|
if constexpr (t == mtx::events::EventType::RoomServerAcl)
|
||||||
|
return tr("%1 changed which servers are allowed in this room.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomName) {
|
||||||
|
if (e.content.name.empty())
|
||||||
|
return tr("%1 removed the room name.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else
|
||||||
|
return tr("%1 changed the room name to: %2")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)))
|
||||||
|
.arg(QString::fromStdString(e.content.name).toHtmlEscaped());
|
||||||
|
} else if constexpr (t == mtx::events::EventType::RoomTopic) {
|
||||||
|
if (e.content.topic.empty())
|
||||||
|
return tr("%1 removed the topic.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else
|
||||||
|
return tr("%1 changed the topic to: %2")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)))
|
||||||
|
.arg(QString::fromStdString(e.content.topic).toHtmlEscaped());
|
||||||
|
} else if constexpr (t == mtx::events::EventType::RoomAvatar) {
|
||||||
|
if (e.content.url.starts_with("mxc://"))
|
||||||
|
return tr("%1 changed the room avatar to: %2")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)))
|
||||||
|
.arg(QStringLiteral("<img height=\"32\" src=\"%1\">")
|
||||||
|
.arg(QUrl::toPercentEncoding(
|
||||||
|
QString::fromStdString(e.content.url))));
|
||||||
|
else
|
||||||
|
return tr("%1 removed the room avatar.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
} else if constexpr (t == mtx::events::EventType::RoomPinnedEvents)
|
||||||
|
return tr("%1 changed the pinned messages.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else if constexpr (t == mtx::events::EventType::ImagePackInRoom)
|
||||||
|
formatImagePackEvent(e);
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomCanonicalAlias)
|
||||||
|
return tr("%1 changed the addresses for this room.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else if constexpr (t == mtx::events::EventType::SpaceParent)
|
||||||
|
return tr("%1 changed the parent communities for this room.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)));
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomCreate)
|
||||||
|
return tr("%1 created and configured room: %2")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)))
|
||||||
|
.arg(room_id_);
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomPowerLevels)
|
||||||
|
return formatPowerLevelEvent(e);
|
||||||
|
else if constexpr (t == mtx::events::EventType::PolicyRuleRoom)
|
||||||
|
return formatPolicyRule(QString::fromStdString(e.event_id));
|
||||||
|
else if constexpr (t == mtx::events::EventType::PolicyRuleUser)
|
||||||
|
return formatPolicyRule(QString::fromStdString(e.event_id));
|
||||||
|
else if constexpr (t == mtx::events::EventType::PolicyRuleServer)
|
||||||
|
return formatPolicyRule(QString::fromStdString(e.event_id));
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomHistoryVisibility)
|
||||||
|
return formatHistoryVisibilityEvent(e);
|
||||||
|
else if constexpr (t == mtx::events::EventType::RoomGuestAccess)
|
||||||
|
return formatGuestAccessEvent(e);
|
||||||
|
|
||||||
|
return tr("%1 changed unknown state event %2.")
|
||||||
|
.arg(displayName(QString::fromStdString(e.sender)))
|
||||||
|
.arg(QString::fromStdString(to_string(e.type)));
|
||||||
|
},
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
case Url:
|
case Url:
|
||||||
return QVariant(QString::fromStdString(url(event)));
|
return QVariant(QString::fromStdString(url(event)));
|
||||||
case ThumbnailUrl:
|
case ThumbnailUrl:
|
||||||
@ -2308,20 +2379,13 @@ TimelineModel::formatJoinRuleEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::formatGuestAccessEvent(const QString &id)
|
TimelineModel::formatGuestAccessEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::state::GuestAccess> &event) const
|
||||||
{
|
{
|
||||||
auto e = events.get(id.toStdString(), "");
|
QString user = QString::fromStdString(event.sender);
|
||||||
if (!e)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::GuestAccess>>(e);
|
|
||||||
if (!event)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
QString user = QString::fromStdString(event->sender);
|
|
||||||
QString name = utils::replaceEmoji(displayName(user));
|
QString name = utils::replaceEmoji(displayName(user));
|
||||||
|
|
||||||
switch (event->content.guest_access) {
|
switch (event.content.guest_access) {
|
||||||
case mtx::events::state::AccessState::CanJoin:
|
case mtx::events::state::AccessState::CanJoin:
|
||||||
return tr("%1 made the room open to guests.").arg(name);
|
return tr("%1 made the room open to guests.").arg(name);
|
||||||
case mtx::events::state::AccessState::Forbidden:
|
case mtx::events::state::AccessState::Forbidden:
|
||||||
@ -2332,21 +2396,13 @@ TimelineModel::formatGuestAccessEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::formatHistoryVisibilityEvent(const QString &id)
|
TimelineModel::formatHistoryVisibilityEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::state::HistoryVisibility> &event) const
|
||||||
{
|
{
|
||||||
auto e = events.get(id.toStdString(), "");
|
QString user = QString::fromStdString(event.sender);
|
||||||
if (!e)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::HistoryVisibility>>(e);
|
|
||||||
|
|
||||||
if (!event)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
QString user = QString::fromStdString(event->sender);
|
|
||||||
QString name = utils::replaceEmoji(displayName(user));
|
QString name = utils::replaceEmoji(displayName(user));
|
||||||
|
|
||||||
switch (event->content.history_visibility) {
|
switch (event.content.history_visibility) {
|
||||||
case mtx::events::state::Visibility::WorldReadable:
|
case mtx::events::state::Visibility::WorldReadable:
|
||||||
return tr("%1 made the room history world readable. Events may be now read by "
|
return tr("%1 made the room history world readable. Events may be now read by "
|
||||||
"non-joined people.")
|
"non-joined people.")
|
||||||
@ -2364,32 +2420,25 @@ TimelineModel::formatHistoryVisibilityEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::formatPowerLevelEvent(const QString &id)
|
TimelineModel::formatPowerLevelEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::state::PowerLevels> &event) const
|
||||||
{
|
{
|
||||||
auto e = events.get(id.toStdString(), "");
|
|
||||||
if (!e)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(e);
|
|
||||||
if (!event)
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
mtx::events::StateEvent<mtx::events::state::PowerLevels> const *prevEvent = nullptr;
|
mtx::events::StateEvent<mtx::events::state::PowerLevels> const *prevEvent = nullptr;
|
||||||
if (!event->unsigned_data.replaces_state.empty()) {
|
if (!event.unsigned_data.replaces_state.empty()) {
|
||||||
auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id);
|
auto tempPrevEvent = events.get(event.unsigned_data.replaces_state, event.event_id);
|
||||||
if (tempPrevEvent) {
|
if (tempPrevEvent) {
|
||||||
prevEvent =
|
prevEvent =
|
||||||
std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(tempPrevEvent);
|
std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(tempPrevEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString user = QString::fromStdString(event->sender);
|
QString user = QString::fromStdString(event.sender);
|
||||||
QString sender_name = utils::replaceEmoji(displayName(user));
|
QString sender_name = utils::replaceEmoji(displayName(user));
|
||||||
// Get the rooms levels for redactions and powerlevel changes to determine "Administrator" and
|
// Get the rooms levels for redactions and powerlevel changes to determine "Administrator" and
|
||||||
// "Moderator" powerlevels.
|
// "Moderator" powerlevels.
|
||||||
auto administrator_power_level = event->content.state_level("m.room.power_levels");
|
auto administrator_power_level = event.content.state_level("m.room.power_levels");
|
||||||
auto moderator_power_level = event->content.redact;
|
auto moderator_power_level = event.content.redact;
|
||||||
auto default_powerlevel = event->content.users_default;
|
auto default_powerlevel = event.content.users_default;
|
||||||
if (!prevEvent)
|
if (!prevEvent)
|
||||||
return tr("%1 has changed the room's permissions.").arg(sender_name);
|
return tr("%1 has changed the room's permissions.").arg(sender_name);
|
||||||
|
|
||||||
@ -2399,7 +2448,7 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
auto numberOfAffected = 0;
|
auto numberOfAffected = 0;
|
||||||
// We do only compare to people with explicit PL. Usually others are not going to be
|
// We do only compare to people with explicit PL. Usually others are not going to be
|
||||||
// affected either way and this is cheaper to iterate over.
|
// affected either way and this is cheaper to iterate over.
|
||||||
for (auto const &[mxid, currentPowerlevel] : event->content.users) {
|
for (auto const &[mxid, currentPowerlevel] : event.content.users) {
|
||||||
if (currentPowerlevel == newPowerlevelSetting &&
|
if (currentPowerlevel == newPowerlevelSetting &&
|
||||||
prevEvent->content.user_level(mxid) < newPowerlevelSetting) {
|
prevEvent->content.user_level(mxid) < newPowerlevelSetting) {
|
||||||
numberOfAffected++;
|
numberOfAffected++;
|
||||||
@ -2413,16 +2462,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
|
|
||||||
QStringList resultingMessage{};
|
QStringList resultingMessage{};
|
||||||
// These affect only a few people. Therefor we can print who is affected.
|
// These affect only a few people. Therefor we can print who is affected.
|
||||||
if (event->content.kick != prevEvent->content.kick) {
|
if (event.content.kick != prevEvent->content.kick) {
|
||||||
auto default_message = tr("%1 has changed the room's kick powerlevel from %2 to %3.")
|
auto default_message = tr("%1 has changed the room's kick powerlevel from %2 to %3.")
|
||||||
.arg(sender_name)
|
.arg(sender_name)
|
||||||
.arg(prevEvent->content.kick)
|
.arg(prevEvent->content.kick)
|
||||||
.arg(event->content.kick);
|
.arg(event.content.kick);
|
||||||
|
|
||||||
// We only calculate affected users if we change to a level above the default users PL
|
// We only calculate affected users if we change to a level above the default users PL
|
||||||
// to not accidentally have a DoS vector
|
// to not accidentally have a DoS vector
|
||||||
if (event->content.kick > default_powerlevel) {
|
if (event.content.kick > default_powerlevel) {
|
||||||
auto [affected, number_of_affected] = calc_affected(event->content.kick);
|
auto [affected, number_of_affected] = calc_affected(event.content.kick);
|
||||||
|
|
||||||
if (number_of_affected != 0) {
|
if (number_of_affected != 0) {
|
||||||
auto true_affected_rest = number_of_affected - affected.size();
|
auto true_affected_rest = number_of_affected - affected.size();
|
||||||
@ -2444,16 +2493,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->content.redact != prevEvent->content.redact) {
|
if (event.content.redact != prevEvent->content.redact) {
|
||||||
auto default_message = tr("%1 has changed the room's redact powerlevel from %2 to %3.")
|
auto default_message = tr("%1 has changed the room's redact powerlevel from %2 to %3.")
|
||||||
.arg(sender_name)
|
.arg(sender_name)
|
||||||
.arg(prevEvent->content.redact)
|
.arg(prevEvent->content.redact)
|
||||||
.arg(event->content.redact);
|
.arg(event.content.redact);
|
||||||
|
|
||||||
// We only calculate affected users if we change to a level above the default users PL
|
// We only calculate affected users if we change to a level above the default users PL
|
||||||
// to not accidentally have a DoS vector
|
// to not accidentally have a DoS vector
|
||||||
if (event->content.redact > default_powerlevel) {
|
if (event.content.redact > default_powerlevel) {
|
||||||
auto [affected, number_of_affected] = calc_affected(event->content.redact);
|
auto [affected, number_of_affected] = calc_affected(event.content.redact);
|
||||||
|
|
||||||
if (number_of_affected != 0) {
|
if (number_of_affected != 0) {
|
||||||
auto true_affected_rest = number_of_affected - affected.size();
|
auto true_affected_rest = number_of_affected - affected.size();
|
||||||
@ -2476,16 +2525,16 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->content.ban != prevEvent->content.ban) {
|
if (event.content.ban != prevEvent->content.ban) {
|
||||||
auto default_message = tr("%1 has changed the room's ban powerlevel from %2 to %3.")
|
auto default_message = tr("%1 has changed the room's ban powerlevel from %2 to %3.")
|
||||||
.arg(sender_name)
|
.arg(sender_name)
|
||||||
.arg(prevEvent->content.ban)
|
.arg(prevEvent->content.ban)
|
||||||
.arg(event->content.ban);
|
.arg(event.content.ban);
|
||||||
|
|
||||||
// We only calculate affected users if we change to a level above the default users PL
|
// We only calculate affected users if we change to a level above the default users PL
|
||||||
// to not accidentally have a DoS vector
|
// to not accidentally have a DoS vector
|
||||||
if (event->content.ban > default_powerlevel) {
|
if (event.content.ban > default_powerlevel) {
|
||||||
auto [affected, number_of_affected] = calc_affected(event->content.ban);
|
auto [affected, number_of_affected] = calc_affected(event.content.ban);
|
||||||
|
|
||||||
if (number_of_affected != 0) {
|
if (number_of_affected != 0) {
|
||||||
auto true_affected_rest = number_of_affected - affected.size();
|
auto true_affected_rest = number_of_affected - affected.size();
|
||||||
@ -2507,17 +2556,17 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->content.state_default != prevEvent->content.state_default) {
|
if (event.content.state_default != prevEvent->content.state_default) {
|
||||||
auto default_message =
|
auto default_message =
|
||||||
tr("%1 has changed the room's state_default powerlevel from %2 to %3.")
|
tr("%1 has changed the room's state_default powerlevel from %2 to %3.")
|
||||||
.arg(sender_name)
|
.arg(sender_name)
|
||||||
.arg(prevEvent->content.state_default)
|
.arg(prevEvent->content.state_default)
|
||||||
.arg(event->content.state_default);
|
.arg(event.content.state_default);
|
||||||
|
|
||||||
// We only calculate affected users if we change to a level above the default users PL
|
// We only calculate affected users if we change to a level above the default users PL
|
||||||
// to not accidentally have a DoS vector
|
// to not accidentally have a DoS vector
|
||||||
if (event->content.state_default > default_powerlevel) {
|
if (event.content.state_default > default_powerlevel) {
|
||||||
auto [affected, number_of_affected] = calc_affected(event->content.kick);
|
auto [affected, number_of_affected] = calc_affected(event.content.kick);
|
||||||
|
|
||||||
if (number_of_affected != 0) {
|
if (number_of_affected != 0) {
|
||||||
auto true_affected_rest = number_of_affected - affected.size();
|
auto true_affected_rest = number_of_affected - affected.size();
|
||||||
@ -2541,42 +2590,42 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
|
|
||||||
// These affect potentially the whole room. We there for do not calculate who gets affected
|
// These affect potentially the whole room. We there for do not calculate who gets affected
|
||||||
// by this to prevent huge lists of people.
|
// by this to prevent huge lists of people.
|
||||||
if (event->content.invite != prevEvent->content.invite) {
|
if (event.content.invite != prevEvent->content.invite) {
|
||||||
resultingMessage.append(tr("%1 has changed the room's invite powerlevel from %2 to %3.")
|
resultingMessage.append(tr("%1 has changed the room's invite powerlevel from %2 to %3.")
|
||||||
.arg(sender_name,
|
.arg(sender_name,
|
||||||
QString::number(prevEvent->content.invite),
|
QString::number(prevEvent->content.invite),
|
||||||
QString::number(event->content.invite)));
|
QString::number(event.content.invite)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->content.events_default != prevEvent->content.events_default) {
|
if (event.content.events_default != prevEvent->content.events_default) {
|
||||||
if ((event->content.events_default > default_powerlevel) &&
|
if ((event.content.events_default > default_powerlevel) &&
|
||||||
prevEvent->content.events_default <= default_powerlevel) {
|
prevEvent->content.events_default <= default_powerlevel) {
|
||||||
resultingMessage.append(
|
resultingMessage.append(
|
||||||
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New "
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New "
|
||||||
"users can now not send any events.")
|
"users can now not send any events.")
|
||||||
.arg(sender_name,
|
.arg(sender_name,
|
||||||
QString::number(prevEvent->content.events_default),
|
QString::number(prevEvent->content.events_default),
|
||||||
QString::number(event->content.events_default)));
|
QString::number(event.content.events_default)));
|
||||||
} else if ((event->content.events_default < prevEvent->content.events_default) &&
|
} else if ((event.content.events_default < prevEvent->content.events_default) &&
|
||||||
(event->content.events_default < default_powerlevel) &&
|
(event.content.events_default < default_powerlevel) &&
|
||||||
(prevEvent->content.events_default > default_powerlevel)) {
|
(prevEvent->content.events_default > default_powerlevel)) {
|
||||||
resultingMessage.append(
|
resultingMessage.append(
|
||||||
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New "
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3. New "
|
||||||
"users can now send events that are not otherwise restricted.")
|
"users can now send events that are not otherwise restricted.")
|
||||||
.arg(sender_name,
|
.arg(sender_name,
|
||||||
QString::number(prevEvent->content.events_default),
|
QString::number(prevEvent->content.events_default),
|
||||||
QString::number(event->content.events_default)));
|
QString::number(event.content.events_default)));
|
||||||
} else {
|
} else {
|
||||||
resultingMessage.append(
|
resultingMessage.append(
|
||||||
tr("%1 has changed the room's events_default powerlevel from %2 to %3.")
|
tr("%1 has changed the room's events_default powerlevel from %2 to %3.")
|
||||||
.arg(sender_name,
|
.arg(sender_name,
|
||||||
QString::number(prevEvent->content.events_default),
|
QString::number(prevEvent->content.events_default),
|
||||||
QString::number(event->content.events_default)));
|
QString::number(event.content.events_default)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare if a Powerlevel of a user changed
|
// Compare if a Powerlevel of a user changed
|
||||||
for (auto const &[mxid, powerlevel] : event->content.users) {
|
for (auto const &[mxid, powerlevel] : event.content.users) {
|
||||||
auto nameOfChangedUser = utils::replaceEmoji(displayName(QString::fromStdString(mxid)));
|
auto nameOfChangedUser = utils::replaceEmoji(displayName(QString::fromStdString(mxid)));
|
||||||
if (prevEvent->content.user_level(mxid) != powerlevel) {
|
if (prevEvent->content.user_level(mxid) != powerlevel) {
|
||||||
if (powerlevel >= administrator_power_level) {
|
if (powerlevel >= administrator_power_level) {
|
||||||
@ -2601,7 +2650,7 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle added/removed/changed event type
|
// Handle added/removed/changed event type
|
||||||
for (auto const &[event_type, powerlevel] : event->content.events) {
|
for (auto const &[event_type, powerlevel] : event.content.events) {
|
||||||
auto prev_not_present =
|
auto prev_not_present =
|
||||||
prevEvent->content.events.find(event_type) == prevEvent->content.events.end();
|
prevEvent->content.events.find(event_type) == prevEvent->content.events.end();
|
||||||
|
|
||||||
@ -2640,26 +2689,19 @@ TimelineModel::formatPowerLevelEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::formatImagePackEvent(const QString &id)
|
TimelineModel::formatImagePackEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::msc2545::ImagePack> &event) const
|
||||||
{
|
{
|
||||||
auto e = events.get(id.toStdString(), "");
|
|
||||||
if (!e)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
auto event = std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(e);
|
|
||||||
if (!event)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
mtx::events::StateEvent<mtx::events::msc2545::ImagePack> const *prevEvent = nullptr;
|
mtx::events::StateEvent<mtx::events::msc2545::ImagePack> const *prevEvent = nullptr;
|
||||||
if (!event->unsigned_data.replaces_state.empty()) {
|
if (!event.unsigned_data.replaces_state.empty()) {
|
||||||
auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id);
|
auto tempPrevEvent = events.get(event.unsigned_data.replaces_state, event.event_id);
|
||||||
if (tempPrevEvent) {
|
if (tempPrevEvent) {
|
||||||
prevEvent =
|
prevEvent =
|
||||||
std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(tempPrevEvent);
|
std::get_if<mtx::events::StateEvent<mtx::events::msc2545::ImagePack>>(tempPrevEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &newImages = event->content.images;
|
const auto &newImages = event.content.images;
|
||||||
const auto oldImages = prevEvent ? prevEvent->content.images : decltype(newImages){};
|
const auto oldImages = prevEvent ? prevEvent->content.images : decltype(newImages){};
|
||||||
|
|
||||||
auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent();
|
auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent();
|
||||||
@ -2682,12 +2724,12 @@ TimelineModel::formatImagePackEvent(const QString &id)
|
|||||||
auto added = calcChange(newImages, oldImages);
|
auto added = calcChange(newImages, oldImages);
|
||||||
auto removed = calcChange(oldImages, newImages);
|
auto removed = calcChange(oldImages, newImages);
|
||||||
|
|
||||||
auto sender = utils::replaceEmoji(displayName(QString::fromStdString(event->sender)));
|
auto sender = utils::replaceEmoji(displayName(QString::fromStdString(event.sender)));
|
||||||
const auto packId = [&event]() -> QString {
|
const auto packId = [&event]() -> QString {
|
||||||
if (event->content.pack && !event->content.pack->display_name.empty()) {
|
if (event.content.pack && !event.content.pack->display_name.empty()) {
|
||||||
return event->content.pack->display_name.c_str();
|
return event.content.pack->display_name.c_str();
|
||||||
} else if (!event->state_key.empty()) {
|
} else if (!event.state_key.empty()) {
|
||||||
return event->state_key.c_str();
|
return event.state_key.c_str();
|
||||||
}
|
}
|
||||||
return tr("(empty)");
|
return tr("(empty)");
|
||||||
}();
|
}();
|
||||||
@ -2712,7 +2754,7 @@ TimelineModel::formatImagePackEvent(const QString &id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::formatPolicyRule(const QString &id)
|
TimelineModel::formatPolicyRule(const QString &id) const
|
||||||
{
|
{
|
||||||
auto idStr = id.toStdString();
|
auto idStr = id.toStdString();
|
||||||
auto e = events.get(idStr, "");
|
auto e = events.get(idStr, "");
|
||||||
|
@ -238,6 +238,7 @@ public:
|
|||||||
IsOnlyEmoji,
|
IsOnlyEmoji,
|
||||||
Body,
|
Body,
|
||||||
FormattedBody,
|
FormattedBody,
|
||||||
|
FormattedStateEvent,
|
||||||
IsSender,
|
IsSender,
|
||||||
UserId,
|
UserId,
|
||||||
UserName,
|
UserName,
|
||||||
@ -310,11 +311,15 @@ public:
|
|||||||
Q_INVOKABLE void joinReplacementRoom(const QString &id);
|
Q_INVOKABLE void joinReplacementRoom(const QString &id);
|
||||||
Q_INVOKABLE QString formatMemberEvent(const QString &id);
|
Q_INVOKABLE QString formatMemberEvent(const QString &id);
|
||||||
Q_INVOKABLE QString formatJoinRuleEvent(const QString &id);
|
Q_INVOKABLE QString formatJoinRuleEvent(const QString &id);
|
||||||
Q_INVOKABLE QString formatHistoryVisibilityEvent(const QString &id);
|
QString formatHistoryVisibilityEvent(
|
||||||
Q_INVOKABLE QString formatGuestAccessEvent(const QString &id);
|
const mtx::events::StateEvent<mtx::events::state::HistoryVisibility> &event) const;
|
||||||
Q_INVOKABLE QString formatPowerLevelEvent(const QString &id);
|
QString
|
||||||
Q_INVOKABLE QString formatImagePackEvent(const QString &id);
|
formatGuestAccessEvent(const mtx::events::StateEvent<mtx::events::state::GuestAccess> &) const;
|
||||||
Q_INVOKABLE QString formatPolicyRule(const QString &id);
|
QString formatPowerLevelEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::state::PowerLevels> &event) const;
|
||||||
|
QString formatImagePackEvent(
|
||||||
|
const mtx::events::StateEvent<mtx::events::msc2545::ImagePack> &event) const;
|
||||||
|
Q_INVOKABLE QString formatPolicyRule(const QString &id) const;
|
||||||
Q_INVOKABLE QVariantMap formatRedactedEvent(const QString &id);
|
Q_INVOKABLE QVariantMap formatRedactedEvent(const QString &id);
|
||||||
|
|
||||||
Q_INVOKABLE void viewRawMessage(const QString &id);
|
Q_INVOKABLE void viewRawMessage(const QString &id);
|
||||||
|
Loading…
Reference in New Issue
Block a user