user details dialog fixes

This commit is contained in:
Tobias Fella
2024-06-28 15:52:26 +02:00
parent e918db2cc1
commit 08df0ebbea
6 changed files with 79 additions and 52 deletions

View File

@@ -114,8 +114,8 @@ Kirigami.ApplicationWindow {
}).open();
}
function onShowUserDetail(user) {
root.showUserDetail(user);
function onShowUserDetail(user, room) {
root.showUserDetail(user, room);
}
function goToEvent(event) {
@@ -351,9 +351,9 @@ Kirigami.ApplicationWindow {
dialog.closeDialog()
})
}
function showUserDetail(user) {
function showUserDetail(user, room) {
Qt.createComponent("org.kde.neochat", "UserDetailDialog").createObject(root.QQC2.ApplicationWindow.window, {
room: RoomManager.currentRoom ? RoomManager.currentRoom : null,
room: room,
user: user,
connection: root.connection
}).open();

View File

@@ -19,21 +19,8 @@ Kirigami.Dialog {
// This dialog is sometimes used outside the context of a room, e.g., when scanning a user's QR code.
// Make sure that code is prepared to deal with this property being null
property NeoChatRoom room
/**
* @brief The user's profile object.
*
* Required to interact with the profile and perform action like ignoring.
*/
property var user
/**
* @brief The RoomMember object for the user in the current room.
*
* Required to visualise the user.
*/
property var member: root.room.member(user.id)
property NeoChatConnection connection
leftPadding: 0
@@ -61,9 +48,9 @@ Kirigami.Dialog {
Layout.preferredWidth: Kirigami.Units.iconSizes.huge
Layout.preferredHeight: Kirigami.Units.iconSizes.huge
name: root.member.displayName
source: root.member.avatarUrl
color: root.member.color
name: root.room ? root.room.member(root.user.id).displayName : root.user.displayName
source: root.room ? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
color: root.room ? root.room.member(root.user.id).color : QmlUtils.getUserColor(root.user.hueF)
}
ColumnLayout {
@@ -76,13 +63,13 @@ Kirigami.Dialog {
elide: Text.ElideRight
wrapMode: Text.NoWrap
text: root.user.displayName
text: root.room ? root.room.member(root.user.id).displayName : root.user.displayName
textFormat: Text.PlainText
}
Kirigami.SelectableLabel {
textFormat: TextEdit.PlainText
text: root.member.id
text: root.user.id
}
}
QQC2.AbstractButton {
@@ -91,16 +78,16 @@ Kirigami.Dialog {
contentItem: Barcode {
id: barcode
barcodeType: Barcode.QRCode
content: "https://matrix.to/#/" + root.member.id
content: "https://matrix.to/#/" + root.user.id
}
onClicked: {
let map = qrMaximizeComponent.createObject(parent, {
text: barcode.content,
title: root.member.displayName,
subtitle: root.member.id,
avatarColor: root.member.color,
avatarSource: root.member.avatarUrl,
title: root.room ? root.room.member(root.user.id).displayName : root.user.displayName,
subtitle: root.user.id,
avatarColor: root.room?.member(root.user.id).color,
avatarSource: root.room? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl
});
root.close();
map.open();
@@ -117,46 +104,46 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: !root.member.isLocalMember
visible: root.user.id !== root.connection.localUserId && !!root.user
action: Kirigami.Action {
text: !!root.user && root.connection.isIgnored(root.user) ? i18n("Unignore this user") : i18n("Ignore this user")
text: !!root.user && root.connection.isIgnored(root.user.id) ? i18n("Unignore this user") : i18n("Ignore this user")
icon.name: "im-invisible-user"
onTriggered: {
root.close();
root.connection.isIgnored(root.user) ? root.connection.removeFromIgnoredUsers(root.user) : root.connection.addToIgnoredUsers(root.user);
root.connection.isIgnored(root.user.id) ? root.connection.removeFromIgnoredUsers(root.user.id) : root.connection.addToIgnoredUsers(root.user.id);
}
}
}
FormCard.FormButtonDelegate {
visible: root.room && !root.member.isLocalMember && room.canSendState("kick") && room.containsUser(root.member.id) && room.getUserPowerLevel(root.member.id) < room.getUserPowerLevel(root.room.localMember.id)
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("kick") && room.containsUser(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.connection.localUserId)
action: Kirigami.Action {
text: i18n("Kick this user")
icon.name: "im-kick-user"
onTriggered: {
root.room.kickMember(root.member.id);
root.room.kickMember(root.user.id);
root.close();
}
}
}
FormCard.FormButtonDelegate {
visible: root.room && !root.member.isLocalMember && room.canSendState("invite") && !room.containsUser(root.member.id)
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("invite") && !room.containsUser(root.user.id)
action: Kirigami.Action {
enabled: root.room && !root.room.isUserBanned(root.member.id)
enabled: root.room && !root.room.isUserBanned(root.user.id)
text: i18n("Invite this user")
icon.name: "list-add-user"
onTriggered: {
root.room.inviteToRoom(root.member.id);
root.room.inviteToRoom(root.user.id);
root.close();
}
}
}
FormCard.FormButtonDelegate {
visible: root.room && !root.member.isLocalMember && room.canSendState("ban") && !room.isUserBanned(root.member.id) && room.getUserPowerLevel(root.member.id) < room.getUserPowerLevel(root.room.localMember.id)
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && !room.isUserBanned(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.connection.localUserId)
action: Kirigami.Action {
text: i18n("Ban this user")
@@ -165,7 +152,7 @@ Kirigami.Dialog {
onTriggered: {
(root.QQC2.ApplicationWindow.window as Kirigami.ApplicationWindow).pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'BanSheet'), {
room: root.room,
userId: root.member.id
userId: root.user.id
}, {
title: i18nc("@title", "Ban User"),
width: Kirigami.Units.gridUnit * 25
@@ -176,14 +163,14 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && !root.member.isLocalMember && room.canSendState("ban") && room.isUserBanned(root.member.id)
visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && room.isUserBanned(root.user.id)
action: Kirigami.Action {
text: i18n("Unban this user")
icon.name: "im-irc"
icon.color: Kirigami.Theme.negativeTextColor
onTriggered: {
root.room.unban(root.member.id);
root.room.unban(root.user.id);
root.close();
}
}
@@ -197,8 +184,8 @@ Kirigami.Dialog {
onTriggered: {
let dialog = powerLevelDialog.createObject(this, {
room: root.room,
userId: root.member.id,
powerLevel: root.room.getUserPowerLevel(root.member.id)
userId: root.user.id,
powerLevel: root.room.getUserPowerLevel(root.user.id)
});
dialog.open();
root.close();
@@ -214,7 +201,7 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: root.room && (root.member.isLocalUser || room.canSendState("redact"))
visible: root.room && (root.user.id === root.connection.localUserId || room.canSendState("redact"))
action: Kirigami.Action {
text: i18n("Remove recent messages by this user")
@@ -223,7 +210,7 @@ Kirigami.Dialog {
onTriggered: {
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RemoveSheet'), {
room: root.room,
userId: root.member.id
userId: root.user.id
}, {
title: i18nc("@title", "Remove Messages"),
width: Kirigami.Units.gridUnit * 25
@@ -234,12 +221,12 @@ Kirigami.Dialog {
}
FormCard.FormButtonDelegate {
visible: !root.member.isLocalMember
visible: root.user.id !== root.connection.localUserId
action: Kirigami.Action {
text: root.connection.directChatExists(root.user.object) ? i18nc("%1 is the name of the user.", "Chat with %1", root.user.escapedDisplayName) : i18n("Invite to private chat")
text: root.connection.directChatExists(root.user) ? i18nc("%1 is the name of the user.", "Chat with %1", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName)) : i18n("Invite to private chat")
icon.name: "document-send"
onTriggered: {
root.room.connection.openOrCreateDirectChat(root.user);
root.connection.openOrCreateDirectChat(root.user.id);
root.close();
}
}
@@ -250,7 +237,7 @@ Kirigami.Dialog {
text: i18n("Copy link")
icon.name: "username-copy"
onTriggered: {
Clipboard.saveText("https://matrix.to/#/" + root.member.id);
Clipboard.saveText("https://matrix.to/#/" + root.user.id);
}
}
}

View File

@@ -146,8 +146,10 @@ void RoomManager::resolveResource(const QString &idOrUri, const QString &action)
if ((uri.type() == Uri::RoomAlias || uri.type() == Uri::RoomId) && action != "no_join"_ls) {
Q_EMIT askJoinRoom(uri.primaryId());
}
} else { // Invalid cases should have been eliminated earlier
Q_ASSERT(result == Quotient::UriResolved);
} else {
if (result != Quotient::UriResolved) {
return;
}
if (uri.type() == Uri::RoomAlias || uri.type() == Uri::RoomId) {
connect(
@@ -255,9 +257,9 @@ void RoomManager::openRoomForActiveConnection()
UriResolveResult RoomManager::visitUser(User *user, const QString &action)
{
if (action == "mention"_ls || action.isEmpty()) {
if (action == "mention"_ls || action == "qr"_ls || action.isEmpty()) {
user->load();
Q_EMIT showUserDetail(user);
Q_EMIT showUserDetail(user, action == "qr"_ls ? nullptr : currentRoom());
} else if (action == "_interactive"_ls) {
user->requestDirectChat();
} else if (action == "chat"_ls) {

View File

@@ -261,7 +261,7 @@ Q_SIGNALS:
* Ask current room to open the user's details for the give user.
* This assumes the user is loaded.
*/
void showUserDetail(const Quotient::User *user);
void showUserDetail(const Quotient::User *user, const NeoChatRoom *room);
/**
* @brief Request a media item is shown maximized.

View File

@@ -7,9 +7,23 @@
#include <QJsonDocument>
using namespace Quotient;
bool QmlUtils::isValidJson(const QByteArray &json)
{
return !QJsonDocument::fromJson(json).isNull();
}
QString QmlUtils::escapeString(const QString &string)
{
return string.toHtmlEscaped();
}
QColor QmlUtils::getUserColor(qreal hueF)
{
const auto lightness = static_cast<QGuiApplication *>(QGuiApplication::instance())->palette().color(QPalette::Active, QPalette::Window).lightnessF();
// https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal
return QColor::fromHslF(hueF, 1, -0.7 * lightness + 0.9, 1);
}
#include "moc_utils.cpp"

View File

@@ -3,9 +3,14 @@
#pragma once
#include <QColor>
#include <QGuiApplication>
#include <QPalette>
#include <QQmlEngine>
#include <QRegularExpression>
#include <Quotient/user.h>
class QmlUtils : public QObject
{
Q_OBJECT
@@ -26,11 +31,30 @@ public:
}
Q_INVOKABLE bool isValidJson(const QByteArray &json);
Q_INVOKABLE QString escapeString(const QString &string);
Q_INVOKABLE QColor getUserColor(qreal hueF);
private:
QmlUtils() = default;
};
namespace Utils
{
/**
* @brief Get a color for a user from a hueF value.
*
* The lightness of the color will be modified depending on the current palette in
* order to maintain contrast.
*/
inline QColor getUserColor(qreal hueF)
{
const auto lightness = static_cast<QGuiApplication *>(QGuiApplication::instance())->palette().color(QPalette::Active, QPalette::Window).lightnessF();
// https://github.com/quotient-im/libQuotient/wiki/User-color-coding-standard-draft-proposal
return QColor::fromHslF(hueF, 1, -0.7 * lightness + 0.9, 1);
}
}
namespace TextRegex
{
static const QRegularExpression endTagType{QStringLiteral("(>| )")};