mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Refactor UserProfile
This commit is contained in:
parent
ac1fbbb69f
commit
08028d5c57
14 changed files with 366 additions and 783 deletions
|
@ -240,7 +240,6 @@ set(SRC_FILES
|
||||||
src/dialogs/ReCaptcha.cpp
|
src/dialogs/ReCaptcha.cpp
|
||||||
src/dialogs/ReadReceipts.cpp
|
src/dialogs/ReadReceipts.cpp
|
||||||
src/dialogs/RoomSettings.cpp
|
src/dialogs/RoomSettings.cpp
|
||||||
src/dialogs/UserProfile.cpp
|
|
||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
src/emoji/Category.cpp
|
src/emoji/Category.cpp
|
||||||
|
@ -280,7 +279,6 @@ set(SRC_FILES
|
||||||
src/ui/Theme.cpp
|
src/ui/Theme.cpp
|
||||||
src/ui/ThemeManager.cpp
|
src/ui/ThemeManager.cpp
|
||||||
src/ui/UserProfile.cpp
|
src/ui/UserProfile.cpp
|
||||||
src/ui/UserProfileModel.cpp
|
|
||||||
|
|
||||||
src/AvatarProvider.cpp
|
src/AvatarProvider.cpp
|
||||||
src/BlurhashProvider.cpp
|
src/BlurhashProvider.cpp
|
||||||
|
@ -449,7 +447,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/dialogs/ReCaptcha.h
|
src/dialogs/ReCaptcha.h
|
||||||
src/dialogs/ReadReceipts.h
|
src/dialogs/ReadReceipts.h
|
||||||
src/dialogs/RoomSettings.h
|
src/dialogs/RoomSettings.h
|
||||||
src/dialogs/UserProfile.h
|
|
||||||
|
|
||||||
# Emoji
|
# Emoji
|
||||||
src/emoji/Category.h
|
src/emoji/Category.h
|
||||||
|
@ -486,7 +483,6 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/ui/Theme.h
|
src/ui/Theme.h
|
||||||
src/ui/ThemeManager.h
|
src/ui/ThemeManager.h
|
||||||
src/ui/UserProfile.h
|
src/ui/UserProfile.h
|
||||||
src/ui/UserProfileModel.h
|
|
||||||
|
|
||||||
src/notifications/Manager.h
|
src/notifications/Manager.h
|
||||||
|
|
||||||
|
|
|
@ -106,17 +106,23 @@ Page {
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: TimelineManager
|
target: TimelineManager
|
||||||
onNewDeviceVerificationRequest: {
|
function onNewDeviceVerificationRequest(flow) {
|
||||||
flow.userId = userId;
|
flow.userId = userId;
|
||||||
flow.sender = false;
|
flow.sender = false;
|
||||||
flow.deviceId = deviceId;
|
flow.deviceId = deviceId;
|
||||||
flow.tranId = transactionId;
|
flow.tranId = transactionId;
|
||||||
deviceVerificationList.add(flow.tranId);
|
deviceVerificationList.add(flow.tranId);
|
||||||
var dialog = deviceVerificationDialog.createObject(timelineRoot,
|
var dialog = deviceVerificationDialog.createObject(timelineRoot, {flow: flow});
|
||||||
{flow: flow});
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Connections {
|
||||||
|
target: TimelineManager.timeline
|
||||||
|
function onOpenProfile(profile) {
|
||||||
|
var userProfile = userProfileComponent.createObject(timelineRoot,{profile: profile});
|
||||||
|
userProfile.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
visible: !TimelineManager.timeline && !TimelineManager.isInitialSync
|
visible: !TimelineManager.timeline && !TimelineManager.isInitialSync
|
||||||
|
@ -293,10 +299,7 @@ Page {
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: chat.model.openUserProfile(modelData.userId)
|
||||||
userProfile = userProfileComponent.createObject(timelineRoot,{user_data: modelData,avatarUrl:chat.model.avatarUrl(modelData.userId)});
|
|
||||||
userProfile.show();
|
|
||||||
}
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
}
|
}
|
||||||
|
@ -311,10 +314,7 @@ Page {
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
onClicked: {
|
onClicked: chat.model.openUserProfile(modelData.userId)
|
||||||
userProfile = userProfileComponent.createObject(timelineRoot,{user_data: modelData,avatarUrl:chat.model.avatarUrl(modelData.userId)});
|
|
||||||
userProfile.show();
|
|
||||||
}
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
propagateComposedEvents: true
|
propagateComposedEvents: true
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,220 +8,211 @@ import im.nheko 1.0
|
||||||
import "./device-verification"
|
import "./device-verification"
|
||||||
|
|
||||||
ApplicationWindow{
|
ApplicationWindow{
|
||||||
property var user_data
|
property var profile
|
||||||
property var avatarUrl
|
|
||||||
property var colors: currentActivePalette
|
|
||||||
|
|
||||||
id:userProfileDialog
|
id: userProfileDialog
|
||||||
height: 650
|
height: 650
|
||||||
width: 420
|
width: 420
|
||||||
modality:Qt.WindowModal
|
modality: Qt.WindowModal
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
palette: colors
|
palette: colors
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: deviceVerificationDialog
|
id: deviceVerificationDialog
|
||||||
DeviceVerification {}
|
DeviceVerification {}
|
||||||
}
|
}
|
||||||
Component{
|
Component{
|
||||||
id: deviceVerificationFlow
|
id: deviceVerificationFlow
|
||||||
DeviceVerificationFlow {}
|
DeviceVerificationFlow {}
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Item{
|
background: Item{
|
||||||
id: userProfileItem
|
id: userProfileItem
|
||||||
width: userProfileDialog.width
|
width: userProfileDialog.width
|
||||||
height: userProfileDialog.height
|
height: userProfileDialog.height
|
||||||
|
|
||||||
// Layout.fillHeight : true
|
// Layout.fillHeight : true
|
||||||
|
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
anchors.fill: userProfileItem
|
anchors.fill: userProfileItem
|
||||||
width: userProfileDialog.width
|
width: userProfileDialog.width
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
Avatar{
|
Avatar {
|
||||||
id: userProfileAvatar
|
url: profile.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
url: avatarUrl.replace("mxc://", "image://MxcImage/")
|
height: 130
|
||||||
height: 130
|
width: 130
|
||||||
width: 130
|
displayName: profile.displayName
|
||||||
displayName: user_data.userName
|
userid: profile.userid
|
||||||
userid: user_data.userId
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.margins : {
|
||||||
Layout.margins : {
|
top: 10
|
||||||
top: 10
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Label{
|
Label {
|
||||||
id: userProfileName
|
text: profile.displayName
|
||||||
text: user_data.userName
|
fontSizeMode: Text.HorizontalFit
|
||||||
fontSizeMode: Text.HorizontalFit
|
font.pixelSize: 20
|
||||||
font.pixelSize: 20
|
color: TimelineManager.userColor(profile.userid, colors.window)
|
||||||
color:TimelineManager.userColor(user_data.userId, colors.window)
|
font.bold: true
|
||||||
font.bold: true
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.alignment: Qt.AlignHCenter
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Label{
|
Label {
|
||||||
id: matrixUserID
|
text: profile.userid
|
||||||
text: user_data.userId
|
fontSizeMode: Text.HorizontalFit
|
||||||
fontSizeMode: Text.HorizontalFit
|
font.pixelSize: 15
|
||||||
font.pixelSize: 15
|
color: colors.text
|
||||||
color:colors.text
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.alignment: Qt.AlignHCenter
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout{
|
RowLayout {
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
ImageButton{
|
ImageButton {
|
||||||
image:":/icons/icons/ui/do-not-disturb-rounded-sign.png"
|
image:":/icons/icons/ui/do-not-disturb-rounded-sign.png"
|
||||||
Layout.margins: {
|
Layout.margins: {
|
||||||
left: 5
|
left: 5
|
||||||
right: 5
|
right: 5
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
ToolTip.text: qsTr("Ban the user")
|
ToolTip.text: qsTr("Ban the user")
|
||||||
onClicked : {
|
onClicked : {
|
||||||
modelDeviceList.deviceList.banUser()
|
profile.banUser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ImageButton{
|
// ImageButton{
|
||||||
// image:":/icons/icons/ui/volume-off-indicator.png"
|
// image:":/icons/icons/ui/volume-off-indicator.png"
|
||||||
// Layout.margins: {
|
// Layout.margins: {
|
||||||
// left: 5
|
// left: 5
|
||||||
// right: 5
|
// right: 5
|
||||||
// }
|
// }
|
||||||
// ToolTip.visible: hovered
|
// ToolTip.visible: hovered
|
||||||
// ToolTip.text: qsTr("Ignore messages from this user")
|
// ToolTip.text: qsTr("Ignore messages from this user")
|
||||||
// onClicked : {
|
// onClicked : {
|
||||||
// modelDeviceList.deviceList.ignoreUser()
|
// profile.ignoreUser()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
ImageButton{
|
ImageButton{
|
||||||
image:":/icons/icons/ui/black-bubble-speech.png"
|
image:":/icons/icons/ui/black-bubble-speech.png"
|
||||||
Layout.margins: {
|
Layout.margins: {
|
||||||
left: 5
|
left: 5
|
||||||
right: 5
|
right: 5
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
ToolTip.text: qsTr("Start a private chat")
|
ToolTip.text: qsTr("Start a private chat")
|
||||||
onClicked : {
|
onClicked : {
|
||||||
modelDeviceList.deviceList.startChat()
|
profile.startChat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageButton{
|
ImageButton{
|
||||||
image:":/icons/icons/ui/round-remove-button.png"
|
image:":/icons/icons/ui/round-remove-button.png"
|
||||||
Layout.margins: {
|
Layout.margins: {
|
||||||
left: 5
|
left: 5
|
||||||
right: 5
|
right: 5
|
||||||
}
|
}
|
||||||
ToolTip.visible: hovered
|
ToolTip.visible: hovered
|
||||||
ToolTip.text: qsTr("Kick the user")
|
ToolTip.text: qsTr("Kick the user")
|
||||||
onClicked : {
|
onClicked : {
|
||||||
modelDeviceList.deviceList.kickUser()
|
profile.kickUser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
implicitHeight: userProfileDialog.height/2 + 20
|
implicitHeight: userProfileDialog.height/2 + 20
|
||||||
implicitWidth: userProfileDialog.width-20
|
implicitWidth: userProfileDialog.width-20
|
||||||
clip: true
|
clip: true
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
ListView{
|
ListView{
|
||||||
id: devicelist
|
id: devicelist
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
clip: true
|
clip: true
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
|
||||||
model: UserProfileModel{
|
model: profile.deviceList
|
||||||
id: modelDeviceList
|
|
||||||
deviceList.userId : user_data.userId
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: RowLayout{
|
delegate: RowLayout{
|
||||||
width: parent.width
|
width: parent.width
|
||||||
Layout.margins : {
|
Layout.margins : {
|
||||||
top : 50
|
top : 50
|
||||||
}
|
}
|
||||||
ColumnLayout{
|
ColumnLayout{
|
||||||
RowLayout{
|
RowLayout{
|
||||||
Text{
|
Text{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: colors.text
|
color: colors.text
|
||||||
font.bold: true
|
font.bold: true
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
text: deviceID
|
text: model.deviceId
|
||||||
}
|
}
|
||||||
Text{
|
Text{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color:colors.text
|
color:colors.text
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
text: (verified_status == UserProfileList.VERIFIED?"V":(verified_status == UserProfileList.UNVERIFIED?"NV":"B"))
|
text: (model.verificationStatus == VerificationStatus.VERIFIED?"V":(model.verificationStatus == VerificationStatus.UNVERIFIED?"NV":"B"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text{
|
Text{
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color:colors.text
|
color:colors.text
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
text: displayName
|
text: model.deviceName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Button{
|
Button{
|
||||||
id: verifyButton
|
id: verifyButton
|
||||||
text:"Verify"
|
text:"Verify"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var newFlow = deviceVerificationFlow.createObject(userProfileDialog,
|
var newFlow = deviceVerificationFlow.createObject(userProfileDialog,
|
||||||
{userId : user_data.userId,sender: true,deviceId : model.deviceID});
|
{userId : profile.userid, sender: true, deviceId : model.deviceID});
|
||||||
deviceVerificationList.add(newFlow.tranId);
|
deviceVerificationList.add(newFlow.tranId);
|
||||||
var dialog = deviceVerificationDialog.createObject(userProfileDialog,
|
var dialog = deviceVerificationDialog.createObject(userProfileDialog, {flow: newFlow});
|
||||||
{flow: newFlow});
|
dialog.show();
|
||||||
dialog.show();
|
}
|
||||||
}
|
Layout.margins:{
|
||||||
Layout.margins:{
|
right: 10
|
||||||
right: 10
|
}
|
||||||
}
|
palette {
|
||||||
palette {
|
button: "white"
|
||||||
button: "white"
|
}
|
||||||
}
|
contentItem: Text {
|
||||||
contentItem: Text {
|
text: verifyButton.text
|
||||||
text: verifyButton.text
|
color: "black"
|
||||||
color: "black"
|
horizontalAlignment: Text.AlignHCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Button{
|
Button{
|
||||||
id: okbutton
|
id: okbutton
|
||||||
text:"OK"
|
text:"OK"
|
||||||
onClicked: userProfileDialog.close()
|
onClicked: userProfileDialog.close()
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
|
|
||||||
|
|
||||||
Layout.margins : {
|
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
|
||||||
right : 10
|
|
||||||
bottom: 5
|
|
||||||
}
|
|
||||||
|
|
||||||
palette {
|
Layout.margins : {
|
||||||
button: "white"
|
right : 10
|
||||||
}
|
bottom: 5
|
||||||
|
}
|
||||||
|
|
||||||
contentItem: Text {
|
palette {
|
||||||
text: okbutton.text
|
button: "white"
|
||||||
color: "black"
|
}
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillHeight: true }
|
contentItem: Text {
|
||||||
}
|
text: okbutton.text
|
||||||
|
color: "black"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,15 +317,6 @@ MainWindow::hasActiveUser()
|
||||||
settings.contains("auth/user_id");
|
settings.contains("auth/user_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MainWindow::openUserProfile(const QString &user_id, const QString &room_id)
|
|
||||||
{
|
|
||||||
auto dialog = new dialogs::UserProfile(this);
|
|
||||||
dialog->init(user_id, room_id);
|
|
||||||
|
|
||||||
showDialog(dialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWindow::openRoomSettings(const QString &room_id)
|
MainWindow::openRoomSettings(const QString &room_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "dialogs/UserProfile.h"
|
|
||||||
#include "ui/OverlayModal.h"
|
#include "ui/OverlayModal.h"
|
||||||
|
|
||||||
#include "jdenticoninterface.h"
|
#include "jdenticoninterface.h"
|
||||||
|
@ -76,7 +75,6 @@ public:
|
||||||
void openLogoutDialog();
|
void openLogoutDialog();
|
||||||
void openRoomSettings(const QString &room_id = "");
|
void openRoomSettings(const QString &room_id = "");
|
||||||
void openMemberListDialog(const QString &room_id = "");
|
void openMemberListDialog(const QString &room_id = "");
|
||||||
void openUserProfile(const QString &user_id, const QString &room_id);
|
|
||||||
void openReadReceiptsDialog(const QString &event_id);
|
void openReadReceiptsDialog(const QString &event_id);
|
||||||
|
|
||||||
void hideOverlay();
|
void hideOverlay();
|
||||||
|
|
|
@ -1,305 +0,0 @@
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QShortcut>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "Cache.h"
|
|
||||||
#include "ChatPage.h"
|
|
||||||
#include "Logging.h"
|
|
||||||
#include "MatrixClient.h"
|
|
||||||
#include "Utils.h"
|
|
||||||
#include "dialogs/UserProfile.h"
|
|
||||||
#include "ui/Avatar.h"
|
|
||||||
#include "ui/FlatButton.h"
|
|
||||||
|
|
||||||
using namespace dialogs;
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::vector<DeviceInfo>)
|
|
||||||
|
|
||||||
constexpr int BUTTON_SIZE = 36;
|
|
||||||
constexpr int BUTTON_RADIUS = BUTTON_SIZE / 2;
|
|
||||||
constexpr int WIDGET_MARGIN = 20;
|
|
||||||
constexpr int TOP_WIDGET_MARGIN = 2 * WIDGET_MARGIN;
|
|
||||||
constexpr int WIDGET_SPACING = 15;
|
|
||||||
constexpr int TEXT_SPACING = 4;
|
|
||||||
constexpr int DEVICE_SPACING = 5;
|
|
||||||
|
|
||||||
DeviceItem::DeviceItem(DeviceInfo device, QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
, info_(std::move(device))
|
|
||||||
{
|
|
||||||
QFont font;
|
|
||||||
font.setBold(true);
|
|
||||||
|
|
||||||
auto deviceIdLabel = new QLabel(info_.device_id, this);
|
|
||||||
deviceIdLabel->setFont(font);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout{this};
|
|
||||||
layout->addWidget(deviceIdLabel);
|
|
||||||
|
|
||||||
if (!info_.display_name.isEmpty())
|
|
||||||
layout->addWidget(new QLabel(info_.display_name, this));
|
|
||||||
|
|
||||||
layout->setMargin(0);
|
|
||||||
layout->setSpacing(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
UserProfile::UserProfile(QWidget *parent)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
setAutoFillBackground(true);
|
|
||||||
setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
||||||
|
|
||||||
QIcon banIcon, kickIcon, ignoreIcon, startChatIcon;
|
|
||||||
|
|
||||||
banIcon.addFile(":/icons/icons/ui/do-not-disturb-rounded-sign.png");
|
|
||||||
banBtn_ = new FlatButton(this);
|
|
||||||
banBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
||||||
banBtn_->setCornerRadius(BUTTON_RADIUS);
|
|
||||||
banBtn_->setIcon(banIcon);
|
|
||||||
banBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS));
|
|
||||||
banBtn_->setToolTip(tr("Ban the user from the room"));
|
|
||||||
|
|
||||||
ignoreIcon.addFile(":/icons/icons/ui/volume-off-indicator.png");
|
|
||||||
ignoreBtn_ = new FlatButton(this);
|
|
||||||
ignoreBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
||||||
ignoreBtn_->setCornerRadius(BUTTON_RADIUS);
|
|
||||||
ignoreBtn_->setIcon(ignoreIcon);
|
|
||||||
ignoreBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS));
|
|
||||||
ignoreBtn_->setToolTip(tr("Ignore messages from this user"));
|
|
||||||
ignoreBtn_->setDisabled(true); // Not used yet.
|
|
||||||
|
|
||||||
kickIcon.addFile(":/icons/icons/ui/round-remove-button.png");
|
|
||||||
kickBtn_ = new FlatButton(this);
|
|
||||||
kickBtn_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
||||||
kickBtn_->setCornerRadius(BUTTON_RADIUS);
|
|
||||||
kickBtn_->setIcon(kickIcon);
|
|
||||||
kickBtn_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS));
|
|
||||||
kickBtn_->setToolTip(tr("Kick the user from the room"));
|
|
||||||
|
|
||||||
startChatIcon.addFile(":/icons/icons/ui/black-bubble-speech.png");
|
|
||||||
startChat_ = new FlatButton(this);
|
|
||||||
startChat_->setFixedSize(BUTTON_SIZE, BUTTON_SIZE);
|
|
||||||
startChat_->setCornerRadius(BUTTON_RADIUS);
|
|
||||||
startChat_->setIcon(startChatIcon);
|
|
||||||
startChat_->setIconSize(QSize(BUTTON_RADIUS, BUTTON_RADIUS));
|
|
||||||
startChat_->setToolTip(tr("Start a conversation"));
|
|
||||||
|
|
||||||
connect(startChat_, &QPushButton::clicked, this, [this]() {
|
|
||||||
auto user_id = userIdLabel_->text();
|
|
||||||
|
|
||||||
mtx::requests::CreateRoom req;
|
|
||||||
req.preset = mtx::requests::Preset::PrivateChat;
|
|
||||||
req.visibility = mtx::requests::Visibility::Private;
|
|
||||||
|
|
||||||
if (utils::localUser() != user_id)
|
|
||||||
req.invite = {user_id.toStdString()};
|
|
||||||
|
|
||||||
emit ChatPage::instance()->createRoom(req);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(banBtn_, &QPushButton::clicked, this, [this] {
|
|
||||||
ChatPage::instance()->banUser(userIdLabel_->text(), "");
|
|
||||||
});
|
|
||||||
connect(kickBtn_, &QPushButton::clicked, this, [this] {
|
|
||||||
ChatPage::instance()->kickUser(userIdLabel_->text(), "");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Button line
|
|
||||||
auto btnLayout = new QHBoxLayout;
|
|
||||||
btnLayout->addStretch(1);
|
|
||||||
btnLayout->addWidget(startChat_);
|
|
||||||
btnLayout->addWidget(ignoreBtn_);
|
|
||||||
|
|
||||||
btnLayout->addWidget(kickBtn_);
|
|
||||||
btnLayout->addWidget(banBtn_);
|
|
||||||
btnLayout->addStretch(1);
|
|
||||||
btnLayout->setSpacing(8);
|
|
||||||
btnLayout->setMargin(0);
|
|
||||||
|
|
||||||
avatar_ = new Avatar(this, 128);
|
|
||||||
avatar_->setLetter("X");
|
|
||||||
|
|
||||||
QFont font;
|
|
||||||
font.setPointSizeF(font.pointSizeF() * 2);
|
|
||||||
|
|
||||||
userIdLabel_ = new QLabel(this);
|
|
||||||
displayNameLabel_ = new QLabel(this);
|
|
||||||
displayNameLabel_->setFont(font);
|
|
||||||
|
|
||||||
auto textLayout = new QVBoxLayout;
|
|
||||||
textLayout->addWidget(displayNameLabel_);
|
|
||||||
textLayout->addWidget(userIdLabel_);
|
|
||||||
textLayout->setAlignment(displayNameLabel_, Qt::AlignCenter | Qt::AlignTop);
|
|
||||||
textLayout->setAlignment(userIdLabel_, Qt::AlignCenter | Qt::AlignTop);
|
|
||||||
textLayout->setSpacing(TEXT_SPACING);
|
|
||||||
textLayout->setMargin(0);
|
|
||||||
|
|
||||||
devices_ = new QListWidget{this};
|
|
||||||
devices_->setFrameStyle(QFrame::NoFrame);
|
|
||||||
devices_->setSelectionMode(QAbstractItemView::NoSelection);
|
|
||||||
devices_->setAttribute(Qt::WA_MacShowFocusRect, 0);
|
|
||||||
devices_->setSpacing(DEVICE_SPACING);
|
|
||||||
|
|
||||||
QFont descriptionLabelFont;
|
|
||||||
descriptionLabelFont.setWeight(65);
|
|
||||||
|
|
||||||
devicesLabel_ = new QLabel(tr("Devices").toUpper(), this);
|
|
||||||
devicesLabel_->setFont(descriptionLabelFont);
|
|
||||||
devicesLabel_->hide();
|
|
||||||
devicesLabel_->setFixedSize(devicesLabel_->sizeHint());
|
|
||||||
|
|
||||||
auto okBtn = new QPushButton("OK", this);
|
|
||||||
|
|
||||||
auto closeLayout = new QHBoxLayout();
|
|
||||||
closeLayout->setSpacing(15);
|
|
||||||
closeLayout->addStretch(1);
|
|
||||||
closeLayout->addWidget(okBtn);
|
|
||||||
|
|
||||||
auto vlayout = new QVBoxLayout{this};
|
|
||||||
vlayout->addWidget(avatar_, 0, Qt::AlignCenter | Qt::AlignTop);
|
|
||||||
vlayout->addLayout(textLayout);
|
|
||||||
vlayout->addLayout(btnLayout);
|
|
||||||
vlayout->addWidget(devicesLabel_, 0, Qt::AlignLeft);
|
|
||||||
vlayout->addWidget(devices_, 1);
|
|
||||||
vlayout->addLayout(closeLayout);
|
|
||||||
|
|
||||||
QFont largeFont;
|
|
||||||
largeFont.setPointSizeF(largeFont.pointSizeF() * 1.5);
|
|
||||||
|
|
||||||
setMinimumWidth(
|
|
||||||
std::max(devices_->sizeHint().width() + 4 * WIDGET_MARGIN, conf::window::minModalWidth));
|
|
||||||
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
|
|
||||||
vlayout->setSpacing(WIDGET_SPACING);
|
|
||||||
vlayout->setContentsMargins(WIDGET_MARGIN, TOP_WIDGET_MARGIN, WIDGET_MARGIN, WIDGET_MARGIN);
|
|
||||||
|
|
||||||
qRegisterMetaType<std::vector<DeviceInfo>>();
|
|
||||||
|
|
||||||
auto closeShortcut = new QShortcut(QKeySequence(QKeySequence::Cancel), this);
|
|
||||||
connect(closeShortcut, &QShortcut::activated, this, &UserProfile::close);
|
|
||||||
connect(okBtn, &QPushButton::clicked, this, &UserProfile::close);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UserProfile::resetToDefaults()
|
|
||||||
{
|
|
||||||
avatar_->setLetter("X");
|
|
||||||
devices_->clear();
|
|
||||||
|
|
||||||
ignoreBtn_->show();
|
|
||||||
devices_->hide();
|
|
||||||
devicesLabel_->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UserProfile::init(const QString &userId, const QString &roomId)
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
|
|
||||||
auto displayName = cache::displayName(roomId, userId);
|
|
||||||
|
|
||||||
userIdLabel_->setText(userId);
|
|
||||||
displayNameLabel_->setText(displayName);
|
|
||||||
avatar_->setLetter(utils::firstChar(displayName));
|
|
||||||
|
|
||||||
avatar_->setImage(roomId, userId);
|
|
||||||
|
|
||||||
auto localUser = utils::localUser();
|
|
||||||
|
|
||||||
try {
|
|
||||||
bool hasMemberRights =
|
|
||||||
cache::hasEnoughPowerLevel({mtx::events::EventType::RoomMember},
|
|
||||||
roomId.toStdString(),
|
|
||||||
localUser.toStdString());
|
|
||||||
if (!hasMemberRights) {
|
|
||||||
kickBtn_->hide();
|
|
||||||
banBtn_->hide();
|
|
||||||
} else {
|
|
||||||
kickBtn_->show();
|
|
||||||
banBtn_->show();
|
|
||||||
}
|
|
||||||
} catch (const lmdb::error &e) {
|
|
||||||
nhlog::db()->warn("lmdb error: {}", e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localUser == userId) {
|
|
||||||
// TODO: click on display name & avatar to change.
|
|
||||||
kickBtn_->hide();
|
|
||||||
banBtn_->hide();
|
|
||||||
ignoreBtn_->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
mtx::requests::QueryKeys req;
|
|
||||||
req.device_keys[userId.toStdString()] = {};
|
|
||||||
|
|
||||||
// A proxy object is used to emit the signal instead of the original object
|
|
||||||
// which might be destroyed by the time the http call finishes.
|
|
||||||
auto proxy = std::make_shared<Proxy>();
|
|
||||||
QObject::connect(proxy.get(), &Proxy::done, this, &UserProfile::updateDeviceList);
|
|
||||||
|
|
||||||
http::client()->query_keys(
|
|
||||||
req,
|
|
||||||
[user_id = userId.toStdString(), proxy = std::move(proxy)](
|
|
||||||
const mtx::responses::QueryKeys &res, mtx::http::RequestErr err) {
|
|
||||||
if (err) {
|
|
||||||
nhlog::net()->warn("failed to query device keys: {} {}",
|
|
||||||
err->matrix_error.error,
|
|
||||||
static_cast<int>(err->status_code));
|
|
||||||
// TODO: Notify the UI.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.device_keys.empty() ||
|
|
||||||
(res.device_keys.find(user_id) == res.device_keys.end())) {
|
|
||||||
nhlog::net()->warn("no devices retrieved {}", user_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto devices = res.device_keys.at(user_id);
|
|
||||||
|
|
||||||
std::vector<DeviceInfo> deviceInfo;
|
|
||||||
for (const auto &d : devices) {
|
|
||||||
auto device = d.second;
|
|
||||||
|
|
||||||
// TODO: Verify signatures and ignore those that don't pass.
|
|
||||||
deviceInfo.emplace_back(DeviceInfo{
|
|
||||||
QString::fromStdString(d.first),
|
|
||||||
QString::fromStdString(device.unsigned_info.device_display_name)});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(deviceInfo.begin(),
|
|
||||||
deviceInfo.end(),
|
|
||||||
[](const DeviceInfo &a, const DeviceInfo &b) {
|
|
||||||
return a.device_id > b.device_id;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceInfo.empty())
|
|
||||||
emit proxy->done(QString::fromStdString(user_id), deviceInfo);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UserProfile::updateDeviceList(const QString &user_id, const std::vector<DeviceInfo> &devices)
|
|
||||||
{
|
|
||||||
if (user_id != userIdLabel_->text())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const auto &dev : devices) {
|
|
||||||
auto deviceItem = new DeviceItem(dev, this);
|
|
||||||
auto item = new QListWidgetItem;
|
|
||||||
|
|
||||||
item->setSizeHint(deviceItem->minimumSizeHint());
|
|
||||||
item->setFlags(Qt::NoItemFlags);
|
|
||||||
item->setTextAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
devices_->insertItem(devices_->count() - 1, item);
|
|
||||||
devices_->setItemWidget(item, deviceItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
devicesLabel_->show();
|
|
||||||
devices_->show();
|
|
||||||
adjustSize();
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
class Avatar;
|
|
||||||
class FlatButton;
|
|
||||||
class QLabel;
|
|
||||||
class QListWidget;
|
|
||||||
class Toggle;
|
|
||||||
|
|
||||||
struct DeviceInfo
|
|
||||||
{
|
|
||||||
QString device_id;
|
|
||||||
QString display_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Proxy : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void done(const QString &user_id, const std::vector<DeviceInfo> &devices);
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace dialogs {
|
|
||||||
|
|
||||||
class DeviceItem : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit DeviceItem(DeviceInfo device, QWidget *parent);
|
|
||||||
|
|
||||||
private:
|
|
||||||
DeviceInfo info_;
|
|
||||||
|
|
||||||
// Toggle *verifyToggle_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class UserProfile : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit UserProfile(QWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void init(const QString &userId, const QString &roomId);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void updateDeviceList(const QString &user_id, const std::vector<DeviceInfo> &devices);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void resetToDefaults();
|
|
||||||
|
|
||||||
Avatar *avatar_;
|
|
||||||
|
|
||||||
QLabel *userIdLabel_;
|
|
||||||
QLabel *displayNameLabel_;
|
|
||||||
|
|
||||||
FlatButton *banBtn_;
|
|
||||||
FlatButton *kickBtn_;
|
|
||||||
FlatButton *ignoreBtn_;
|
|
||||||
FlatButton *startChat_;
|
|
||||||
|
|
||||||
QLabel *devicesLabel_;
|
|
||||||
QListWidget *devices_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // dialogs
|
|
|
@ -654,9 +654,9 @@ TimelineModel::viewDecryptedRawMessage(QString id) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineModel::openUserProfile(QString userid) const
|
TimelineModel::openUserProfile(QString userid)
|
||||||
{
|
{
|
||||||
MainWindow::instance()->openUserProfile(userid, room_id_);
|
emit openProfile(new UserProfile(room_id_, userid, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -9,7 +9,12 @@
|
||||||
#include <mtxclient/http/errors.hpp>
|
#include <mtxclient/http/errors.hpp>
|
||||||
|
|
||||||
#include "CacheCryptoStructs.h"
|
#include "CacheCryptoStructs.h"
|
||||||
|
<<<<<<< HEAD
|
||||||
#include "EventStore.h"
|
#include "EventStore.h"
|
||||||
|
=======
|
||||||
|
#include "ReactionsModel.h"
|
||||||
|
#include "ui/UserProfile.h"
|
||||||
|
>>>>>>> Refactor UserProfile
|
||||||
|
|
||||||
namespace mtx::http {
|
namespace mtx::http {
|
||||||
using RequestErr = const std::optional<mtx::http::ClientError> &;
|
using RequestErr = const std::optional<mtx::http::ClientError> &;
|
||||||
|
@ -188,7 +193,7 @@ public:
|
||||||
Q_INVOKABLE QString escapeEmoji(QString str) const;
|
Q_INVOKABLE QString escapeEmoji(QString str) const;
|
||||||
Q_INVOKABLE void viewRawMessage(QString id) const;
|
Q_INVOKABLE void viewRawMessage(QString id) const;
|
||||||
Q_INVOKABLE void viewDecryptedRawMessage(QString id) const;
|
Q_INVOKABLE void viewDecryptedRawMessage(QString id) const;
|
||||||
Q_INVOKABLE void openUserProfile(QString userid) const;
|
Q_INVOKABLE void openUserProfile(QString userid);
|
||||||
Q_INVOKABLE void replyAction(QString id);
|
Q_INVOKABLE void replyAction(QString id);
|
||||||
Q_INVOKABLE void readReceiptsAction(QString id) const;
|
Q_INVOKABLE void readReceiptsAction(QString id) const;
|
||||||
Q_INVOKABLE void redactEvent(QString id);
|
Q_INVOKABLE void redactEvent(QString id);
|
||||||
|
@ -256,8 +261,7 @@ signals:
|
||||||
void replyChanged(QString reply);
|
void replyChanged(QString reply);
|
||||||
void paginationInProgressChanged(const bool);
|
void paginationInProgressChanged(const bool);
|
||||||
|
|
||||||
void newMessageToSend(mtx::events::collections::TimelineEvents event);
|
void openProfile(UserProfile *profile);
|
||||||
void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendEncryptedMessage(const std::string txn_id, nlohmann::json content);
|
void sendEncryptedMessage(const std::string txn_id, nlohmann::json content);
|
||||||
|
|
|
@ -16,10 +16,9 @@
|
||||||
#include "dialogs/ImageOverlay.h"
|
#include "dialogs/ImageOverlay.h"
|
||||||
#include "emoji/EmojiModel.h"
|
#include "emoji/EmojiModel.h"
|
||||||
#include "emoji/Provider.h"
|
#include "emoji/Provider.h"
|
||||||
#include "src/ui/UserProfile.h"
|
|
||||||
#include "src/ui/UserProfileModel.h"
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
|
Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
|
||||||
|
Q_DECLARE_METATYPE(std::vector<DeviceInfo>)
|
||||||
|
|
||||||
namespace msgs = mtx::events::msg;
|
namespace msgs = mtx::events::msg;
|
||||||
|
|
||||||
|
@ -109,15 +108,28 @@ TimelineViewManager::TimelineViewManager(QSharedPointer<UserSettings> userSettin
|
||||||
0,
|
0,
|
||||||
"MtxEvent",
|
"MtxEvent",
|
||||||
"Can't instantiate enum!");
|
"Can't instantiate enum!");
|
||||||
|
qmlRegisterUncreatableMetaObject(verification::staticMetaObject,
|
||||||
|
"im.nheko",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
"VerificationStatus",
|
||||||
|
"Can't instantiate enum!");
|
||||||
|
|
||||||
qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice");
|
qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice");
|
||||||
qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
|
qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
|
||||||
qmlRegisterType<DeviceVerificationFlow>("im.nheko", 1, 0, "DeviceVerificationFlow");
|
qmlRegisterType<DeviceVerificationFlow>("im.nheko", 1, 0, "DeviceVerificationFlow");
|
||||||
qmlRegisterType<UserProfileModel>("im.nheko", 1, 0, "UserProfileModel");
|
qmlRegisterUncreatableType<UserProfile>(
|
||||||
qmlRegisterType<UserProfile>("im.nheko", 1, 0, "UserProfileList");
|
"im.nheko",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
"UserProfileModel",
|
||||||
|
"UserProfile needs to be instantiated on the C++ side");
|
||||||
qmlRegisterSingletonInstance("im.nheko", 1, 0, "TimelineManager", this);
|
qmlRegisterSingletonInstance("im.nheko", 1, 0, "TimelineManager", this);
|
||||||
qmlRegisterSingletonInstance("im.nheko", 1, 0, "Settings", settings.data());
|
qmlRegisterSingletonInstance("im.nheko", 1, 0, "Settings", settings.data());
|
||||||
|
|
||||||
qRegisterMetaType<mtx::events::collections::TimelineEvents>();
|
qRegisterMetaType<mtx::events::collections::TimelineEvents>();
|
||||||
|
qRegisterMetaType<std::vector<DeviceInfo>>();
|
||||||
|
|
||||||
qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
|
qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
|
||||||
qmlRegisterType<emoji::EmojiProxyModel>("im.nheko.EmojiModel", 1, 0, "EmojiProxyModel");
|
qmlRegisterType<emoji::EmojiProxyModel>("im.nheko.EmojiModel", 1, 0, "EmojiProxyModel");
|
||||||
qmlRegisterUncreatableType<QAbstractItemModel>(
|
qmlRegisterUncreatableType<QAbstractItemModel>(
|
||||||
|
|
|
@ -5,47 +5,72 @@
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "mtx/responses/crypto.hpp"
|
#include "mtx/responses/crypto.hpp"
|
||||||
|
|
||||||
#include <iostream> // only for debugging
|
UserProfile::UserProfile(QString roomid, QString userid, QObject *parent)
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(UserProfile::Status)
|
|
||||||
|
|
||||||
UserProfile::UserProfile(QObject *parent)
|
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
, roomid_(roomid)
|
||||||
|
, userid_(userid)
|
||||||
{
|
{
|
||||||
qRegisterMetaType<UserProfile::Status>();
|
fetchDeviceList(this->userid_);
|
||||||
connect(
|
|
||||||
this, &UserProfile::updateDeviceList, this, [this]() { fetchDeviceList(this->userId); });
|
|
||||||
connect(
|
|
||||||
this,
|
|
||||||
&UserProfile::appendDeviceList,
|
|
||||||
this,
|
|
||||||
[this](QString device_id, QString device_name, UserProfile::Status verification_status) {
|
|
||||||
this->deviceList.push_back(
|
|
||||||
DeviceInfo{device_id, device_name, verification_status});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DeviceInfo>
|
QHash<int, QByteArray>
|
||||||
UserProfile::getDeviceList()
|
DeviceInfoModel::roleNames() const
|
||||||
{
|
{
|
||||||
return this->deviceList;
|
return {
|
||||||
|
{DeviceId, "deviceId"},
|
||||||
|
{DeviceName, "deviceName"},
|
||||||
|
{VerificationStatus, "verificationStatus"},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QVariant
|
||||||
UserProfile::getUserId()
|
DeviceInfoModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
return this->userId;
|
if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case DeviceId:
|
||||||
|
return deviceList_[index.row()].device_id;
|
||||||
|
case DeviceName:
|
||||||
|
return deviceList_[index.row()].display_name;
|
||||||
|
case VerificationStatus:
|
||||||
|
return QVariant::fromValue(deviceList_[index.row()].verification_status);
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UserProfile::setUserId(const QString &user_id)
|
DeviceInfoModel::reset(const std::vector<DeviceInfo> &deviceList)
|
||||||
{
|
{
|
||||||
if (this->userId != userId)
|
beginResetModel();
|
||||||
return;
|
this->deviceList_ = std::move(deviceList);
|
||||||
else {
|
endResetModel();
|
||||||
this->userId = user_id;
|
}
|
||||||
emit UserProfile::userIdChanged();
|
|
||||||
}
|
DeviceInfoModel *
|
||||||
|
UserProfile::deviceList()
|
||||||
|
{
|
||||||
|
return &this->deviceList_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
UserProfile::userid()
|
||||||
|
{
|
||||||
|
return this->userid_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
UserProfile::displayName()
|
||||||
|
{
|
||||||
|
return cache::displayName(roomid_, userid_);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
UserProfile::avatarUrl()
|
||||||
|
{
|
||||||
|
return cache::avatarUrl(roomid_, userid_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -74,27 +99,27 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res,
|
||||||
auto device = d.second;
|
auto device = d.second;
|
||||||
|
|
||||||
// TODO: Verify signatures and ignore those that don't pass.
|
// TODO: Verify signatures and ignore those that don't pass.
|
||||||
UserProfile::Status verified = UserProfile::Status::UNVERIFIED;
|
verification::Status verified = verification::Status::UNVERIFIED;
|
||||||
if (cross_verified.has_value()) {
|
if (cross_verified.has_value()) {
|
||||||
if (std::find(cross_verified->begin(), cross_verified->end(), d.first) !=
|
if (std::find(cross_verified->begin(), cross_verified->end(), d.first) !=
|
||||||
cross_verified->end())
|
cross_verified->end())
|
||||||
verified = UserProfile::Status::VERIFIED;
|
verified = verification::Status::VERIFIED;
|
||||||
} else if (device_verified.has_value()) {
|
} else if (device_verified.has_value()) {
|
||||||
if (std::find(device_verified->device_verified.begin(),
|
if (std::find(device_verified->device_verified.begin(),
|
||||||
device_verified->device_verified.end(),
|
device_verified->device_verified.end(),
|
||||||
d.first) != device_verified->device_verified.end())
|
d.first) != device_verified->device_verified.end())
|
||||||
verified = UserProfile::Status::VERIFIED;
|
verified = verification::Status::VERIFIED;
|
||||||
} else if (device_verified.has_value()) {
|
} else if (device_verified.has_value()) {
|
||||||
if (std::find(device_verified->device_blocked.begin(),
|
if (std::find(device_verified->device_blocked.begin(),
|
||||||
device_verified->device_blocked.end(),
|
device_verified->device_blocked.end(),
|
||||||
d.first) != device_verified->device_blocked.end())
|
d.first) != device_verified->device_blocked.end())
|
||||||
verified = UserProfile::Status::BLOCKED;
|
verified = verification::Status::BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit UserProfile::appendDeviceList(
|
deviceInfo.push_back(
|
||||||
QString::fromStdString(d.first),
|
{QString::fromStdString(d.first),
|
||||||
QString::fromStdString(device.unsigned_info.device_display_name),
|
QString::fromStdString(device.unsigned_info.device_display_name),
|
||||||
verified);
|
verified});
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::sort(
|
// std::sort(
|
||||||
|
@ -102,8 +127,7 @@ UserProfile::callback_fn(const mtx::responses::QueryKeys &res,
|
||||||
// return a.device_id > b.device_id;
|
// return a.device_id > b.device_id;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
this->deviceList = std::move(deviceInfo);
|
this->deviceList_.queueReset(std::move(deviceInfo));
|
||||||
emit UserProfile::deviceListUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -130,7 +154,7 @@ UserProfile::fetchDeviceList(const QString &userID)
|
||||||
void
|
void
|
||||||
UserProfile::banUser()
|
UserProfile::banUser()
|
||||||
{
|
{
|
||||||
ChatPage::instance()->banUser(this->userId, "");
|
ChatPage::instance()->banUser(this->userid_, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// void ignoreUser(){
|
// void ignoreUser(){
|
||||||
|
@ -140,7 +164,7 @@ UserProfile::banUser()
|
||||||
void
|
void
|
||||||
UserProfile::kickUser()
|
UserProfile::kickUser()
|
||||||
{
|
{
|
||||||
ChatPage::instance()->kickUser(this->userId, "");
|
ChatPage::instance()->kickUser(this->userid_, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -149,7 +173,7 @@ UserProfile::startChat()
|
||||||
mtx::requests::CreateRoom req;
|
mtx::requests::CreateRoom req;
|
||||||
req.preset = mtx::requests::Preset::PrivateChat;
|
req.preset = mtx::requests::Preset::PrivateChat;
|
||||||
req.visibility = mtx::requests::Visibility::Private;
|
req.visibility = mtx::requests::Visibility::Private;
|
||||||
if (utils::localUser() != this->userId)
|
if (utils::localUser() != this->userid_)
|
||||||
req.invite = {this->userId.toStdString()};
|
req.invite = {this->userid_.toStdString()};
|
||||||
emit ChatPage::instance()->createRoom(req);
|
emit ChatPage::instance()->createRoom(req);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,92 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
|
|
||||||
class DeviceInfo;
|
namespace verification {
|
||||||
|
Q_NAMESPACE
|
||||||
|
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
VERIFIED,
|
||||||
|
UNVERIFIED,
|
||||||
|
BLOCKED
|
||||||
|
};
|
||||||
|
Q_ENUM_NS(Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeviceInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeviceInfo(const QString deviceID,
|
||||||
|
const QString displayName,
|
||||||
|
verification::Status verification_status_)
|
||||||
|
: device_id(deviceID)
|
||||||
|
, display_name(displayName)
|
||||||
|
, verification_status(verification_status_)
|
||||||
|
{}
|
||||||
|
DeviceInfo()
|
||||||
|
: verification_status(verification::UNVERIFIED)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString device_id;
|
||||||
|
QString display_name;
|
||||||
|
|
||||||
|
verification::Status verification_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeviceInfoModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
DeviceId,
|
||||||
|
DeviceName,
|
||||||
|
VerificationStatus,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit DeviceInfoModel(QObject *parent = nullptr)
|
||||||
|
{
|
||||||
|
(void)parent;
|
||||||
|
connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset);
|
||||||
|
};
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const
|
||||||
|
{
|
||||||
|
(void)parent;
|
||||||
|
return (int)deviceList_.size();
|
||||||
|
}
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void queueReset(const std::vector<DeviceInfo> &deviceList);
|
||||||
|
public slots:
|
||||||
|
void reset(const std::vector<DeviceInfo> &deviceList);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<DeviceInfo> deviceList_;
|
||||||
|
};
|
||||||
|
|
||||||
class UserProfile : public QObject
|
class UserProfile : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString userId READ getUserId WRITE setUserId NOTIFY userIdChanged)
|
Q_PROPERTY(QString displayName READ displayName CONSTANT)
|
||||||
Q_PROPERTY(std::vector<DeviceInfo> deviceList READ getDeviceList NOTIFY deviceListUpdated)
|
Q_PROPERTY(QString userid READ userid CONSTANT)
|
||||||
|
Q_PROPERTY(QString avatarUrl READ avatarUrl CONSTANT)
|
||||||
|
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList CONSTANT)
|
||||||
public:
|
public:
|
||||||
// constructor
|
UserProfile(QString roomid, QString userid, QObject *parent = 0);
|
||||||
explicit UserProfile(QObject *parent = 0);
|
|
||||||
// getters
|
|
||||||
std::vector<DeviceInfo> getDeviceList();
|
|
||||||
QString getUserId();
|
|
||||||
// setters
|
|
||||||
void setUserId(const QString &userId);
|
|
||||||
|
|
||||||
enum Status
|
DeviceInfoModel *deviceList();
|
||||||
{
|
|
||||||
VERIFIED,
|
QString userid();
|
||||||
UNVERIFIED,
|
QString displayName();
|
||||||
BLOCKED
|
QString avatarUrl();
|
||||||
};
|
|
||||||
Q_ENUM(Status)
|
|
||||||
|
|
||||||
void fetchDeviceList(const QString &userID);
|
void fetchDeviceList(const QString &userID);
|
||||||
Q_INVOKABLE void banUser();
|
Q_INVOKABLE void banUser();
|
||||||
|
@ -36,37 +94,13 @@ public:
|
||||||
Q_INVOKABLE void kickUser();
|
Q_INVOKABLE void kickUser();
|
||||||
Q_INVOKABLE void startChat();
|
Q_INVOKABLE void startChat();
|
||||||
|
|
||||||
signals:
|
|
||||||
void userIdChanged();
|
|
||||||
void deviceListUpdated();
|
|
||||||
void updateDeviceList();
|
|
||||||
void appendDeviceList(const QString device_id,
|
|
||||||
const QString device_naem,
|
|
||||||
const UserProfile::Status verification_status);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<DeviceInfo> deviceList;
|
QString roomid_, userid_;
|
||||||
QString userId;
|
|
||||||
std::optional<std::string> cross_verified;
|
std::optional<std::string> cross_verified;
|
||||||
|
DeviceInfoModel deviceList_;
|
||||||
|
|
||||||
void callback_fn(const mtx::responses::QueryKeys &res,
|
void callback_fn(const mtx::responses::QueryKeys &res,
|
||||||
mtx::http::RequestErr err,
|
mtx::http::RequestErr err,
|
||||||
std::string user_id,
|
std::string user_id,
|
||||||
std::optional<std::vector<std::string>> cross_verified);
|
std::optional<std::vector<std::string>> cross_verified);
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DeviceInfo(const QString deviceID,
|
|
||||||
const QString displayName,
|
|
||||||
UserProfile::Status verification_status_)
|
|
||||||
: device_id(deviceID)
|
|
||||||
, display_name(displayName)
|
|
||||||
, verification_status(verification_status_)
|
|
||||||
{}
|
|
||||||
|
|
||||||
QString device_id;
|
|
||||||
QString display_name;
|
|
||||||
UserProfile::Status verification_status;
|
|
||||||
};
|
|
|
@ -1,63 +0,0 @@
|
||||||
#include "UserProfileModel.h"
|
|
||||||
#include <QModelIndex>
|
|
||||||
|
|
||||||
UserProfileModel::UserProfileModel(QObject *parent)
|
|
||||||
: QAbstractListModel(parent)
|
|
||||||
, deviceList(nullptr)
|
|
||||||
{
|
|
||||||
this->deviceList = new UserProfile(this);
|
|
||||||
|
|
||||||
connect(this->deviceList, &UserProfile::userIdChanged, this, [this]() {
|
|
||||||
emit this->deviceList->updateDeviceList();
|
|
||||||
});
|
|
||||||
connect(this->deviceList, &UserProfile::deviceListUpdated, this, [this]() {
|
|
||||||
beginResetModel();
|
|
||||||
this->beginInsertRows(
|
|
||||||
QModelIndex(), 0, this->deviceList->getDeviceList().size() - 1);
|
|
||||||
this->endInsertRows();
|
|
||||||
endResetModel();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
UserProfileModel::rowCount(const QModelIndex &parent) const
|
|
||||||
{
|
|
||||||
if (parent.isValid() || !this->deviceList)
|
|
||||||
return 0;
|
|
||||||
return this->deviceList->getDeviceList().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant
|
|
||||||
UserProfileModel::data(const QModelIndex &index, int role) const
|
|
||||||
{
|
|
||||||
if (!index.isValid() &&
|
|
||||||
static_cast<int>(this->deviceList->getDeviceList().size()) <= index.row())
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
const DeviceInfo device = this->deviceList->getDeviceList().at(index.row());
|
|
||||||
switch (role) {
|
|
||||||
case DEVICEID:
|
|
||||||
return QVariant(device.device_id);
|
|
||||||
case DISPLAYNAME:
|
|
||||||
return QVariant(device.display_name);
|
|
||||||
case VERIFIED_STATUS:
|
|
||||||
return device.verification_status;
|
|
||||||
}
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray>
|
|
||||||
UserProfileModel::roleNames() const
|
|
||||||
{
|
|
||||||
QHash<int, QByteArray> names;
|
|
||||||
names[DEVICEID] = "deviceID";
|
|
||||||
names[DISPLAYNAME] = "displayName";
|
|
||||||
names[VERIFIED_STATUS] = "verified_status";
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserProfile *
|
|
||||||
UserProfileModel::getList() const
|
|
||||||
{
|
|
||||||
return (this->deviceList);
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "UserProfile.h"
|
|
||||||
#include <QAbstractListModel>
|
|
||||||
|
|
||||||
class UserProfile; // forward declaration of the class UserProfile
|
|
||||||
|
|
||||||
class UserProfileModel : public QAbstractListModel
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(UserProfile *deviceList READ getList)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit UserProfileModel(QObject *parent = nullptr);
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
DEVICEID,
|
|
||||||
DISPLAYNAME,
|
|
||||||
VERIFIED_STATUS
|
|
||||||
};
|
|
||||||
UserProfile *getList() const;
|
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const override;
|
|
||||||
virtual QHash<int, QByteArray> roleNames() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
UserProfile *deviceList;
|
|
||||||
};
|
|
Loading…
Reference in a new issue