aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/user.cpp58
1 files changed, 44 insertions, 14 deletions
diff --git a/lib/user.cpp b/lib/user.cpp
index dac1bb68..3c9652b0 100644
--- a/lib/user.cpp
+++ b/lib/user.cpp
@@ -109,10 +109,24 @@ bool User::isGuest() const
int User::hue() const { return int(hueF() * 359); }
+/// \sa https://github.com/matrix-org/matrix-doc/issues/1375
+///
+/// Relies on untrusted prevContent so can't be put to RoomMemberEvent and
+/// in general should rather be remade in terms of the room's eventual "state
+/// time machine"
+QString getBestKnownName(const RoomMemberEvent* event)
+{
+ const auto& jv = event->contentJson().value("displayname"_ls);
+ return !jv.isUndefined()
+ ? jv.toString()
+ : event->prevContent() ? event->prevContent()->displayName
+ : QString();
+}
+
QString User::name(const Room* room) const
{
if (room)
- return room->getCurrentState<RoomMemberEvent>(id())->displayName();
+ return getBestKnownName(room->getCurrentState<RoomMemberEvent>(id()));
if (d->defaultName.isNull())
d->fetchProfile(this);
@@ -232,6 +246,16 @@ QString User::fullName(const Room* room) const
QString User::bridged() const { return {}; }
+/// \sa getBestKnownName, https://github.com/matrix-org/matrix-doc/issues/1375
+QUrl getBestKnownAvatarUrl(const RoomMemberEvent* event)
+{
+ const auto& jv = event->contentJson().value("avatar_url"_ls);
+ return !jv.isUndefined()
+ ? jv.toString()
+ : event->prevContent() ? event->prevContent()->avatarUrl
+ : QUrl();
+}
+
const Avatar& User::avatarObject(const Room* room) const
{
if (!room) {
@@ -241,7 +265,8 @@ const Avatar& User::avatarObject(const Room* room) const
return *d->defaultAvatar;
}
- const auto& url = room->getCurrentState<RoomMemberEvent>(id())->avatarUrl();
+ const auto& url =
+ getBestKnownAvatarUrl(room->getCurrentState<RoomMemberEvent>(id()));
const auto& mediaId = url.authority() + url.path();
return d->otherAvatars.try_emplace(mediaId, url).first->second;
}
@@ -280,21 +305,26 @@ void User::processEvent(const RoomMemberEvent& event, const Room* room,
{
Q_ASSERT(room);
- const auto& oldName = firstMention || !event.prevContent() ? QString()
- : event.prevContent()->displayName;
- const auto& newName = event.displayName();
- // A hacky way to find out if it's about to change or already changed
- bool isAboutToChange = room->getCurrentState<RoomMemberEvent>(id()) != &event;
- if (newName != oldName) {
- if (isAboutToChange)
+ // This is prone to abuse if prevContent is forged; only here until 0.7
+ // (and the whole method, actually).
+ const auto& oldName = event.prevContent() ? event.prevContent()->displayName
+ : QString();
+ const auto& newName = getBestKnownName(&event);
+ // A hacky way to find out if it's about to change or already changed;
+ // making it a lambda allows to omit stub event creation when unneeded
+ const auto& isAboutToChange = [&event, room, this] {
+ return room->getCurrentState<RoomMemberEvent>(id()) != &event;
+ };
+ if (firstMention || newName != oldName) {
+ if (isAboutToChange())
emit nameAboutToChange(newName, oldName, room);
- else {
+ else
emit nameChanged(newName, oldName, room);
- }
}
- const auto& oldAvatarUrl = firstMention || !event.prevContent() ? QUrl()
- : event.prevContent()->avatarUrl;
- if (event.avatarUrl() != oldAvatarUrl && !isAboutToChange)
+ const auto& oldAvatarUrl =
+ event.prevContent() ? event.prevContent()->avatarUrl : QUrl();
+ const auto& newAvatarUrl = getBestKnownAvatarUrl(&event);
+ if ((firstMention || newAvatarUrl != oldAvatarUrl) && !isAboutToChange())
emit avatarChanged(this, room);
}