diff options
author | Malte E <97891689+maltee1@users.noreply.github.com> | 2023-02-01 00:59:49 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-31 16:59:49 +0000 |
commit | 5ed3bfc8f82e9123db4c198b6b9701df57c968f4 (patch) | |
tree | 9cb27ca2ed00830dba9d8adcc780d1b5296dd7cc /resources/qml | |
parent | Merge pull request #1319 from Decodetalkers/menuhideonwayland (diff) | |
download | nheko-5ed3bfc8f82e9123db4c198b6b9701df57c968f4.tar.xz |
add user search to invite dialog (#1253)
Diffstat (limited to 'resources/qml')
-rw-r--r-- | resources/qml/Root.qml | 10 | ||||
-rw-r--r-- | resources/qml/components/UserListRow.qml | 53 | ||||
-rw-r--r-- | resources/qml/dialogs/InviteDialog.qml | 211 |
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 } } - } } |