Add visualisation of the account's third party IDs in the account editor.

A category won't be shown if there are no relevant IDs (will add the ability to add new ones later).

Part of network/neochat#565

![image](/uploads/7da00b0b4acf90d145c09969ac2a91e1/image.png)
This commit is contained in:
James Graham
2024-04-14 16:37:34 +00:00
parent 1e24bde9a9
commit b7ee83f6b6
8 changed files with 190 additions and 1 deletions

View File

@@ -175,6 +175,8 @@ add_library(neochat STATIC
models/roomtreeitem.cpp models/roomtreeitem.cpp
models/roomtreeitem.h models/roomtreeitem.h
foreigntypes.h foreigntypes.h
models/threepidmodel.cpp
models/threepidmodel.h
) )
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES

View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include "threepidmodel.h"
#include "neochatconnection.h"
ThreePIdModel::ThreePIdModel(NeoChatConnection *connection)
: QAbstractListModel(connection)
{
Q_ASSERT(connection);
connect(connection, &NeoChatConnection::stateChanged, this, [this]() {
const auto connection = dynamic_cast<NeoChatConnection *>(this->parent());
if (connection != nullptr && connection->isLoggedIn()) {
const auto threePIdJob = connection->callApi<Quotient::GetAccount3PIDsJob>();
connect(threePIdJob, &Quotient::BaseJob::success, this, [this, threePIdJob]() {
beginResetModel();
m_threePIds = threePIdJob->threepids();
endResetModel();
});
}
});
}
QVariant ThreePIdModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return {};
}
if (index.row() >= rowCount()) {
qDebug() << "ThreePIdModel, something's wrong: index.row() >= m_threePIds.count()";
return {};
}
if (role == AddressRole) {
return m_threePIds.at(index.row()).address;
}
if (role == MediumRole) {
return m_threePIds.at(index.row()).medium;
}
return {};
}
int ThreePIdModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_threePIds.count();
}
QHash<int, QByteArray> ThreePIdModel::roleNames() const
{
return {
{AddressRole, QByteArrayLiteral("address")},
{MediumRole, QByteArrayLiteral("medium")},
};
}

View File

@@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <QAbstractListModel>
#include <QQmlEngine>
#include <Quotient/csapi/administrative_contact.h>
class NeoChatConnection;
/**
* @class ThreePIdModel
*
* This class defines the model for visualising an account's 3PIDs.
*/
class ThreePIdModel : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
/**
* @brief Defines the model roles.
*/
enum EventRoles {
AddressRole = Qt::DisplayRole, /**< The third-party identifier address. */
MediumRole, /**< The medium of the third-party identifier. One of: [email, msisdn]. */
};
explicit ThreePIdModel(NeoChatConnection *parent);
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
[[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
/**
* @brief Number of rows in the model.
*
* @sa QAbstractItemModel::rowCount
*/
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a mapping from Role enum values to role names.
*
* @sa EventRoles, QAbstractItemModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
private:
QVector<Quotient::GetAccount3PIDsJob::ThirdPartyIdentifier> m_threePIds;
};

View File

@@ -16,6 +16,7 @@
#include "spacehierarchycache.h" #include "spacehierarchycache.h"
#include <Quotient/connection.h> #include <Quotient/connection.h>
#include <Quotient/jobs/basejob.h>
#include <Quotient/quotient_common.h> #include <Quotient/quotient_common.h>
#include <qt6keychain/keychain.h> #include <qt6keychain/keychain.h>
@@ -41,12 +42,14 @@ using namespace Qt::StringLiterals;
NeoChatConnection::NeoChatConnection(QObject *parent) NeoChatConnection::NeoChatConnection(QObject *parent)
: Connection(parent) : Connection(parent)
, m_threePIdModel(new ThreePIdModel(this))
{ {
connectSignals(); connectSignals();
} }
NeoChatConnection::NeoChatConnection(const QUrl &server, QObject *parent) NeoChatConnection::NeoChatConnection(const QUrl &server, QObject *parent)
: Connection(server, parent) : Connection(server, parent)
, m_threePIdModel(new ThreePIdModel(this))
{ {
connectSignals(); connectSignals();
} }
@@ -248,6 +251,11 @@ void NeoChatConnection::deactivateAccount(const QString &password)
}); });
} }
ThreePIdModel *NeoChatConnection::threePIdModel() const
{
return m_threePIdModel;
}
void NeoChatConnection::createRoom(const QString &name, const QString &topic, const QString &parent, bool setChildParent) void NeoChatConnection::createRoom(const QString &name, const QString &topic, const QString &parent, bool setChildParent)
{ {
QList<CreateRoomJob::StateEvent> initialStateEvents; QList<CreateRoomJob::StateEvent> initialStateEvents;

View File

@@ -9,6 +9,8 @@
#include <QCoroTask> #include <QCoroTask>
#include <Quotient/connection.h> #include <Quotient/connection.h>
#include "models/threepidmodel.h"
class LinkPreviewer; class LinkPreviewer;
class NeoChatConnection : public Quotient::Connection class NeoChatConnection : public Quotient::Connection
@@ -29,6 +31,11 @@ class NeoChatConnection : public Quotient::Connection
Q_PROPERTY(QString deviceKey READ deviceKey CONSTANT) Q_PROPERTY(QString deviceKey READ deviceKey CONSTANT)
Q_PROPERTY(QString encryptionKey READ encryptionKey CONSTANT) Q_PROPERTY(QString encryptionKey READ encryptionKey CONSTANT)
/**
* @brief The model with the account's 3PIDs.
*/
Q_PROPERTY(ThreePIdModel *threePIdModel READ threePIdModel CONSTANT)
/** /**
* @brief The total number of notifications for all direct chats. * @brief The total number of notifications for all direct chats.
*/ */
@@ -96,6 +103,8 @@ public:
Q_INVOKABLE void deactivateAccount(const QString &password); Q_INVOKABLE void deactivateAccount(const QString &password);
ThreePIdModel *threePIdModel() const;
/** /**
* @brief Create new room for a group chat. * @brief Create new room for a group chat.
*/ */
@@ -167,6 +176,8 @@ private:
bool m_isOnline = true; bool m_isOnline = true;
void setIsOnline(bool isOnline); void setIsOnline(bool isOnline);
ThreePIdModel *m_threePIdModel;
void connectSignals(); void connectSignals();
int m_badgeNotificationCount = 0; int m_badgeNotificationCount = 0;

View File

@@ -11,6 +11,7 @@ import QtQuick.Window
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kirigamiaddons.components as KirigamiComponents import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.neochat import org.kde.neochat
FormCard.FormCardPage { FormCard.FormCardPage {
@@ -195,7 +196,16 @@ FormCard.FormCardPage {
} }
} }
} }
ThreePIdCard {
connection: root.connection
title: i18n("Email Addresses")
medium: "email"
}
ThreePIdCard {
connection: root.connection
title: i18n("Phone Numbers")
medium: "msisdn"
}
FormCard.FormHeader { FormCard.FormHeader {
Layout.fillWidth: true Layout.fillWidth: true
title: i18n("Server Information") title: i18n("Server Information")

View File

@@ -32,4 +32,5 @@ qt_add_qml_module(settings
IgnoredUsersDialog.qml IgnoredUsersDialog.qml
NotificationRuleItem.qml NotificationRuleItem.qml
ThemeRadioButton.qml ThemeRadioButton.qml
ThreePIdCard.qml
) )

View File

@@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.kitemmodels
import org.kde.neochat
ColumnLayout {
id: root
required property NeoChatConnection connection
required property string title
required property string medium
visible: deviceRepeater.count > 0
FormCard.FormHeader {
title: root.title
}
FormCard.FormCard {
id: devicesCard
Repeater {
id: deviceRepeater
model: KSortFilterProxyModel {
sourceModel: root.connection.threePIdModel
filterRoleName: "medium"
filterString: root.medium
}
delegate: FormCard.FormTextDelegate {
required property string address
text: address
}
}
}
}