Add user directory.
This commit is contained in:
@@ -144,6 +144,7 @@ set(spectral_SRCS
|
|||||||
src/trayicon.h
|
src/trayicon.h
|
||||||
src/userlistmodel.h
|
src/userlistmodel.h
|
||||||
src/publicroomlistmodel.h
|
src/publicroomlistmodel.h
|
||||||
|
src/userdirectorylistmodel.h
|
||||||
src/utils.h
|
src/utils.h
|
||||||
src/accountlistmodel.cpp
|
src/accountlistmodel.cpp
|
||||||
src/controller.cpp
|
src/controller.cpp
|
||||||
@@ -157,6 +158,7 @@ set(spectral_SRCS
|
|||||||
src/trayicon.cpp
|
src/trayicon.cpp
|
||||||
src/userlistmodel.cpp
|
src/userlistmodel.cpp
|
||||||
src/publicroomlistmodel.cpp
|
src/publicroomlistmodel.cpp
|
||||||
|
src/userdirectorylistmodel.cpp
|
||||||
src/utils.cpp
|
src/utils.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -118,6 +118,36 @@ Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
MaterialIcon {
|
||||||
|
Layout.preferredWidth: 48
|
||||||
|
Layout.preferredHeight: 48
|
||||||
|
|
||||||
|
color: MPalette.foreground
|
||||||
|
icon: "\ue7ff"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
color: MPalette.foreground
|
||||||
|
text: "Start a Chat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RippleEffect {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
onPrimaryClicked: {
|
||||||
|
startChatDialog.createObject(ApplicationWindow.overlay, {"controller": spectralController, "connection": spectralController.connection}).open()
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Control {
|
Control {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
|
|||||||
@@ -3,26 +3,180 @@ import QtQuick.Controls 2.12
|
|||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.12
|
||||||
|
|
||||||
import Spectral.Component 2.0
|
import Spectral.Component 2.0
|
||||||
|
import Spectral.Effect 2.0
|
||||||
|
import Spectral.Setting 0.1
|
||||||
|
|
||||||
|
import Spectral 0.1
|
||||||
|
|
||||||
Dialog {
|
Dialog {
|
||||||
|
property var controller
|
||||||
property var room
|
property var room
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: 360
|
width: 480
|
||||||
|
height: window.height - 100
|
||||||
|
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
title: "Invite User"
|
title: "Invite a User"
|
||||||
|
|
||||||
modal: true
|
contentItem: ColumnLayout {
|
||||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
spacing: 0
|
||||||
|
|
||||||
contentItem: AutoTextField {
|
RowLayout {
|
||||||
id: inviteUserDialogTextField
|
Layout.fillWidth: true
|
||||||
placeholderText: "User ID"
|
|
||||||
|
AutoTextField {
|
||||||
|
property bool isUserID: text.match(/@(.+):(.+)/g)
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
id: identifierField
|
||||||
|
|
||||||
|
placeholderText: "Find a user..."
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
userDictListModel.search()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
visible: identifierField.isUserID
|
||||||
|
|
||||||
|
text: "Add"
|
||||||
|
highlighted: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
room.inviteToRoom(identifierField.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoListView {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
id: userDictListView
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
model: UserDirectoryListModel {
|
||||||
|
id: userDictListModel
|
||||||
|
|
||||||
|
connection: root.room.connection
|
||||||
|
keyword: identifierField.text
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Control {
|
||||||
|
property bool inRoom: room && room.containsUser(userID)
|
||||||
|
|
||||||
|
width: userDictListView.width
|
||||||
|
height: 48
|
||||||
|
|
||||||
|
id: delegate
|
||||||
|
|
||||||
|
padding: 8
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
source: avatar
|
||||||
|
hint: name
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
text: name
|
||||||
|
color: MPalette.foreground
|
||||||
|
font.pixelSize: 13
|
||||||
|
textFormat: Text.PlainText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
text: userID
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 10
|
||||||
|
textFormat: Text.PlainText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
|
||||||
|
visible: inRoom
|
||||||
|
|
||||||
|
contentItem: MaterialIcon {
|
||||||
|
icon: "\ue89e"
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
background: RippleEffect {
|
||||||
|
circular: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
|
||||||
|
visible: !inRoom
|
||||||
|
|
||||||
|
contentItem: MaterialIcon {
|
||||||
|
icon: "\ue7fe"
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
background: RippleEffect {
|
||||||
|
circular: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
room.inviteToRoom(userID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
visible: userDictListView.count < 1
|
||||||
|
|
||||||
|
text: "No users available"
|
||||||
|
color: MPalette.foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAccepted: room.inviteToRoom(inviteUserDialogTextField.text)
|
|
||||||
|
|
||||||
onClosed: destroy()
|
onClosed: destroy()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ Dialog {
|
|||||||
if (identifierField.isJoined) {
|
if (identifierField.isJoined) {
|
||||||
roomListForm.joinRoom(identifierField.room)
|
roomListForm.joinRoom(identifierField.room)
|
||||||
} else {
|
} else {
|
||||||
spectralController.joinRoom(connection, identifierField.text)
|
controller.joinRoom(connection, identifierField.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,7 +248,7 @@ Dialog {
|
|||||||
circular: true
|
circular: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
spectralController.joinRoom(connection, roomID)
|
controller.joinRoom(connection, roomID)
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
182
imports/Spectral/Dialog/StartChatDialog.qml
Normal file
182
imports/Spectral/Dialog/StartChatDialog.qml
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Controls 2.12
|
||||||
|
import QtQuick.Layouts 1.12
|
||||||
|
|
||||||
|
import Spectral.Component 2.0
|
||||||
|
import Spectral.Effect 2.0
|
||||||
|
import Spectral.Setting 0.1
|
||||||
|
|
||||||
|
import Spectral 0.1
|
||||||
|
|
||||||
|
Dialog {
|
||||||
|
property var controller
|
||||||
|
property var connection
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: 480
|
||||||
|
height: window.height - 100
|
||||||
|
|
||||||
|
id: root
|
||||||
|
|
||||||
|
title: "Start a Chat"
|
||||||
|
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
AutoTextField {
|
||||||
|
property bool isUserID: text.match(/@(.+):(.+)/g)
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
id: identifierField
|
||||||
|
|
||||||
|
placeholderText: "Find a user..."
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
userDictListModel.search()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
visible: identifierField.isUserID
|
||||||
|
|
||||||
|
text: "Chat"
|
||||||
|
highlighted: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
controller.createDirectChat(connection, identifierField.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoListView {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
id: userDictListView
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
model: UserDirectoryListModel {
|
||||||
|
id: userDictListModel
|
||||||
|
|
||||||
|
connection: root.connection
|
||||||
|
keyword: identifierField.text
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Control {
|
||||||
|
width: userDictListView.width
|
||||||
|
height: 48
|
||||||
|
|
||||||
|
padding: 8
|
||||||
|
|
||||||
|
contentItem: RowLayout {
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
source: avatar
|
||||||
|
hint: name
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
text: name
|
||||||
|
color: MPalette.foreground
|
||||||
|
font.pixelSize: 13
|
||||||
|
textFormat: Text.PlainText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
text: userID
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 10
|
||||||
|
textFormat: Text.PlainText
|
||||||
|
elide: Text.ElideRight
|
||||||
|
wrapMode: Text.NoWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
|
||||||
|
visible: directChats != null
|
||||||
|
|
||||||
|
contentItem: MaterialIcon {
|
||||||
|
icon: "\ue89e"
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
background: RippleEffect {
|
||||||
|
circular: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
roomListForm.joinRoom(connection.room(directChats[0]))
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control {
|
||||||
|
Layout.preferredWidth: 32
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
|
||||||
|
contentItem: MaterialIcon {
|
||||||
|
icon: "\ue7f0"
|
||||||
|
color: MPalette.lighter
|
||||||
|
font.pixelSize: 20
|
||||||
|
}
|
||||||
|
|
||||||
|
background: RippleEffect {
|
||||||
|
circular: true
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
controller.createDirectChat(connection, userID)
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
visible: userDictListView.count < 1
|
||||||
|
|
||||||
|
text: "No users available"
|
||||||
|
color: MPalette.foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClosed: destroy()
|
||||||
|
}
|
||||||
@@ -12,3 +12,4 @@ AccountDetailDialog 2.0 AccountDetailDialog.qml
|
|||||||
OpenFileDialog 2.0 OpenFileDialog.qml
|
OpenFileDialog 2.0 OpenFileDialog.qml
|
||||||
OpenFolderDialog 2.0 OpenFolderDialog.qml
|
OpenFolderDialog 2.0 OpenFolderDialog.qml
|
||||||
ImageClipboardDialog 2.0 ImageClipboardDialog.qml
|
ImageClipboardDialog 2.0 ImageClipboardDialog.qml
|
||||||
|
StartChatDialog 2.0 StartChatDialog.qml
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ Drawer {
|
|||||||
color: MPalette.lighter
|
color: MPalette.lighter
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: inviteUserDialog.createObject(ApplicationWindow.overlay, {"room": room}).open()
|
onClicked: inviteUserDialog.createObject(ApplicationWindow.overlay, {"controller": spectralController, "room": room}).open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +249,12 @@ Drawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onRoomChanged: {
|
||||||
|
if (room == null) {
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: roomSettingDialog
|
id: roomSettingDialog
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,12 @@ ApplicationWindow {
|
|||||||
JoinRoomDialog {}
|
JoinRoomDialog {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: startChatDialog
|
||||||
|
|
||||||
|
StartChatDialog {}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: createRoomDialog
|
id: createRoomDialog
|
||||||
|
|
||||||
|
|||||||
1
res.qrc
1
res.qrc
@@ -58,5 +58,6 @@
|
|||||||
<file>imports/Spectral/Component/AutoRectangle.qml</file>
|
<file>imports/Spectral/Component/AutoRectangle.qml</file>
|
||||||
<file>imports/Spectral/Component/Timeline/ReactionDelegate.qml</file>
|
<file>imports/Spectral/Component/Timeline/ReactionDelegate.qml</file>
|
||||||
<file>imports/Spectral/Component/Timeline/AudioDelegate.qml</file>
|
<file>imports/Spectral/Component/Timeline/AudioDelegate.qml</file>
|
||||||
|
<file>imports/Spectral/Dialog/StartChatDialog.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "spectralroom.h"
|
#include "spectralroom.h"
|
||||||
#include "spectraluser.h"
|
#include "spectraluser.h"
|
||||||
#include "trayicon.h"
|
#include "trayicon.h"
|
||||||
|
#include "userdirectorylistmodel.h"
|
||||||
#include "userlistmodel.h"
|
#include "userlistmodel.h"
|
||||||
|
|
||||||
using namespace Quotient;
|
using namespace Quotient;
|
||||||
@@ -42,6 +43,8 @@ int main(int argc, char* argv[]) {
|
|||||||
qmlRegisterType<UserListModel>("Spectral", 0, 1, "UserListModel");
|
qmlRegisterType<UserListModel>("Spectral", 0, 1, "UserListModel");
|
||||||
qmlRegisterType<MessageEventModel>("Spectral", 0, 1, "MessageEventModel");
|
qmlRegisterType<MessageEventModel>("Spectral", 0, 1, "MessageEventModel");
|
||||||
qmlRegisterType<PublicRoomListModel>("Spectral", 0, 1, "PublicRoomListModel");
|
qmlRegisterType<PublicRoomListModel>("Spectral", 0, 1, "PublicRoomListModel");
|
||||||
|
qmlRegisterType<UserDirectoryListModel>("Spectral", 0, 1,
|
||||||
|
"UserDirectoryListModel");
|
||||||
qmlRegisterType<EmojiModel>("Spectral", 0, 1, "EmojiModel");
|
qmlRegisterType<EmojiModel>("Spectral", 0, 1, "EmojiModel");
|
||||||
qmlRegisterType<NotificationsManager>("Spectral", 0, 1,
|
qmlRegisterType<NotificationsManager>("Spectral", 0, 1,
|
||||||
"NotificationsManager");
|
"NotificationsManager");
|
||||||
|
|||||||
@@ -573,3 +573,12 @@ void SpectralRoom::toggleReaction(const QString& eventId,
|
|||||||
postReaction(eventId, reaction);
|
postReaction(eventId, reaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpectralRoom::containsUser(QString userID) const {
|
||||||
|
auto u = Room::user(userID);
|
||||||
|
|
||||||
|
if (!u)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return Room::memberJoinState(u) != JoinState::Leave;
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ class SpectralRoom : public Room {
|
|||||||
Qt::TextFormat format = Qt::PlainText,
|
Qt::TextFormat format = Qt::PlainText,
|
||||||
bool removeReply = true) const;
|
bool removeReply = true) const;
|
||||||
|
|
||||||
|
Q_INVOKABLE bool containsUser(QString userID) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_cachedInput;
|
QString m_cachedInput;
|
||||||
QSet<const Quotient::RoomEvent*> highlights;
|
QSet<const Quotient::RoomEvent*> highlights;
|
||||||
|
|||||||
156
src/userdirectorylistmodel.cpp
Normal file
156
src/userdirectorylistmodel.cpp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#include "userdirectorylistmodel.h"
|
||||||
|
|
||||||
|
UserDirectoryListModel::UserDirectoryListModel(QObject* parent)
|
||||||
|
: QAbstractListModel(parent) {}
|
||||||
|
|
||||||
|
void UserDirectoryListModel::setConnection(Connection* conn) {
|
||||||
|
if (m_connection == conn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
m_limited = false;
|
||||||
|
attempted = false;
|
||||||
|
users.clear();
|
||||||
|
|
||||||
|
if (m_connection) {
|
||||||
|
m_connection->disconnect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
m_connection = conn;
|
||||||
|
|
||||||
|
if (job) {
|
||||||
|
job->abandon();
|
||||||
|
job = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit connectionChanged();
|
||||||
|
emit limitedChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserDirectoryListModel::setKeyword(const QString& value) {
|
||||||
|
if (m_keyword == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_keyword = value;
|
||||||
|
|
||||||
|
m_limited = false;
|
||||||
|
attempted = false;
|
||||||
|
|
||||||
|
if (job) {
|
||||||
|
job->abandon();
|
||||||
|
job = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit keywordChanged();
|
||||||
|
emit limitedChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserDirectoryListModel::search(int count) {
|
||||||
|
if (count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (job) {
|
||||||
|
qDebug() << "UserDirectoryListModel: Other jobs running, ignore";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attempted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
job = m_connection->callApi<SearchUserDirectoryJob>(m_keyword, count);
|
||||||
|
|
||||||
|
connect(job, &BaseJob::finished, this, [=] {
|
||||||
|
attempted = true;
|
||||||
|
|
||||||
|
if (job->status() == BaseJob::Success) {
|
||||||
|
auto users = job->results();
|
||||||
|
|
||||||
|
this->beginResetModel();
|
||||||
|
|
||||||
|
this->users = users;
|
||||||
|
this->m_limited = job->limited();
|
||||||
|
|
||||||
|
this->endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->job = nullptr;
|
||||||
|
|
||||||
|
emit limitedChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant UserDirectoryListModel::data(const QModelIndex& index,
|
||||||
|
int role) const {
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (index.row() >= users.count()) {
|
||||||
|
qDebug() << "UserDirectoryListModel, something's wrong: index.row() >= "
|
||||||
|
"users.count()";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto user = users.at(index.row());
|
||||||
|
if (role == NameRole) {
|
||||||
|
auto displayName = user.displayName;
|
||||||
|
if (!displayName.isEmpty()) {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
displayName = user.userId;
|
||||||
|
if (!displayName.isEmpty()) {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown User";
|
||||||
|
}
|
||||||
|
if (role == AvatarRole) {
|
||||||
|
auto avatarUrl = user.avatarUrl;
|
||||||
|
|
||||||
|
if (avatarUrl.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return avatarUrl.remove(0, 6);
|
||||||
|
}
|
||||||
|
if (role == UserIDRole) {
|
||||||
|
return user.userId;
|
||||||
|
}
|
||||||
|
if (role == DirectChatsRole) {
|
||||||
|
if (!m_connection)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto userObj = m_connection->user(user.userId);
|
||||||
|
auto directChats = m_connection->directChats();
|
||||||
|
|
||||||
|
if (userObj && directChats.contains(userObj)) {
|
||||||
|
auto directChatsForUser = directChats.values(userObj);
|
||||||
|
if (!directChatsForUser.isEmpty()) {
|
||||||
|
return QVariant::fromValue(directChatsForUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> UserDirectoryListModel::roleNames() const {
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
|
||||||
|
roles[NameRole] = "name";
|
||||||
|
roles[AvatarRole] = "avatar";
|
||||||
|
roles[UserIDRole] = "userID";
|
||||||
|
roles[DirectChatsRole] = "directChats";
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int UserDirectoryListModel::rowCount(const QModelIndex& parent) const {
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return users.count();
|
||||||
|
}
|
||||||
62
src/userdirectorylistmodel.h
Normal file
62
src/userdirectorylistmodel.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef USERDIRECTORYLISTMODEL_H
|
||||||
|
#define USERDIRECTORYLISTMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "connection.h"
|
||||||
|
#include "csapi/users.h"
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
class UserDirectoryListModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY
|
||||||
|
connectionChanged)
|
||||||
|
Q_PROPERTY(
|
||||||
|
QString keyword READ keyword WRITE setKeyword NOTIFY keywordChanged)
|
||||||
|
Q_PROPERTY(bool limited READ limited NOTIFY limitedChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum EventRoles {
|
||||||
|
NameRole = Qt::DisplayRole + 1,
|
||||||
|
AvatarRole,
|
||||||
|
UserIDRole,
|
||||||
|
DirectChatsRole,
|
||||||
|
};
|
||||||
|
|
||||||
|
UserDirectoryListModel(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex& index, int role = NameRole) const override;
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
Connection* connection() const { return m_connection; }
|
||||||
|
void setConnection(Connection* value);
|
||||||
|
|
||||||
|
QString keyword() const { return m_keyword; }
|
||||||
|
void setKeyword(const QString& value);
|
||||||
|
|
||||||
|
bool limited() const { return m_limited; }
|
||||||
|
|
||||||
|
Q_INVOKABLE void search(int count = 50);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Connection* m_connection = nullptr;
|
||||||
|
QString m_keyword;
|
||||||
|
bool m_limited = false;
|
||||||
|
|
||||||
|
bool attempted = false;
|
||||||
|
|
||||||
|
QVector<SearchUserDirectoryJob::User> users;
|
||||||
|
|
||||||
|
SearchUserDirectoryJob* job = nullptr;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectionChanged();
|
||||||
|
void keywordChanged();
|
||||||
|
void limitedChanged();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USERDIRECTORYLISTMODEL_H
|
||||||
Reference in New Issue
Block a user