Add dialog to see who has read this message
You were previously relegated to looking at any avatars or a buggy tooltip, but suffer no longer! If you tap on a message's read marker, a dialog will pop up listing the users who have read it. Uou can also view their profiles from here, etc.
This commit is contained in:
@@ -106,6 +106,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
|
||||
qml/NewPollDialog.qml
|
||||
qml/UserMenu.qml
|
||||
qml/MeetingDialog.qml
|
||||
qml/SeenByDialog.qml
|
||||
DEPENDENCIES
|
||||
QtCore
|
||||
QtQuick
|
||||
|
||||
90
src/app/qml/SeenByDialog.qml
Normal file
90
src/app/qml/SeenByDialog.qml
Normal file
@@ -0,0 +1,90 @@
|
||||
// SPDX-FileCopyrightText: 2026 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.components as KirigamiComponents
|
||||
import org.kde.kirigamiaddons.delegates as Delegates
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Dialog {
|
||||
id: root
|
||||
|
||||
property var model
|
||||
|
||||
standardButtons: Kirigami.Dialog.NoButton
|
||||
|
||||
width: Math.min(QQC2.ApplicationWindow.window.width, Kirigami.Units.gridUnit * 24)
|
||||
maximumHeight: Kirigami.Units.gridUnit * 24
|
||||
title: i18nc("@title:menu Seen by/read marker dialog", "Seen By")
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
QQC2.ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
|
||||
model: root.model
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
onCountChanged: {
|
||||
if (listView.count === 0) {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Delegates.RoundedItemDelegate {
|
||||
id: userDelegate
|
||||
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
required property color memberColor
|
||||
required property string userId
|
||||
|
||||
implicitHeight: Kirigami.Units.gridUnit * 2
|
||||
|
||||
text: displayName
|
||||
highlighted: false
|
||||
|
||||
onClicked: {
|
||||
root.close();
|
||||
RoomManager.resolveResource(userDelegate.userId);
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
KirigamiComponents.Avatar {
|
||||
implicitWidth: height
|
||||
sourceSize {
|
||||
height: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
|
||||
width: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
|
||||
}
|
||||
source: userDelegate.avatarUrl
|
||||
name: userDelegate.displayName
|
||||
color: userDelegate.memberColor
|
||||
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
QQC2.Label {
|
||||
text: userDelegate.displayName
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
clip: true // Intentional to limit insane Unicode in display names
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,24 @@ import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property var avatarSize: Kirigami.Units.iconSizes.small
|
||||
property alias model: avatarFlowRepeater.model
|
||||
property alias model: root.limiterModel.sourceModel
|
||||
property string toolTipText
|
||||
|
||||
property LimiterModel limiterModel: LimiterModel {
|
||||
maximumCount: 5
|
||||
}
|
||||
|
||||
spacing: -avatarSize / 2
|
||||
Repeater {
|
||||
id: avatarFlowRepeater
|
||||
model: root.limiterModel
|
||||
|
||||
delegate: KirigamiComponents.Avatar {
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
@@ -39,11 +47,11 @@ RowLayout {
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.small + Kirigami.Units.smallSpacing
|
||||
Layout.fillHeight: true
|
||||
|
||||
visible: text !== ""
|
||||
visible: root.limiterModel.extraCount > 0
|
||||
color: Kirigami.Theme.textColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: root.model?.excessReadMarkersString ?? ""
|
||||
text: "+ " + root.limiterModel.extraCount
|
||||
|
||||
background: Kirigami.ShadowedRectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
@@ -208,6 +208,15 @@ MessageDelegateBase {
|
||||
|
||||
readMarkerComponent: AvatarFlow {
|
||||
model: root.readMarkers
|
||||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
const dialog = Qt.createComponent("org.kde.neochat", "SeenByDialog").createObject(root, {
|
||||
model: root.readMarkers
|
||||
}) as SeenByDialog;
|
||||
dialog.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compactBackgroundComponent: Rectangle {
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#include <Quotient/roommember.h>
|
||||
|
||||
#define MAXMARKERS 5
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
ReadMarkerModel::ReadMarkerModel(const QString &eventId, NeoChatRoom *room)
|
||||
@@ -85,13 +83,17 @@ QVariant ReadMarkerModel::data(const QModelIndex &index, int role) const
|
||||
return member.color();
|
||||
}
|
||||
|
||||
if (role == UserIdRole) {
|
||||
return member.id();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int ReadMarkerModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return std::min(int(m_markerIds.size()), MAXMARKERS);
|
||||
return m_markerIds.size();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> ReadMarkerModel::roleNames() const
|
||||
@@ -100,6 +102,7 @@ QHash<int, QByteArray> ReadMarkerModel::roleNames() const
|
||||
{DisplayNameRole, "displayName"},
|
||||
{AvatarUrlRole, "avatarUrl"},
|
||||
{ColorRole, "memberColor"},
|
||||
{UserIdRole, "userId"},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -122,17 +125,4 @@ QString ReadMarkerModel::readMarkersString()
|
||||
return readMarkersString;
|
||||
}
|
||||
|
||||
QString ReadMarkerModel::excessReadMarkersString()
|
||||
{
|
||||
if (m_room == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (m_markerIds.size() > MAXMARKERS) {
|
||||
return u"+ "_s + QString::number(m_markerIds.size() - MAXMARKERS);
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_readmarkermodel.cpp"
|
||||
|
||||
@@ -26,13 +26,6 @@ class ReadMarkerModel : public QAbstractListModel
|
||||
*/
|
||||
Q_PROPERTY(QString readMarkersString READ readMarkersString NOTIFY reactionUpdated)
|
||||
|
||||
/**
|
||||
* @brief Returns the number of excess user read markers for the event.
|
||||
*
|
||||
* This returns a string in the form "+ x" ready for use in the UI.
|
||||
*/
|
||||
Q_PROPERTY(QString excessReadMarkersString READ excessReadMarkersString NOTIFY reactionUpdated)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Defines the model roles.
|
||||
@@ -41,12 +34,12 @@ public:
|
||||
DisplayNameRole = Qt::DisplayRole, /**< The display name of the member in the room. */
|
||||
AvatarUrlRole, /**< The avatar for the member in the room. */
|
||||
ColorRole, /**< The color for the member. */
|
||||
UserIdRole, /** The user ID for the member. */
|
||||
};
|
||||
|
||||
explicit ReadMarkerModel(const QString &eventId, NeoChatRoom *room);
|
||||
|
||||
QString readMarkersString();
|
||||
QString excessReadMarkersString();
|
||||
|
||||
/**
|
||||
* @brief Get the given role value at the given index.
|
||||
|
||||
Reference in New Issue
Block a user