Limit the maximum number of avatars shown
Limit the maximum number of avatars shown for other user read markers and collapsed state events For state events \  For read markers \ 
This commit is contained in:
@@ -24,6 +24,8 @@ QVariant CollapseStateProxyModel::data(const QModelIndex &index, int role) const
|
|||||||
return stateEventsList(mapToSource(index).row());
|
return stateEventsList(mapToSource(index).row());
|
||||||
} else if (role == AuthorListRole) {
|
} else if (role == AuthorListRole) {
|
||||||
return authorList(mapToSource(index).row());
|
return authorList(mapToSource(index).row());
|
||||||
|
} else if (role == ExcessAuthorsRole) {
|
||||||
|
return excessAuthors(mapToSource(index).row());
|
||||||
}
|
}
|
||||||
return sourceModel()->data(mapToSource(index), role);
|
return sourceModel()->data(mapToSource(index), role);
|
||||||
}
|
}
|
||||||
@@ -34,6 +36,7 @@ QHash<int, QByteArray> CollapseStateProxyModel::roleNames() const
|
|||||||
roles[AggregateDisplayRole] = "aggregateDisplay";
|
roles[AggregateDisplayRole] = "aggregateDisplay";
|
||||||
roles[StateEventsRole] = "stateEvents";
|
roles[StateEventsRole] = "stateEvents";
|
||||||
roles[AuthorListRole] = "authorList";
|
roles[AuthorListRole] = "authorList";
|
||||||
|
roles[ExcessAuthorsRole] = "excessAuthors";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,5 +133,39 @@ QVariantList CollapseStateProxyModel::authorList(int sourceRow) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uniqueAuthors.count() > 5) {
|
||||||
|
uniqueAuthors = uniqueAuthors.mid(0, 5);
|
||||||
|
}
|
||||||
return uniqueAuthors;
|
return uniqueAuthors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CollapseStateProxyModel::excessAuthors(int row) const
|
||||||
|
{
|
||||||
|
QVariantList uniqueAuthors;
|
||||||
|
for (int i = row; i >= 0; i--) {
|
||||||
|
QVariant nextAvatar = sourceModel()->data(sourceModel()->index(i, 0), MessageEventModel::AuthorRole);
|
||||||
|
if (!uniqueAuthors.contains(nextAvatar)) {
|
||||||
|
uniqueAuthors.append(nextAvatar);
|
||||||
|
}
|
||||||
|
if (sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::DelegateTypeRole)
|
||||||
|
!= MessageEventModel::DelegateType::State // If it's not a state event
|
||||||
|
|| sourceModel()->data(sourceModel()->index(i - 1, 0), MessageEventModel::ShowSectionRole).toBool() // or the section needs to be visible
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int excessAuthors;
|
||||||
|
if (uniqueAuthors.count() > 5) {
|
||||||
|
excessAuthors = uniqueAuthors.count() - 5;
|
||||||
|
} else {
|
||||||
|
excessAuthors = 0;
|
||||||
|
}
|
||||||
|
QString excessAuthorsString;
|
||||||
|
if (excessAuthors == 0) {
|
||||||
|
return QString();
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("+ %1").arg(excessAuthors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ public:
|
|||||||
enum Roles {
|
enum Roles {
|
||||||
AggregateDisplayRole = MessageEventModel::LastRole + 1, /**< Single line aggregation of all the state events. */
|
AggregateDisplayRole = MessageEventModel::LastRole + 1, /**< Single line aggregation of all the state events. */
|
||||||
StateEventsRole, /**< List of state events in the aggregated state. */
|
StateEventsRole, /**< List of state events in the aggregated state. */
|
||||||
AuthorListRole, /**< List of unique authors of the aggregated state event. */
|
AuthorListRole, /**< List of the first 5 unique authors of the aggregated state event. */
|
||||||
|
ExcessAuthorsRole, /**< The number of unique authors beyond the first 5. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +68,12 @@ private:
|
|||||||
[[nodiscard]] QVariantList stateEventsList(int row) const;
|
[[nodiscard]] QVariantList stateEventsList(int row) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief List of unique authors for the aggregate state events starting at row.
|
* @brief List of the first 5 unique authors for the aggregate state events starting at row.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] QVariantList authorList(int row) const;
|
[[nodiscard]] QVariantList authorList(int row) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of unique authors beyond the first 5 for the aggregate state events starting at row.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] QString excessAuthors(int row) const;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ QHash<int, QByteArray> MessageEventModel::roleNames() const
|
|||||||
roles[ShowAuthorRole] = "showAuthor";
|
roles[ShowAuthorRole] = "showAuthor";
|
||||||
roles[ShowSectionRole] = "showSection";
|
roles[ShowSectionRole] = "showSection";
|
||||||
roles[ReadMarkersRole] = "readMarkers";
|
roles[ReadMarkersRole] = "readMarkers";
|
||||||
|
roles[ExcessReadMarkersRole] = "excessReadMarkers";
|
||||||
roles[ReadMarkersStringRole] = "readMarkersString";
|
roles[ReadMarkersStringRole] = "readMarkersString";
|
||||||
roles[ShowReadMarkersRole] = "showReadMarkers";
|
roles[ShowReadMarkersRole] = "showReadMarkers";
|
||||||
roles[ReactionRole] = "reaction";
|
roles[ReactionRole] = "reaction";
|
||||||
@@ -248,7 +249,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
|||||||
connect(m_currentRoom, &Room::changed, this, [this]() {
|
connect(m_currentRoom, &Room::changed, this, [this]() {
|
||||||
for (auto it = m_currentRoom->messageEvents().rbegin(); it != m_currentRoom->messageEvents().rend(); ++it) {
|
for (auto it = m_currentRoom->messageEvents().rbegin(); it != m_currentRoom->messageEvents().rend(); ++it) {
|
||||||
auto event = it->event();
|
auto event = it->event();
|
||||||
refreshEventRoles(event->id(), {ReadMarkersRole, ReadMarkersStringRole});
|
refreshEventRoles(event->id(), {ReadMarkersRole, ReadMarkersStringRole, ExcessReadMarkersRole});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(m_currentRoom, &Room::newFileTransfer, this, &MessageEventModel::refreshEvent);
|
connect(m_currentRoom, &Room::newFileTransfer, this, &MessageEventModel::refreshEvent);
|
||||||
@@ -852,8 +853,13 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
|
|
||||||
if (role == ReadMarkersRole) {
|
if (role == ReadMarkersRole) {
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
auto userIds = room()->userIdsAtEvent(evt.id());
|
auto userIds_temp = room()->userIdsAtEvent(evt.id());
|
||||||
userIds.remove(m_currentRoom->localUser()->id());
|
userIds_temp.remove(m_currentRoom->localUser()->id());
|
||||||
|
|
||||||
|
auto userIds = userIds_temp.values();
|
||||||
|
if (userIds.count() > 5) {
|
||||||
|
userIds = userIds.mid(0, 5);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
auto userIds = room()->usersAtEventId(evt.id());
|
auto userIds = room()->usersAtEventId(evt.id());
|
||||||
userIds.removeAll(m_currentRoom->localUser());
|
userIds.removeAll(m_currentRoom->localUser());
|
||||||
@@ -873,6 +879,22 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (role == ExcessReadMarkersRole) {
|
||||||
|
#ifdef QUOTIENT_07
|
||||||
|
auto userIds = room()->userIdsAtEvent(evt.id());
|
||||||
|
userIds.remove(m_currentRoom->localUser()->id());
|
||||||
|
#else
|
||||||
|
auto userIds = room()->usersAtEventId(evt.id());
|
||||||
|
userIds.removeAll(m_currentRoom->localUser());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (userIds.count() > 5) {
|
||||||
|
return QStringLiteral("+ ") + QString::number(userIds.count() - 5);
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (role == ReadMarkersStringRole) {
|
if (role == ReadMarkersStringRole) {
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
auto userIds = room()->userIdsAtEvent(evt.id());
|
auto userIds = room()->userIdsAtEvent(evt.id());
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ public:
|
|||||||
ShowAuthorRole, /**< Whether the author's name should be shown. */
|
ShowAuthorRole, /**< Whether the author's name should be shown. */
|
||||||
ShowSectionRole, /**< Whether the section header should be shown. */
|
ShowSectionRole, /**< Whether the section header should be shown. */
|
||||||
|
|
||||||
ReadMarkersRole, /**< Other users at the event for read marker tracking. */
|
ReadMarkersRole, /**< The first 5 other users at the event for read marker tracking. */
|
||||||
|
ExcessReadMarkersRole, /**< The number of other users at the event after the first 5. */
|
||||||
ReadMarkersStringRole, /**< String with the display name and mxID of the users at the event. */
|
ReadMarkersStringRole, /**< String with the display name and mxID of the users at the event. */
|
||||||
ShowReadMarkersRole, /**< Whether there are any other user read markers to be shown. */
|
ShowReadMarkersRole, /**< Whether there are any other user read markers to be shown. */
|
||||||
ReactionRole, /**< List of reactions to this event. */
|
ReactionRole, /**< List of reactions to this event. */
|
||||||
|
|||||||
@@ -12,19 +12,46 @@ Flow {
|
|||||||
property var avatarSize: Kirigami.Units.iconSizes.small
|
property var avatarSize: Kirigami.Units.iconSizes.small
|
||||||
property alias model: avatarFlowRepeater.model
|
property alias model: avatarFlowRepeater.model
|
||||||
property string toolTipText
|
property string toolTipText
|
||||||
|
property alias excessAvatars: excessAvatarsLabel.text
|
||||||
|
|
||||||
spacing: -avatarSize / 2
|
spacing: -avatarSize / 2
|
||||||
Repeater {
|
Repeater {
|
||||||
id: avatarFlowRepeater
|
id: avatarFlowRepeater
|
||||||
delegate: Kirigami.Avatar {
|
delegate: Kirigami.Avatar {
|
||||||
|
topInset: Kirigami.Units.smallSpacing / 2
|
||||||
|
topPadding: Kirigami.Units.smallSpacing / 2
|
||||||
implicitWidth: avatarSize
|
implicitWidth: avatarSize
|
||||||
implicitHeight: avatarSize
|
implicitHeight: avatarSize + Kirigami.Units.smallSpacing / 2
|
||||||
|
|
||||||
name: modelData.displayName
|
name: modelData.displayName
|
||||||
source: modelData.avatarSource
|
source: modelData.avatarSource
|
||||||
color: modelData.color
|
color: modelData.color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QQC2.Label {
|
||||||
|
id: excessAvatarsLabel
|
||||||
|
visible: text !== ""
|
||||||
|
color: Kirigami.Theme.textColor
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
background: Kirigami.ShadowedRectangle {
|
||||||
|
color: Kirigami.Theme.backgroundColor
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
|
radius: height / 2
|
||||||
|
shadow.size: Kirigami.Units.smallSpacing
|
||||||
|
shadow.color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||||
|
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
height: Kirigami.Units.iconSizes.small + Kirigami.Units.smallSpacing
|
||||||
|
width: Math.max(excessAvatarsTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: excessAvatarsTextMetrics
|
||||||
|
text: excessAvatarsLabel.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QQC2.ToolTip.text: toolTipText
|
QQC2.ToolTip.text: toolTipText
|
||||||
QQC2.ToolTip.visible: hoverHandler.hovered
|
QQC2.ToolTip.visible: hoverHandler.hovered
|
||||||
|
|||||||
@@ -78,14 +78,41 @@ QQC2.Control {
|
|||||||
Repeater {
|
Repeater {
|
||||||
model: authorList
|
model: authorList
|
||||||
delegate: Kirigami.Avatar {
|
delegate: Kirigami.Avatar {
|
||||||
|
topInset: Kirigami.Units.smallSpacing / 2
|
||||||
|
topPadding: Kirigami.Units.smallSpacing / 2
|
||||||
implicitWidth: Kirigami.Units.iconSizes.small
|
implicitWidth: Kirigami.Units.iconSizes.small
|
||||||
implicitHeight: Kirigami.Units.iconSizes.small
|
implicitHeight: Kirigami.Units.iconSizes.small + Kirigami.Units.smallSpacing / 2
|
||||||
|
|
||||||
name: modelData.displayName
|
name: modelData.displayName
|
||||||
source: modelData.avatarSource
|
source: modelData.avatarSource
|
||||||
color: modelData.color
|
color: modelData.color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QQC2.Label {
|
||||||
|
id: excessAuthorsLabel
|
||||||
|
text: model.excessAuthors
|
||||||
|
visible: model.excessAuthors !== ""
|
||||||
|
color: Kirigami.Theme.textColor
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
background: Kirigami.ShadowedRectangle {
|
||||||
|
color: Kirigami.Theme.backgroundColor
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||||
|
radius: height / 2
|
||||||
|
shadow.size: Kirigami.Units.smallSpacing
|
||||||
|
shadow.color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
|
||||||
|
border.color: Kirigami.ColorUtils.tintWithAlpha(color, Kirigami.Theme.textColor, 0.15)
|
||||||
|
border.width: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
height: Kirigami.Units.iconSizes.small + Kirigami.Units.smallSpacing
|
||||||
|
width: Math.max(excessAuthorsTextMetrics.advanceWidth + Kirigami.Units.smallSpacing * 2, height)
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: excessAuthorsTextMetrics
|
||||||
|
text: excessAuthorsLabel.text
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
QQC2.Label {
|
QQC2.Label {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -140,6 +167,7 @@ QQC2.Control {
|
|||||||
visible: showReadMarkers
|
visible: showReadMarkers
|
||||||
model: readMarkers
|
model: readMarkers
|
||||||
toolTipText: readMarkersString
|
toolTipText: readMarkersString
|
||||||
|
excessAvatars: excessReadMarkers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ ColumnLayout {
|
|||||||
visible: showReadMarkers
|
visible: showReadMarkers
|
||||||
model: readMarkers
|
model: readMarkers
|
||||||
toolTipText: readMarkersString
|
toolTipText: readMarkersString
|
||||||
|
excessAvatars: excessReadMarkers
|
||||||
}
|
}
|
||||||
|
|
||||||
function isVisibleInTimeline() {
|
function isVisibleInTimeline() {
|
||||||
|
|||||||
Reference in New Issue
Block a user