Skip to content
Snippets Groups Projects
Commit 86960e67 authored by Nicolas Werner's avatar Nicolas Werner
Browse files

Implement display of membership events

parent 8f660d52
No related branches found
No related tags found
No related merge requests found
......@@ -78,6 +78,12 @@ Item {
notice: model.data.roomTopic ? qsTr("topic changed to: %1").arg(model.data.roomTopic) : qsTr("removed topic")
}
}
DelegateChoice {
roleValue: MtxEvent.Member
NoticeMessage {
notice: timelineManager.timeline.formatMemberEvent(model.data.id);
}
}
DelegateChoice {
Placeholder {}
}
......
......@@ -189,7 +189,7 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
connect(this, &TimelineModel::newMessageToSend, this, &TimelineModel::addPendingMessage);
connect(this,
&TimelineModel::replyFetched,
&TimelineModel::eventFetched,
this,
[this](QString requestingEvent, mtx::events::collections::TimelineEvents event) {
events.insert(QString::fromStdString(mtx::accessors::event_id(event)),
......@@ -566,7 +566,7 @@ TimelineModel::internalAddEvents(
id.toStdString());
return;
}
emit replyFetched(id, timeline);
emit eventFetched(id, timeline);
});
}
}
......@@ -1442,3 +1442,101 @@ TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg)
return temp.arg(uidWithoutLast.join(", ")).arg(formatUser(users.back()));
}
QString
TimelineModel::formatMemberEvent(QString id)
{
if (!events.contains(id))
return "";
auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(&events[id]);
if (!event)
return "";
mtx::events::StateEvent<mtx::events::state::Member> *prevEvent = nullptr;
QString prevEventId = QString::fromStdString(event->unsigned_data.replaces_state);
if (!prevEventId.isEmpty()) {
if (!events.contains(prevEventId)) {
http::client()->get_event(
this->room_id_.toStdString(),
event->unsigned_data.replaces_state,
[this, id, prevEventId](
const mtx::events::collections::TimelineEvents &timeline,
mtx::http::RequestErr err) {
if (err) {
nhlog::net()->error(
"Failed to retrieve event with id {}, which was "
"requested to show the membership for event {}",
prevEventId.toStdString(),
id.toStdString());
return;
}
emit eventFetched(id, timeline);
});
} else {
prevEvent =
std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(
&events[prevEventId]);
}
}
QString user = QString::fromStdString(event->state_key);
QString name = escapeEmoji(displayName(user));
// see table https://matrix.org/docs/spec/client_server/latest#m-room-member
using namespace mtx::events::state;
switch (event->content.membership) {
case Membership::Invite:
return tr("%1 was invited.").arg(name);
case Membership::Join:
if (prevEvent && prevEvent->content.membership == Membership::Join) {
bool displayNameChanged =
prevEvent->content.display_name != event->content.display_name;
bool avatarChanged =
prevEvent->content.avatar_url != event->content.avatar_url;
if (displayNameChanged && avatarChanged)
return tr("%1 changed their display name and avatar.").arg(name);
else if (displayNameChanged)
return tr("%1 changed their display name.").arg(name);
else if (avatarChanged)
return tr("%1 changed their avatar.").arg(name);
// the case of nothing changed but join follows join shouldn't happen, so
// just show it as join
}
return tr("%1 joined.").arg(name);
case Membership::Leave:
if (!prevEvent) // Should only ever happen temporarily
return "";
if (prevEvent->content.membership == Membership::Invite) {
if (event->state_key == event->sender)
return tr("%1 rejected their invite.").arg(name);
else
return tr("Revoked the invite to %1.").arg(name);
} else if (prevEvent->content.membership == Membership::Join) {
if (event->state_key == event->sender)
return tr("%1 left the room.").arg(name);
else
return tr("Kicked %1.").arg(name);
} else if (prevEvent->content.membership == Membership::Ban) {
return tr("Unbanned %1").arg(name);
} else if (prevEvent->content.membership == Membership::Knock) {
if (event->state_key == event->sender)
return tr("%1 redacted their knock.").arg(name);
else
return tr("Rejected the knock from %1.").arg(name);
} else
return tr("%1 left after having already left!",
"This is a leave event after the user already left and shouln't "
"happen apart from state resets")
.arg(name);
case Membership::Ban:
return tr("%1 was banned.").arg(name);
case Membership::Knock:
return tr("%1 knocked.").arg(name);
default:
return "";
}
}
......@@ -165,6 +165,7 @@ public:
Q_INVOKABLE QString avatarUrl(QString id) const;
Q_INVOKABLE QString formatDateSeparator(QDate date) const;
Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg);
Q_INVOKABLE QString formatMemberEvent(QString id);
Q_INVOKABLE QString escapeEmoji(QString str) const;
Q_INVOKABLE void viewRawMessage(QString id) const;
......@@ -212,7 +213,7 @@ signals:
void newMessageToSend(mtx::events::collections::TimelineEvents event);
void mediaCached(QString mxcUrl, QString cacheUrl);
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
void replyFetched(QString requestingEvent, mtx::events::collections::TimelineEvents event);
void eventFetched(QString requestingEvent, mtx::events::collections::TimelineEvents event);
void typingUsersChanged(std::vector<QString> users);
private:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment