Unify getUser

Always use `NeoChatRoom::getUser` for getting user details in a room context.
- `MessageEventModel` now calls `getUser`
- `getUser` is now overloaded to also be able to take a `NeoChatUser*`
- add params to `getUser` that are needed for the model outputs
This commit is contained in:
James Graham
2023-05-27 18:27:28 +00:00
parent f2aa375b43
commit e1d4b66479
8 changed files with 120 additions and 61 deletions

View File

@@ -431,33 +431,6 @@ void MessageEventModel::fetchMore(const QModelIndex &parent)
} }
} }
static const QVariantMap emptyUser = {
{"isLocalUser", false},
{"id", QString()},
{"avatarSource", QUrl()},
{"avatarMediaId", QString()},
{"avatarUrl", QString()},
{"displayName", QString()},
{"display", QString()},
{"color", QColor()},
{"object", QVariant()},
};
inline QVariantMap userInContext(NeoChatUser *user, NeoChatRoom *room)
{
return QVariantMap{
{"isLocalUser", user->id() == room->localUser()->id()},
{"id", user->id()},
{"avatarSource", room->avatarForMember(user)},
{"avatarMediaId", user->avatarMediaId(room)},
{"avatarUrl", user->avatarUrl(room)},
{"displayName", user->displayname(room)},
{"display", user->name()},
{"color", user->color()},
{"object", QVariant::fromValue(user)},
};
}
static LinkPreviewer *emptyLinkPreview = new LinkPreviewer; static LinkPreviewer *emptyLinkPreview = new LinkPreviewer;
QVariant MessageEventModel::data(const QModelIndex &idx, int role) const QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
@@ -572,7 +545,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
if (role == AuthorRole) { if (role == AuthorRole) {
auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId())); auto author = static_cast<NeoChatUser *>(isPending ? m_currentRoom->localUser() : m_currentRoom->user(evt.senderId()));
return userInContext(author, m_currentRoom); return m_currentRoom->getUser(author);
} }
if (role == ContentRole) { if (role == ContentRole) {
@@ -715,9 +688,9 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
if (replyPtr) { if (replyPtr) {
auto replyUser = static_cast<NeoChatUser *>(m_currentRoom->user(replyPtr->senderId())); auto replyUser = static_cast<NeoChatUser *>(m_currentRoom->user(replyPtr->senderId()));
return userInContext(replyUser, m_currentRoom); return m_currentRoom->getUser(replyUser);
} else { } else {
return emptyUser; return m_currentRoom->getUser(nullptr);
} }
} }
@@ -853,7 +826,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
#else #else
auto user = static_cast<NeoChatUser *>(userId); auto user = static_cast<NeoChatUser *>(userId);
#endif #endif
users += userInContext(user, m_currentRoom); users += m_currentRoom->getUser(user);
} }
return users; return users;
@@ -1195,7 +1168,7 @@ void MessageEventModel::createReactionModelForEvent(const Quotient::RoomMessageE
while (i != reactions.constEnd()) { while (i != reactions.constEnd()) {
QVariantList authors; QVariantList authors;
for (const auto &author : i.value()) { for (const auto &author : i.value()) {
authors.append(userInContext(author, m_currentRoom)); authors.append(m_currentRoom->getUser(author));
} }
res.append(ReactionModel::Reaction{i.key(), authors}); res.append(ReactionModel::Reaction{i.key(), authors});

View File

@@ -459,13 +459,38 @@ QVariantList NeoChatRoom::getUsers(const QString &keyword, int limit) const
return matchedList; return matchedList;
} }
// An empty user is useful for returning as a model value to avoid properties being undefined.
static const QVariantMap emptyUser = {
{"isLocalUser", false},
{"id", QString()},
{"displayName", QString()},
{"avatarSource", QUrl()},
{"avatarMediaId", QString()},
{"color", QColor()},
{"object", QVariant()},
};
QVariantMap NeoChatRoom::getUser(const QString &userID) const QVariantMap NeoChatRoom::getUser(const QString &userID) const
{ {
NeoChatUser user(userID, connection()); NeoChatUser *userObject = static_cast<NeoChatUser *>(user(userID));
return QVariantMap{{QStringLiteral("id"), user.id()}, return getUser(userObject);
{QStringLiteral("displayName"), user.displayname(this)}, }
{QStringLiteral("avatarMediaId"), user.avatarMediaId(this)},
{QStringLiteral("color"), user.color()}}; QVariantMap NeoChatRoom::getUser(NeoChatUser *user) const
{
if (user == nullptr) {
return emptyUser;
}
return QVariantMap{
{QStringLiteral("isLocalUser"), user->id() == localUser()->id()},
{QStringLiteral("id"), user->id()},
{QStringLiteral("displayName"), user->displayname(this)},
{QStringLiteral("avatarSource"), avatarForMember(user)},
{QStringLiteral("avatarMediaId"), user->avatarMediaId(this)},
{QStringLiteral("color"), user->color()},
{QStringLiteral("object"), QVariant::fromValue(user)},
};
} }
QString NeoChatRoom::avatarMediaId() const QString NeoChatRoom::avatarMediaId() const
@@ -1768,12 +1793,12 @@ void NeoChatRoom::setChatBoxEditId(const QString &editId)
Q_EMIT chatBoxEditIdChanged(); Q_EMIT chatBoxEditIdChanged();
} }
NeoChatUser *NeoChatRoom::chatBoxReplyUser() const QVariantMap NeoChatRoom::chatBoxReplyUser() const
{ {
if (m_chatBoxReplyId.isEmpty()) { if (m_chatBoxReplyId.isEmpty()) {
return nullptr; return emptyUser;
} }
return static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxReplyId))->senderId())); return getUser(static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxReplyId))->senderId())));
} }
QString NeoChatRoom::chatBoxReplyMessage() const QString NeoChatRoom::chatBoxReplyMessage() const
@@ -1784,12 +1809,12 @@ QString NeoChatRoom::chatBoxReplyMessage() const
return eventToString(*static_cast<const RoomMessageEvent *>(&**findInTimeline(m_chatBoxReplyId))); return eventToString(*static_cast<const RoomMessageEvent *>(&**findInTimeline(m_chatBoxReplyId)));
} }
NeoChatUser *NeoChatRoom::chatBoxEditUser() const QVariantMap NeoChatRoom::chatBoxEditUser() const
{ {
if (m_chatBoxEditId.isEmpty()) { if (m_chatBoxEditId.isEmpty()) {
return nullptr; return emptyUser;
} }
return static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxEditId))->senderId())); return getUser(static_cast<NeoChatUser *>(user((*findInTimeline(m_chatBoxEditId))->senderId())));
} }
QString NeoChatRoom::chatBoxEditMessage() const QString NeoChatRoom::chatBoxEditMessage() const

View File

@@ -315,11 +315,26 @@ class NeoChatRoom : public Quotient::Room
Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged) Q_PROPERTY(QString chatBoxEditId READ chatBoxEditId WRITE setChatBoxEditId NOTIFY chatBoxEditIdChanged)
/** /**
* @brief Get the user object for the message being replied to. * @brief Get the user for the message being replied to.
* *
* Returns a nullptr if not replying to a message. * This is different to getting a NeoChatUser object or Quotient::User object
* as neither of those can provide details like the displayName or avatarMediaId
* without the room context as these can vary from room to room.
*
* Returns an empty user if not replying to a message.
*
* The user QVariantMap has the following properties:
* - isLocalUser - Whether the user is the local user.
* - id - The matrix ID of the user.
* - displayName - Display name in the context of this room.
* - avatarSource - The mxc URL for the user's avatar in the current room.
* - avatarMediaId - Avatar id in the context of this room.
* - color - Color for the user.
* - object - The NeoChatUser object for the user.
*
* @sa getUser, Quotient::User, NeoChatUser
*/ */
Q_PROPERTY(NeoChatUser *chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged) Q_PROPERTY(QVariantMap chatBoxReplyUser READ chatBoxReplyUser NOTIFY chatBoxReplyIdChanged)
/** /**
* @brief The content of the message being replied to. * @brief The content of the message being replied to.
@@ -329,11 +344,26 @@ class NeoChatRoom : public Quotient::Room
Q_PROPERTY(QString chatBoxReplyMessage READ chatBoxReplyMessage NOTIFY chatBoxReplyIdChanged) Q_PROPERTY(QString chatBoxReplyMessage READ chatBoxReplyMessage NOTIFY chatBoxReplyIdChanged)
/** /**
* @brief Get the user object for the message being edited. * @brief Get the user for the message being edited.
* *
* Returns a nullptr if not editing a message. * This is different to getting a NeoChatUser object or Quotient::User object
* as neither of those can provide details like the displayName or avatarMediaId
* without the room context as these can vary from room to room.
*
* Returns an empty user if not replying to a message.
*
* The user QVariantMap has the following properties:
* - isLocalUser - Whether the user is the local user.
* - id - The matrix ID of the user.
* - displayName - Display name in the context of this room.
* - avatarSource - The mxc URL for the user's avatar in the current room.
* - avatarMediaId - Avatar id in the context of this room.
* - color - Color for the user.
* - object - The NeoChatUser object for the user.
*
* @sa getUser, Quotient::User, NeoChatUser
*/ */
Q_PROPERTY(NeoChatUser *chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged) Q_PROPERTY(QVariantMap chatBoxEditUser READ chatBoxEditUser NOTIFY chatBoxEditIdChanged)
/** /**
* @brief The content of the message being edited. * @brief The content of the message being edited.
@@ -390,18 +420,50 @@ public:
* without the room context as these can vary from room to room. This function * without the room context as these can vary from room to room. This function
* provides the room context and outputs the result as QVariantMap. * provides the room context and outputs the result as QVariantMap.
* *
* Can be called with an empty QString to return an empty user, which is a useful return
* from models to avoid undefined properties.
*
* @param userID the ID of the user to output. * @param userID the ID of the user to output.
* *
* @return a QVariantMap for the user with the following properties: * @return a QVariantMap for the user with the following properties:
* - id - User ID. * - isLocalUser - Whether the user is the local user.
* - id - The matrix ID of the user.
* - displayName - Display name in the context of this room. * - displayName - Display name in the context of this room.
* - avatarSource - The mxc URL for the user's avatar in the current room.
* - avatarMediaId - Avatar id in the context of this room. * - avatarMediaId - Avatar id in the context of this room.
* - color - Color for the user. * - color - Color for the user.
* - object - The NeoChatUser object for the user.
* *
* @sa Quotient::User, NeoChatUser * @sa Quotient::User, NeoChatUser
*/ */
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const; Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
/**
* @brief Get a user in the context of this room.
*
* This is different to getting a NeoChatUser object or Quotient::User object
* as neither of those can provide details like the displayName or avatarMediaId
* without the room context as these can vary from room to room. This function
* provides the room context and outputs the result as QVariantMap.
*
* Can be called with a nullptr to return an empty user, which is a useful return
* from models to avoid undefined properties.
*
* @param user the user to output.
*
* @return a QVariantMap for the user with the following properties:
* - isLocalUser - Whether the user is the local user.
* - id - The matrix ID of the user.
* - displayName - Display name in the context of this room.
* - avatarSource - The mxc URL for the user's avatar in the current room.
* - avatarMediaId - Avatar id in the context of this room.
* - color - Color for the user.
* - object - The NeoChatUser object for the user.
*
* @sa Quotient::User, NeoChatUser
*/
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(NeoChatUser *user) const;
[[nodiscard]] QVariantList getUsersTyping() const; [[nodiscard]] QVariantList getUsersTyping() const;
[[nodiscard]] QDateTime lastActiveTime(); [[nodiscard]] QDateTime lastActiveTime();
@@ -704,13 +766,13 @@ public:
QString chatBoxReplyId() const; QString chatBoxReplyId() const;
void setChatBoxReplyId(const QString &replyId); void setChatBoxReplyId(const QString &replyId);
NeoChatUser *chatBoxReplyUser() const; QVariantMap chatBoxReplyUser() const;
QString chatBoxReplyMessage() const; QString chatBoxReplyMessage() const;
QString chatBoxEditId() const; QString chatBoxEditId() const;
void setChatBoxEditId(const QString &editId); void setChatBoxEditId(const QString &editId);
NeoChatUser *chatBoxEditUser() const; QVariantMap chatBoxEditUser() const;
QString chatBoxEditMessage() const; QString chatBoxEditMessage() const;
QString chatBoxAttachmentPath() const; QString chatBoxAttachmentPath() const;

View File

@@ -15,7 +15,6 @@ QQC2.Control {
property alias textField: textField property alias textField: textField
property bool isReplying: currentRoom.chatBoxReplyId.length > 0 property bool isReplying: currentRoom.chatBoxReplyId.length > 0
property NeoChatUser replyUser: currentRoom.chatBoxReplyUser
property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0 property bool attachmentPaneVisible: currentRoom.chatBoxAttachmentPath.length > 0
signal messageSent() signal messageSent()
@@ -244,9 +243,9 @@ QQC2.Control {
Component { Component {
id: replyPane id: replyPane
ReplyPane { ReplyPane {
userName: root.replyUser ? root.replyUser.displayName : "" userName: currentRoom.chatBoxReplyUser.displayName
userColor: root.replyUser ? root.replyUser.color : "" userColor: currentRoom.chatBoxReplyUser.color
userAvatar: root.replyUser ? "image://mxc/" + currentRoom.getUser(root.replyUser.id).avatarMediaId : "" userAvatar: currentRoom.chatBoxReplyUser.avatarSource
text: currentRoom.chatBoxReplyMessage text: currentRoom.chatBoxReplyMessage
} }
} }

View File

@@ -54,7 +54,7 @@ Components.AlbumMaximizeComponent {
implicitWidth: Kirigami.Units.iconSizes.medium implicitWidth: Kirigami.Units.iconSizes.medium
implicitHeight: Kirigami.Units.iconSizes.medium implicitHeight: Kirigami.Units.iconSizes.medium
name: root.author.name ?? root.author.displayName name: root.author.displayName
source: root.author.avatarSource source: root.author.avatarSource
color: root.author.color color: root.author.color
} }
@@ -62,7 +62,7 @@ Components.AlbumMaximizeComponent {
spacing: 0 spacing: 0
QQC2.Label { QQC2.Label {
id: userLabel id: userLabel
text: root.author.name ?? root.author.displayName text: root.author.displayName
color: root.author.color color: root.author.color
font.weight: Font.Bold font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight

View File

@@ -93,7 +93,7 @@ TimelineContainer {
visible: root.asset === "m.self" visible: root.asset === "m.self"
width: height width: height
height: parent.height / 3 + 1 height: parent.height / 3 + 1
name: root.author.name ?? root.author.displayName name: root.author.displayName
source: root.author.avatarSource source: root.author.avatarSource
color: root.author.color color: root.author.color
} }

View File

@@ -100,7 +100,7 @@ Item {
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
source: root.author.avatarSource source: root.author.avatarSource
name: root.author.displayName || "" name: root.author.displayName
color: root.author.color color: root.author.color
} }
QQC2.Label { QQC2.Label {

View File

@@ -381,7 +381,7 @@ ColumnLayout {
visible: root.showAuthor && visible: root.showAuthor &&
Config.showAvatarInTimeline && Config.showAvatarInTimeline &&
(Config.compactLayout || !showUserMessageOnRight) (Config.compactLayout || !showUserMessageOnRight)
name: root.author.name ?? root.author.displayName name: root.author.displayName
source: root.author.avatarSource source: root.author.avatarSource
color: root.author.color color: root.author.color