diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 6fd0bfaa..a5bc3a15 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -201,11 +201,15 @@ Pane {
}
function onOpenInviteUsersDialog(invitees) {
- var dialog = Qt.createComponent("qrc:/qml/dialogs/InviteDialog.qml").createObject(timelineRoot, {
+ var component = Qt.createComponent("qrc:/qml/dialogs/InviteDialog.qml")
+ var dialog = component.createObject(timelineRoot, {
"roomId": Rooms.currentRoom.roomId,
"plainRoomName": Rooms.currentRoom.plainRoomName,
"invitees": invitees
});
+ if (component.status != Component.Ready) {
+ console.log("Failed to create component: " + component.errorString());
+ }
dialog.show();
destroyOnClose(dialog);
}
diff --git a/resources/qml/components/UserListRow.qml b/resources/qml/components/UserListRow.qml
new file mode 100644
index 00000000..09360fd7
--- /dev/null
+++ b/resources/qml/components/UserListRow.qml
@@ -0,0 +1,52 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import ".."
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import im.nheko 1.0
+
+ItemDelegate {
+ property alias bgColor: background.color
+ property alias userid: avatar.userid
+ property alias displayName: avatar.displayName
+ property string avatarUrl
+ implicitHeight: layout.implicitHeight + Nheko.paddingSmall * 2
+ background: Rectangle {id: background}
+ GridLayout {
+ id: layout
+ anchors.centerIn: parent
+ width: parent.width - Nheko.paddingSmall * 2
+ rows: 2
+ columns: 2
+ rowSpacing: Nheko.paddingSmall
+ columnSpacing: Nheko.paddingMedium
+
+ Avatar {
+ id: avatar
+ Layout.rowSpan: 2
+ Layout.preferredWidth: Nheko.avatarSize
+ Layout.preferredHeight: Nheko.avatarSize
+ Layout.alignment: Qt.AlignLeft
+ url: avatarUrl.replace("mxc://", "image://MxcImage/")
+ enabled: false
+ }
+ Label {
+ Layout.fillWidth: true
+ text: displayName
+ color: TimelineManager.userColor(userid, Nheko.colors.window)
+ font.pointSize: fontMetrics.font.pointSize
+ }
+
+ Label {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignTop
+ text: userid
+ color: Nheko.colors.buttonText
+ font.pointSize: fontMetrics.font.pointSize * 0.9
+ }
+ }
+}
diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml
index 1f3a909a..37f0d09b 100644
--- a/resources/qml/dialogs/InviteDialog.qml
+++ b/resources/qml/dialogs/InviteDialog.qml
@@ -4,6 +4,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import ".."
+import "../components"
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
@@ -67,13 +68,13 @@ ApplicationWindow {
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
spacing: 4
+ visible: !inviteesList.visible
Repeater {
id: inviteesRepeater
model: invitees
delegate: ItemDelegate {
onClicked: invitees.removeUser(model.mxid)
id: inviteeButton
- visible: !inviteesList.visible
contentItem: Label {
anchors.centerIn: parent
id: inviteeUserid
@@ -92,7 +93,7 @@ ApplicationWindow {
}
Label {
- text: qsTr("User to invite")
+ text: qsTr("Search user")
Layout.fillWidth: true
color: Nheko.colors.text
}
@@ -145,51 +146,17 @@ ApplicationWindow {
}
RowLayout {
- ItemDelegate {
+ UserListRow {
visible: inviteeEntry.isValidMxid
id: del3
Layout.preferredWidth: inviteDialogRoot.width/2
Layout.alignment: Qt.AlignTop
- Layout.preferredHeight: layout3.implicitHeight + Nheko.paddingSmall * 2
- onClicked: addInvite(inviteeEntry.text, profile? profile.displayName : "", profile? profile.avatarUrl : "")
- background: Rectangle {
- color: del3.hovered ? Nheko.colors.dark : inviteDialogRoot.color
- clip: true
- }
- GridLayout {
- id: layout3
- anchors.centerIn: parent
- width: del3.width - Nheko.paddingSmall * 2
- rows: 2
- columns: 2
- rowSpacing: Nheko.paddingSmall
- columnSpacing: Nheko.paddingMedium
-
- Avatar {
- Layout.rowSpan: 2
- Layout.preferredWidth: Nheko.avatarSize
- Layout.preferredHeight: Nheko.avatarSize
- Layout.alignment: Qt.AlignLeft
- userid: inviteeEntry.text
- url: profile? profile.avatarUrl.replace("mxc://", "image://MxcImage/") : ""
- displayName: profile? profile.displayName : ""
- enabled: false
- }
- Label {
- Layout.fillWidth: true
- text: profile? profile.displayName : ""
- color: TimelineManager.userColor(inviteeEntry.text, Nheko.colors.window)
- font.pointSize: fontMetrics.font.pointSize
- }
-
- Label {
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- text: inviteeEntry.text
- color: Nheko.colors.buttonText
- font.pointSize: fontMetrics.font.pointSize * 0.9
- }
- }
+ Layout.preferredHeight: implicitHeight
+ displayName: profile? profile.displayName : ""
+ avatarUrl: profile? profile.avatarUrl : ""
+ userid: inviteeEntry.text
+ onClicked: addInvite(inviteeEntry.text, displayName, avatarUrl)
+ bgColor: del3.hovered ? Nheko.colors.dark : inviteDialogRoot.color
}
ListView {
visible: !inviteeEntry.isValidMxid
@@ -198,48 +165,15 @@ ApplicationWindow {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
- delegate: ItemDelegate {
+ delegate: UserListRow {
id: del2
width: ListView.view.width
- height: layout2.implicitHeight + Nheko.paddingSmall * 2
- onClicked: addInvite(model.userid, model.displayName, model.avatarUrl)
- background: Rectangle {
- color: del2.hovered ? Nheko.colors.dark : inviteDialogRoot.color
- }
- GridLayout {
- id: layout2
- anchors.centerIn: parent
- width: del2.width - Nheko.paddingSmall * 2
- rows: 2
- columns: 2
- rowSpacing: Nheko.paddingSmall
- columnSpacing: Nheko.paddingMedium
-
- Avatar {
- Layout.rowSpan: 2
- Layout.preferredWidth: Nheko.avatarSize
- Layout.preferredHeight: Nheko.avatarSize
- Layout.alignment: Qt.AlignLeft
- userid: model.userid
- url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
- displayName: model.displayName
- enabled: false
- }
- Label {
- Layout.fillWidth: true
- text: model.displayName
- color: TimelineManager.userColor(model.userid, Nheko.colors.window)
- font.pointSize: fontMetrics.font.pointSize
- }
-
- Label {
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- text: model.userid
- color: Nheko.colors.buttonText
- font.pointSize: fontMetrics.font.pointSize * 0.9
- }
- }
+ height: implicitHeight
+ displayName: model.displayName
+ userid: model.userid
+ avatarUrl: model.avatarUrl
+ onClicked: addInvite(userid, displayName, avatarUrl)
+ bgColor: del2.hovered ? Nheko.colors.dark : inviteDialogRoot.color
}
}
ListView {
@@ -251,57 +185,24 @@ ApplicationWindow {
clip: true
visible: inviteDialogRoot.width >= 500
- delegate: ItemDelegate {
+ delegate: UserListRow {
id: del
-
hoverEnabled: true
width: ListView.view.width
- height: layout.implicitHeight + Nheko.paddingSmall * 2
+ height: implicitHeight
onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
- background: Rectangle {
- color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
- }
- GridLayout {
- id: layout
- anchors.centerIn: parent
- width: del.width - Nheko.paddingSmall * 2
- rows: 2
- columns: 3
- rowSpacing: Nheko.paddingSmall
- columnSpacing: Nheko.paddingMedium
-
- Avatar {
- Layout.rowSpan: 2
- Layout.preferredWidth: Nheko.avatarSize
- Layout.preferredHeight: Nheko.avatarSize
- Layout.alignment: Qt.AlignLeft
- userid: model.mxid
- url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
- displayName: model.displayName
- enabled: false
- }
- Label {
- Layout.fillWidth: true
- text: model.displayName
- color: TimelineManager.userColor(model.mxid, Nheko.colors.window)
- font.pointSize: fontMetrics.font.pointSize
- }
-
- ImageButton {
- Layout.rowSpan: 2
- id: removeButton
- image: ":/icons/icons/ui/dismiss.svg"
- onClicked: invitees.removeUser(model.mxid)
- }
-
- Label {
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- text: model.mxid
- color: Nheko.colors.buttonText
- font.pointSize: fontMetrics.font.pointSize * 0.9
- }
-
+ userid: model.mxid
+ avatarUrl: model.avatarUrl
+ displayName: model.displayName
+ bgColor: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
+ ImageButton {
+ anchors.right: parent.right
+ anchors.rightMargin: Nheko.paddingSmall
+ anchors.top: parent.top
+ anchors.topMargin: Nheko.paddingSmall
+ id: removeButton
+ image: ":/icons/icons/ui/dismiss.svg"
+ onClicked: invitees.removeUser(model.mxid)
}
CursorShape {
diff --git a/resources/res.qrc b/resources/res.qrc
index e9320a1b..060ccbbe 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -132,6 +132,7 @@
qml/components/ReorderableListview.qml
qml/components/SpaceMenuLevel.qml
qml/components/TextButton.qml
+ qml/components/UserListRow.qml
qml/delegates/Encrypted.qml
qml/delegates/FileMessage.qml
qml/delegates/ImageMessage.qml
diff --git a/src/InviteesModel.cpp b/src/InviteesModel.cpp
index fe30e70a..528b2774 100644
--- a/src/InviteesModel.cpp
+++ b/src/InviteesModel.cpp
@@ -88,7 +88,9 @@ Invitee::Invitee(QString mxid, QString displayName, QString avatarUrl, QObject *
: QObject{parent}
, mxid_{std::move(mxid)}
{
- if (displayName == "" || avatarUrl == "") {
+ // checking for empty avatarUrl will cause profiles to be loaded that don't have an avatar
+ // to needlessly be loaded. Can we make sure we either provide both or none?
+ if (displayName == "") {
http::client()->get_profile(
mxid_.toStdString(),
[this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {