summary refs log tree commit diff
path: root/resources/qml
diff options
context:
space:
mode:
authorMalte E <97891689+maltee1@users.noreply.github.com>2023-02-01 00:59:49 +0800
committerGitHub <noreply@github.com>2023-01-31 16:59:49 +0000
commit5ed3bfc8f82e9123db4c198b6b9701df57c968f4 (patch)
tree9cb27ca2ed00830dba9d8adcc780d1b5296dd7cc /resources/qml
parentMerge pull request #1319 from Decodetalkers/menuhideonwayland (diff)
downloadnheko-5ed3bfc8f82e9123db4c198b6b9701df57c968f4.tar.xz
add user search to invite dialog (#1253)
Diffstat (limited to 'resources/qml')
-rw-r--r--resources/qml/Root.qml10
-rw-r--r--resources/qml/components/UserListRow.qml53
-rw-r--r--resources/qml/dialogs/InviteDialog.qml211
3 files changed, 199 insertions, 75 deletions
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index 5f7d7229..f60ebac1 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -34,6 +34,10 @@ Pane {
         id: publicRooms
     }
 
+    UserDirectoryModel {
+        id: userDirectory
+    }
+
     //Timer {
     //    onTriggered: gc()
     //    interval: 1000
@@ -198,11 +202,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..8cbbd195
--- /dev/null
+++ b/resources/qml/components/UserListRow.qml
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+// SPDX-FileCopyrightText: 2022 Nheko Contributors
+// SPDX-FileCopyrightText: 2023 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 33fd32c4..20699a65 100644
--- a/resources/qml/dialogs/InviteDialog.qml
+++ b/resources/qml/dialogs/InviteDialog.qml
@@ -5,6 +5,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
@@ -16,17 +17,25 @@ ApplicationWindow {
     property string roomId
     property string plainRoomName
     property InviteesModel invitees
+    property var friendsCompleter
+    property var profile
+    minimumWidth: 300
 
-    function addInvite() {
-        if (inviteeEntry.isValidMxid) {
-            invitees.addUser(inviteeEntry.text);
-            inviteeEntry.clear();
-        }
+    Component.onCompleted: {
+        friendsCompleter = TimelineManager.completerFor("user", "friends")
+        width = 600
+    }
+
+    function addInvite(mxid, displayName, avatarUrl) {
+        if (mxid.match("@.+?:.{3,}")) {
+            invitees.addUser(mxid, displayName, avatarUrl);
+        } else
+            console.log("invalid mxid: " + mxid)
     }
 
     function cleanUpAndClose() {
         if (inviteeEntry.isValidMxid)
-            addInvite();
+            addInvite(inviteeEntry.text, "", "");
 
         invitees.accept();
         close();
@@ -53,13 +62,40 @@ ApplicationWindow {
         anchors.fill: parent
         anchors.margins: Nheko.paddingMedium
         spacing: Nheko.paddingMedium
+        Flow {
+            layoutDirection: Qt.LeftToRight
+            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
+                    contentItem: Label {
+                        anchors.centerIn: parent
+                        id: inviteeUserid
+                        text: model.displayName != "" ? model.displayName : model.userid
+                        color: inviteeButton.hovered ? Nheko.colors.highlightedText: Nheko.colors.text
+                        maximumLineCount: 1
+                    }
+                    background: Rectangle {
+                        border.color: Nheko.colors.text
+                        color: inviteeButton.hovered ? Nheko.colors.highlight : Nheko.colors.window
+                        border.width: 1
+                        radius: inviteeButton.height / 2
+                    }
+                }
+            }
+        }
 
         Label {
-            text: qsTr("User ID to invite")
+            text: qsTr("Search user")
             Layout.fillWidth: true
             color: Nheko.colors.text
         }
-
         RowLayout {
             spacing: Nheko.paddingMedium
 
@@ -72,9 +108,14 @@ ApplicationWindow {
                 placeholderText: qsTr("@joe:matrix.org", "Example user id. The name 'joe' can be localized however you want.")
                 Layout.fillWidth: true
                 onAccepted: {
-                    if (isValidMxid)
-                        addInvite();
-
+                    if (isValidMxid) {
+                        addInvite(text, "", "");
+                        clear()
+                    }
+                    else if (userSearch.count > 0) {
+                        addInvite(userSearch.itemAtIndex(0).userid, userSearch.itemAtIndex(0).displayName, userSearch.itemAtIndex(0).avatarUrl)
+                        clear()
+                    }
                 }
                 Component.onCompleted: forceActiveFocus()
                 Keys.onShortcutOverride: event.accepted = ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter) && (event.modifiers & Qt.ControlModifier))
@@ -83,85 +124,107 @@ ApplicationWindow {
                         cleanUpAndClose();
 
                 }
+                onTextChanged: {
+                    searchTimer.restart()
+                    if(isValidMxid) {
+                        profile = TimelineManager.getGlobalUserProfile(text);
+                    } else
+                        profile = null;
+                }
+                Timer {
+                    id: searchTimer
+
+                    interval: 350
+                    onTriggered: {
+                        userSearch.model.setSearchString(parent.text)
+                    }
+                }
             }
 
-            Button {
-                text: qsTr("Add")
-                enabled: inviteeEntry.isValidMxid
-                onClicked: addInvite()
+            ToggleButton {
+                id: searchOnServer
+                checked: false
+                onClicked: userSearch.model.setSearchString(inviteeEntry.text)
+            }
+            MatrixText {
+                text: qsTr("Search on Server")
             }
 
         }
-
-        ListView {
-            id: inviteesList
-
-            Layout.fillWidth: true
-            Layout.fillHeight: true
-            model: invitees
-
-            delegate: ItemDelegate {
-                id: del
-
-                hoverEnabled: true
-                width: ListView.view.width
-                height: layout.implicitHeight + Nheko.paddingSmall * 2
-                onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
-                background: Rectangle {
-                    color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
+        RowLayout {
+            UserListRow {
+                visible: inviteeEntry.isValidMxid
+                id: del3
+                Layout.preferredWidth: inviteDialogRoot.width/2
+                Layout.alignment: Qt.AlignTop
+                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
+                id: userSearch
+                model: searchOnServer.checked? userDirectory : friendsCompleter
+                Layout.fillWidth: true
+                Layout.fillHeight: true
+                clip: true
+                delegate: UserListRow {
+                    id: del2
+                    width: ListView.view.width
+                    height: implicitHeight
+                    displayName: model.displayName
+                    userid: model.userid
+                    avatarUrl: model.avatarUrl
+                    onClicked: addInvite(userid, displayName, avatarUrl)
+                    bgColor: del2.hovered ? Nheko.colors.dark : inviteDialogRoot.color
                 }
+            }
+            Rectangle {
+                Layout.fillHeight: true
+                visible: inviteesList.visible
+                width: 1
+                color: Nheko.theme.separator
+            }
+            ListView {
+                id: inviteesList
 
-                RowLayout {
-                    id: layout
-
-                    spacing: Nheko.paddingMedium
-                    anchors.centerIn: parent
-                    width: del.width - Nheko.paddingSmall * 2
-
-                    Avatar {
-                        width: Nheko.avatarSize
-                        height: Nheko.avatarSize
-                        userid: model.mxid
-                        url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
-                        displayName: model.displayName
-                        enabled: false
-                    }
-
-                    ColumnLayout {
-                        spacing: Nheko.paddingSmall
-
-                        Label {
-                            text: model.displayName
-                            color: TimelineManager.userColor(model ? model.mxid : "", del.background.color)
-                            font.pointSize: fontMetrics.font.pointSize
-                        }
-
-                        Label {
-                            text: model.mxid
-                            color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText
-                            font.pointSize: fontMetrics.font.pointSize * 0.9
-                        }
-
-                    }
-
-                    Item {
-                        Layout.fillWidth: true
-                    }
-
+                Layout.fillWidth: true
+                Layout.fillHeight: true
+                model: invitees
+                clip: true
+                visible: inviteDialogRoot.width >= 500
+
+                delegate: UserListRow {
+                    id: del
+                    hoverEnabled: true
+                    width: ListView.view.width
+                    height: implicitHeight
+                    onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
+                    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 {
+                        anchors.fill: parent
+                        cursorShape: Qt.PointingHandCursor
+                    }
 
-                CursorShape {
-                    anchors.fill: parent
-                    cursorShape: Qt.PointingHandCursor
                 }
 
             }
-
         }
 
     }