diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b760934d..dc202fc3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -273,6 +273,7 @@ set(SRC_FILES src/ui/Theme.cpp src/ui/ThemeManager.cpp src/ui/UserProfile.cpp + src/ui/UserProfileModel.cpp src/AvatarProvider.cpp src/BlurhashProvider.cpp @@ -475,6 +476,7 @@ qt5_wrap_cpp(MOC_HEADERS src/ui/Theme.h src/ui/ThemeManager.h src/ui/UserProfile.h + src/ui/UserProfileModel.h src/notifications/Manager.h diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 90d30b077..8ca9126e3 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -288,6 +288,7 @@ Page { MouseArea { anchors.fill: parent + Layout.alignment: Qt.AlignHCenter onClicked: { userProfile.user_data = modelData userProfile.show() diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml index ae91abc49..e395ad6bd 100644 --- a/resources/qml/UserProfile.qml +++ b/resources/qml/UserProfile.qml @@ -20,21 +20,17 @@ ApplicationWindow{ userProfileAvatar.url = chat.model.avatarUrl(user_data.userId).replace("mxc://", "image://MxcImage/") userProfileName.text = user_data.userName matrixUserID.text = user_data.userId - userProfile.userId = user_data.userId - log_devices() + userProfileList.userId = user_data.userId } - function log_devices() - { - console.log(userProfile.deviceList); - userProfile.deviceList.forEach((item,index)=>{ - console.log(item.device_id) - console.log(item.display_name) - }) - } - - UserProfileContent{ - id: userProfile + UserProfileList{ + id: userProfileList + onUserIdChanged : { + userProfileList.updateDeviceList() + } + onDeviceListUpdated : { + modelDeviceList.deviceList = userProfileList + } } background: Item{ @@ -78,9 +74,27 @@ ApplicationWindow{ ScrollBar.horizontal.policy: ScrollBar.AlwaysOn ScrollBar.vertical.policy: ScrollBar.AlwaysOn - Label { - text: "ABC" - font.pixelSize: 700 + ListView{ + id: deviceList + anchors.fill: parent + clip: true + spacing: 10 + + model: UserProfileModel{ + id: modelDeviceList + } + + delegate: RowLayout{ + width: parent.width + Text{ + Layout.fillWidth: true + text: deviceID + } + Text{ + Layout.fillWidth: true + text: displayName + } + } } } diff --git a/src/Olm.cpp b/src/Olm.cpp index 1a7e9786f..4fb14ca64 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -56,7 +56,6 @@ handle_to_device_messages(const std::vectorwarn("validation error for olm message: {} {}", e.what(), j_msg.dump(2)); - } } else if (msg_type == to_string(mtx::events::EventType::RoomKeyRequest)) { @@ -398,7 +397,6 @@ handle_key_request_message(const mtx::events::DeviceEventdebug("ignoring all key requests for room {}", req.content.room_id); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index ec6af64cb..5ea8e2974 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "BlurhashProvider.h" #include "ChatPage.h" @@ -13,9 +14,11 @@ #include "MxcImageProvider.h" #include "UserSettingsPage.h" #include "dialogs/ImageOverlay.h" -#include "../ui/UserProfile.h" +#include "src/ui/UserProfile.h" +#include "src/ui/UserProfileModel.h" Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) +UserProfile deviceList; void TimelineViewManager::updateEncryptedDescriptions() @@ -73,8 +76,9 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin qmlRegisterType("im.nheko", 1, 0, "DelegateChoice"); qmlRegisterType("im.nheko", 1, 0, "DelegateChooser"); qmlRegisterType("im.nheko", 1, 0, "DeviceVerificationFlow"); - qmlRegisterType("im.nheko",1,0,"UserProfileContent"); - qRegisterMetaType(); + qmlRegisterType("im.nheko", 1, 0, "UserProfileModel"); + qmlRegisterType("im.nheko", 1, 0, "UserProfileList"); + qRegisterMetaType(); #ifdef USE_QUICK_VIEW @@ -97,6 +101,7 @@ TimelineViewManager::TimelineViewManager(QSharedPointer userSettin view->engine()->addImageProvider("colorimage", colorImgProvider); view->engine()->addImageProvider("blurhash", blurhashProvider); view->setSource(QUrl("qrc:///qml/TimelineView.qml")); + view->rootContext()->setContextProperty(QStringLiteral("devices"), &deviceList); connect(dynamic_cast(parent), &ChatPage::themeChanged, diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp index 30785699d..694a91015 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp @@ -2,29 +2,34 @@ #include "Logging.h" #include "Utils.h" #include "mtx/responses/crypto.hpp" -#include +#include // added only for debugging UserProfile::UserProfile(QObject *parent) : QObject(parent) {} QVector -UserProfile::getDeviceList(){ +UserProfile::getDeviceList() +{ UserProfile::fetchDeviceList(this->userId); return this->deviceList; } QString -UserProfile::getUserId (){ +UserProfile::getUserId() +{ return this->userId; } void -UserProfile::setUserId (const QString &user_id){ - if(this->userId != userId) +UserProfile::setUserId(const QString &user_id) +{ + if (this->userId != userId) return; - else + else { + emit UserProfile::userIdChanged(); this->userId = user_id; + } } void @@ -34,14 +39,15 @@ UserProfile::fetchDeviceList(const QString &userID) mtx::requests::QueryKeys req; mtx::responses::QueryKeys res; req.device_keys[userID.toStdString()] = {}; - + // to be removed + std::cout << json(req).dump(2) << std::endl; http::client()->query_keys( req, - [user_id = userID.toStdString(),this](const mtx::responses::QueryKeys &res, - mtx::http::RequestErr err) { + [user_id = userID.toStdString(), this](const mtx::responses::QueryKeys &res, + mtx::http::RequestErr err) { if (err) { - nhlog::net()->warn("failed to query device keys: {} {}", - err->matrix_error.error, + nhlog::net()->warn("failed to query device keys: {},{}", + err->matrix_error.errcode, static_cast(err->status_code)); return; } @@ -53,17 +59,16 @@ UserProfile::fetchDeviceList(const QString &userID) } auto devices = res.device_keys.at(user_id); - QVector deviceInfo; + for (const auto &d : devices) { auto device = d.second; // TODO: Verify signatures and ignore those that don't pass. - // std::cout<device_id = QString::fromStdString(d.first); - newdevice->display_name = QString::fromStdString(device.unsigned_info.device_display_name) + DeviceInfo newdevice( + QString::fromStdString(d.first), + QString::fromStdString(device.unsigned_info.device_display_name)); + QString::fromStdString(device.unsigned_info.device_display_name); deviceInfo.append(std::move(newdevice)); } @@ -74,7 +79,13 @@ UserProfile::fetchDeviceList(const QString &userID) return a.device_id > b.device_id; }); - this->deviceList = deviceInfo; - emit UserProfile::deviceListUpdated(); + this->deviceList = std::move(deviceInfo); + emit UserProfile::deviceListUpdated(); }); } + +void +UserProfile::updateDeviceList() +{ + fetchDeviceList(this->userId); +} diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h index bbf57c7b0..c37e23aed 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h @@ -2,33 +2,29 @@ #include #include +#include #include "MatrixClient.h" class DeviceInfo { public: - explicit DeviceInfo(QString device_id,QString display_name){ - this->device_id = device_id; - this->display_name = display_name; - } - ~DeviceInfo() = default; - DeviceInfo(const DeviceInfo &device){ - this->device_id = device.device_id; - this->display_name = device.display_name; - } + DeviceInfo(const QString deviceID, const QString displayName) + : device_id(deviceID) + , display_name(displayName) + {} + + DeviceInfo() {} QString device_id; QString display_name; }; -Q_DECLARE_METATYPE(DeviceInfo); class UserProfile : public QObject { Q_OBJECT + Q_PROPERTY(QString userId READ getUserId WRITE setUserId NOTIFY userIdChanged) Q_PROPERTY(QVector deviceList READ getDeviceList NOTIFY deviceListUpdated) - Q_PROPERTY(QString userId READ getUserId WRITE setUserId) - public: // constructor explicit UserProfile(QObject *parent = 0); @@ -39,8 +35,10 @@ class UserProfile : public QObject void setUserId(const QString &userId); Q_INVOKABLE void fetchDeviceList(const QString &userID); + Q_INVOKABLE void updateDeviceList(); signals: + void userIdChanged(); void deviceListUpdated(); private: diff --git a/src/ui/UserProfileModel.cpp b/src/ui/UserProfileModel.cpp new file mode 100644 index 000000000..ec0456cd9 --- /dev/null +++ b/src/ui/UserProfileModel.cpp @@ -0,0 +1,66 @@ +#include "UserProfileModel.h" +#include "UserProfile.h" +#include + +UserProfileModel::UserProfileModel(QObject *parent) + : QAbstractListModel(parent) + , deviceList(nullptr) +{} + +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() || !this->deviceList) + 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); + } + return QVariant(); +} + +QHash +UserProfileModel::roleNames() const +{ + QHash names; + names[DEVICEID] = "deviceID"; + names[DISPLAYNAME] = "displayName"; + return names; +} + +UserProfile * +UserProfileModel::getList() const +{ + return (this->deviceList); +} + +void +UserProfileModel::setList(UserProfile *devices) +{ + beginResetModel(); + + if (devices) + devices->disconnect(this); + + if (this->deviceList) { + const int index = this->deviceList->getDeviceList().size(); + beginInsertRows(QModelIndex(), index, index); + endInsertRows(); + } + + this->deviceList = devices; + + endResetModel(); +} \ No newline at end of file diff --git a/src/ui/UserProfileModel.h b/src/ui/UserProfileModel.h new file mode 100644 index 000000000..c21a806dd --- /dev/null +++ b/src/ui/UserProfileModel.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +class UserProfile; // forward declaration of the class UserProfile + +class UserProfileModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(UserProfile *deviceList READ getList WRITE setList) + +public: + explicit UserProfileModel(QObject *parent = nullptr); + + enum + { + DEVICEID, + DISPLAYNAME + }; + UserProfile *getList() const; + void setList(UserProfile *devices); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + virtual QHash roleNames() const override; + +private: + UserProfile *deviceList; +}; \ No newline at end of file