Compare commits
1 Commits
master
...
work/redst
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db2238805b |
@@ -23,6 +23,11 @@ Kirigami.Dialog {
|
|||||||
|
|
||||||
property NeoChatConnection connection
|
property NeoChatConnection connection
|
||||||
|
|
||||||
|
readonly property ProfileFieldsHelper profileFieldsHelper: ProfileFieldsHelper {
|
||||||
|
connection: root.connection
|
||||||
|
userId: root.user.id
|
||||||
|
}
|
||||||
|
|
||||||
leftPadding: 0
|
leftPadding: 0
|
||||||
rightPadding: 0
|
rightPadding: 0
|
||||||
topPadding: 0
|
topPadding: 0
|
||||||
@@ -126,14 +131,38 @@ Kirigami.Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Kirigami.Chip {
|
RowLayout {
|
||||||
visible: root.room
|
spacing: Kirigami.Units.smallSpacing
|
||||||
text: root.room ? QmlUtils.nameForPowerLevelValue(root.room.memberEffectivePowerLevel(root.user.id)) : ""
|
|
||||||
closable: false
|
|
||||||
checkable: false
|
|
||||||
|
|
||||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||||
|
|
||||||
|
Kirigami.Chip {
|
||||||
|
visible: root.room
|
||||||
|
text: root.room ? QmlUtils.nameForPowerLevelValue(root.room.memberEffectivePowerLevel(root.user.id)) : ""
|
||||||
|
closable: false
|
||||||
|
checkable: false
|
||||||
|
}
|
||||||
|
|
||||||
|
QQC2.BusyIndicator {
|
||||||
|
visible: root.connection.supportsProfileFields && root.profileFieldsHelper.loading
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Chip {
|
||||||
|
id: timezoneChip
|
||||||
|
visible: root.connection.supportsProfileFields && !root.profileFieldsHelper.loading && root.profileFieldsHelper.timezone.length > 0
|
||||||
|
text: root.profileFieldsHelper.timezone
|
||||||
|
closable: false
|
||||||
|
checkable: false
|
||||||
|
}
|
||||||
|
|
||||||
|
Kirigami.Chip {
|
||||||
|
id: pronounsChip
|
||||||
|
visible: root.connection.supportsProfileFields && !root.profileFieldsHelper.loading && root.profileFieldsHelper.pronouns.length > 0
|
||||||
|
text: root.profileFieldsHelper.pronouns
|
||||||
|
closable: false
|
||||||
|
checkable: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Kirigami.Separator {
|
Kirigami.Separator {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ target_sources(LibNeoChat PRIVATE
|
|||||||
texthandler.cpp
|
texthandler.cpp
|
||||||
urlhelper.cpp
|
urlhelper.cpp
|
||||||
utils.cpp
|
utils.cpp
|
||||||
|
profilefieldshelper.cpp
|
||||||
enums/messagecomponenttype.h
|
enums/messagecomponenttype.h
|
||||||
enums/messagetype.h
|
enums/messagetype.h
|
||||||
enums/powerlevel.cpp
|
enums/powerlevel.cpp
|
||||||
@@ -32,6 +33,7 @@ target_sources(LibNeoChat PRIVATE
|
|||||||
events/imagepackevent.cpp
|
events/imagepackevent.cpp
|
||||||
events/pollevent.cpp
|
events/pollevent.cpp
|
||||||
jobs/neochatgetcommonroomsjob.cpp
|
jobs/neochatgetcommonroomsjob.cpp
|
||||||
|
jobs/neochatprofilefieldjobs.cpp
|
||||||
models/actionsmodel.cpp
|
models/actionsmodel.cpp
|
||||||
models/completionmodel.cpp
|
models/completionmodel.cpp
|
||||||
models/completionproxymodel.cpp
|
models/completionproxymodel.cpp
|
||||||
@@ -44,6 +46,8 @@ target_sources(LibNeoChat PRIVATE
|
|||||||
models/stickermodel.cpp
|
models/stickermodel.cpp
|
||||||
models/userfiltermodel.cpp
|
models/userfiltermodel.cpp
|
||||||
models/userlistmodel.cpp
|
models/userlistmodel.cpp
|
||||||
|
models/timezonemodel.cpp
|
||||||
|
models/timezonemodel.h
|
||||||
)
|
)
|
||||||
|
|
||||||
ecm_add_qml_module(LibNeoChat GENERATE_PLUGIN_SOURCE
|
ecm_add_qml_module(LibNeoChat GENERATE_PLUGIN_SOURCE
|
||||||
|
|||||||
20
src/libneochat/jobs/neochatprofilefieldjobs.cpp
Normal file
20
src/libneochat/jobs/neochatprofilefieldjobs.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "neochatprofilefieldjobs.h"
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
NeoChatGetProfileFieldJob::NeoChatGetProfileFieldJob(const QString &userId, const QString &key)
|
||||||
|
: BaseJob(HttpVerb::Get, u"GetProfileFieldJob"_s, makePath("/_matrix/client/unstable/uk.tcpip.msc4133", "/profile/", userId, "/", key))
|
||||||
|
, m_key(key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NeoChatSetProfileFieldJob::NeoChatSetProfileFieldJob(const QString &userId, const QString &key, const QString &value)
|
||||||
|
: BaseJob(HttpVerb::Put, u"SetProfileFieldJob"_s, makePath("/_matrix/client/unstable/uk.tcpip.msc4133", "/profile/", userId, "/", key))
|
||||||
|
{
|
||||||
|
QJsonObject _dataJson;
|
||||||
|
addParam(_dataJson, key, value);
|
||||||
|
setRequestData({_dataJson});
|
||||||
|
}
|
||||||
49
src/libneochat/jobs/neochatprofilefieldjobs.h
Normal file
49
src/libneochat/jobs/neochatprofilefieldjobs.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Quotient/jobs/basejob.h>
|
||||||
|
|
||||||
|
// NOTE: This is currently being upstreamed to libQuotient, awaiting MSC4133: https://github.com/quotient-im/libQuotient/pull/869
|
||||||
|
|
||||||
|
//! \brief Get a user's profile field.
|
||||||
|
//!
|
||||||
|
//! Get one of the user's profile fields. This API may be used to fetch the user's
|
||||||
|
//! own profile field or to query the profile field of other users; either locally or
|
||||||
|
//! on remote homeservers.
|
||||||
|
class QUOTIENT_API NeoChatGetProfileFieldJob : public Quotient::BaseJob
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! \param userId
|
||||||
|
//! The user whose profile field to query.
|
||||||
|
//! \param key
|
||||||
|
//! The key of the profile field.
|
||||||
|
explicit NeoChatGetProfileFieldJob(const QString &userId, const QString &key);
|
||||||
|
|
||||||
|
// Result properties
|
||||||
|
|
||||||
|
//! The value of the profile field.
|
||||||
|
QString value() const
|
||||||
|
{
|
||||||
|
return loadFromJson<QString>(m_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief Sets a user's profile field.
|
||||||
|
//!
|
||||||
|
//! Set one of the user's own profile fields. This may fail depending on if the server allows the
|
||||||
|
//! user to change their own profile field, or if the field isn't allowed.
|
||||||
|
class QUOTIENT_API NeoChatSetProfileFieldJob : public Quotient::BaseJob
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! \param userId
|
||||||
|
//! The user whose avatar URL to set.
|
||||||
|
//!
|
||||||
|
//! \param avatarUrl
|
||||||
|
//! The new avatar URL for this user.
|
||||||
|
explicit NeoChatSetProfileFieldJob(const QString &userId, const QString &key, const QString &value);
|
||||||
|
};
|
||||||
48
src/libneochat/models/timezonemodel.cpp
Normal file
48
src/libneochat/models/timezonemodel.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "timezonemodel.h"
|
||||||
|
|
||||||
|
#include <KLocalizedString>
|
||||||
|
|
||||||
|
using namespace Qt::Literals::StringLiterals;
|
||||||
|
|
||||||
|
TimeZoneModel::TimeZoneModel(QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
m_timezoneIds = QTimeZone::availableTimeZoneIds();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TimeZoneModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole: {
|
||||||
|
if (index.row() == 0) {
|
||||||
|
return i18nc("@item:inlistbox Prefer not to say which timezone im in", "Prefer not to say");
|
||||||
|
} else {
|
||||||
|
return m_timezoneIds[index.row() - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimeZoneModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
|
||||||
|
return m_timezoneIds.count() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TimeZoneModel::indexOfValue(const QString &code)
|
||||||
|
{
|
||||||
|
const auto it = std::ranges::find(std::as_const(m_timezoneIds), code.toUtf8());
|
||||||
|
if (it != m_timezoneIds.cend()) {
|
||||||
|
return std::distance(m_timezoneIds.cbegin(), it) + 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_timezonemodel.cpp"
|
||||||
24
src/libneochat/models/timezonemodel.h
Normal file
24
src/libneochat/models/timezonemodel.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
class TimeZoneModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit TimeZoneModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
[[nodiscard]] int rowCount(const QModelIndex &parent) const override;
|
||||||
|
|
||||||
|
Q_INVOKABLE int indexOfValue(const QString &code);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<QByteArray> m_timezoneIds;
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
#include "jobs/neochatprofilefieldjobs.h"
|
||||||
#include "neochatroom.h"
|
#include "neochatroom.h"
|
||||||
#include "spacehierarchycache.h"
|
#include "spacehierarchycache.h"
|
||||||
|
|
||||||
@@ -139,6 +140,19 @@ void NeoChatConnection::connectSignals()
|
|||||||
Q_EMIT canCheckMutualRoomsChanged();
|
Q_EMIT canCheckMutualRoomsChanged();
|
||||||
m_canEraseData = job->unstableFeatures().contains("org.matrix.msc4025"_L1) || job->versions().count("v1.10"_L1);
|
m_canEraseData = job->unstableFeatures().contains("org.matrix.msc4025"_L1) || job->versions().count("v1.10"_L1);
|
||||||
Q_EMIT canEraseDataChanged();
|
Q_EMIT canEraseDataChanged();
|
||||||
|
m_supportsProfileFields = job->unstableFeatures().contains("uk.tcpip.msc4133"_L1);
|
||||||
|
Q_EMIT supportsProfileFieldsChanged();
|
||||||
|
|
||||||
|
if (m_supportsProfileFields) {
|
||||||
|
callApi<NeoChatGetProfileFieldJob>(BackgroundRequest, userId(), QStringLiteral("us.cloke.msc4175.tz")).then([this](const auto &job) {
|
||||||
|
m_timezone = job->value();
|
||||||
|
Q_EMIT timezoneChanged();
|
||||||
|
});
|
||||||
|
callApi<NeoChatGetProfileFieldJob>(BackgroundRequest, userId(), QStringLiteral("io.fsky.nyx.pronouns")).then([this](const auto &job) {
|
||||||
|
m_pronouns = job->value();
|
||||||
|
Q_EMIT pronounsChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Qt::SingleShotConnection);
|
Qt::SingleShotConnection);
|
||||||
@@ -558,4 +572,33 @@ bool NeoChatConnection::enablePushNotifications() const
|
|||||||
return m_pushNotificationsEnabled;
|
return m_pushNotificationsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NeoChatConnection::supportsProfileFields() const
|
||||||
|
{
|
||||||
|
return m_supportsProfileFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NeoChatConnection::timezone() const
|
||||||
|
{
|
||||||
|
return m_timezone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeoChatConnection::setTimezone(const QString &value)
|
||||||
|
{
|
||||||
|
callApi<NeoChatSetProfileFieldJob>(BackgroundRequest, userId(), QStringLiteral("us.cloke.msc4175.tz"), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString NeoChatConnection::pronouns() const
|
||||||
|
{
|
||||||
|
return m_pronouns;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeoChatConnection::setPronouns(const QString &value)
|
||||||
|
{
|
||||||
|
const QJsonObject pronounsObj{{"summary"_L1, value}};
|
||||||
|
callApi<NeoChatSetProfileFieldJob>(BackgroundRequest,
|
||||||
|
userId(),
|
||||||
|
QStringLiteral("io.fsky.nyx.pronouns"),
|
||||||
|
QString::fromUtf8(QJsonDocument(pronounsObj).toJson(QJsonDocument::Compact)));
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_neochatconnection.cpp"
|
#include "moc_neochatconnection.cpp"
|
||||||
|
|||||||
@@ -90,6 +90,21 @@ class NeoChatConnection : public Quotient::Connection
|
|||||||
*/
|
*/
|
||||||
Q_PROPERTY(bool enablePushNotifications READ enablePushNotifications NOTIFY enablePushNotificationsChanged)
|
Q_PROPERTY(bool enablePushNotifications READ enablePushNotifications NOTIFY enablePushNotificationsChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief If the server supports profile fields (MSC4133)
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool supportsProfileFields READ supportsProfileFields NOTIFY supportsProfileFieldsChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The timezone profile field for this account.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString timezone READ timezone WRITE setTimezone NOTIFY timezoneChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The pronouns profile field for this account.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString pronouns READ pronouns WRITE setPronouns NOTIFY pronounsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Defines the status after an attempt to change the password on an account.
|
* @brief Defines the status after an attempt to change the password on an account.
|
||||||
@@ -204,6 +219,14 @@ public:
|
|||||||
bool pushNotificationsAvailable() const;
|
bool pushNotificationsAvailable() const;
|
||||||
bool enablePushNotifications() const;
|
bool enablePushNotifications() const;
|
||||||
|
|
||||||
|
bool supportsProfileFields() const;
|
||||||
|
|
||||||
|
QString timezone() const;
|
||||||
|
void setTimezone(const QString &value);
|
||||||
|
|
||||||
|
QString pronouns() const;
|
||||||
|
void setPronouns(const QString &value);
|
||||||
|
|
||||||
LinkPreviewer *previewerForLink(const QUrl &link);
|
LinkPreviewer *previewerForLink(const QUrl &link);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
@@ -221,6 +244,9 @@ Q_SIGNALS:
|
|||||||
void canCheckMutualRoomsChanged();
|
void canCheckMutualRoomsChanged();
|
||||||
void canEraseDataChanged();
|
void canEraseDataChanged();
|
||||||
void enablePushNotificationsChanged();
|
void enablePushNotificationsChanged();
|
||||||
|
void supportsProfileFieldsChanged();
|
||||||
|
void timezoneChanged();
|
||||||
|
void pronounsChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Request a message be shown to the user of the given type.
|
* @brief Request a message be shown to the user of the given type.
|
||||||
@@ -250,4 +276,7 @@ private:
|
|||||||
bool m_canCheckMutualRooms = false;
|
bool m_canCheckMutualRooms = false;
|
||||||
bool m_canEraseData = false;
|
bool m_canEraseData = false;
|
||||||
bool m_pushNotificationsEnabled = false;
|
bool m_pushNotificationsEnabled = false;
|
||||||
|
bool m_supportsProfileFields = false;
|
||||||
|
QString m_timezone;
|
||||||
|
QString m_pronouns;
|
||||||
};
|
};
|
||||||
|
|||||||
110
src/libneochat/profilefieldshelper.cpp
Normal file
110
src/libneochat/profilefieldshelper.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#include "profilefieldshelper.h"
|
||||||
|
#include "jobs/neochatprofilefieldjobs.h"
|
||||||
|
#include "neochatconnection.h"
|
||||||
|
|
||||||
|
#include <Quotient/csapi/profile.h>
|
||||||
|
|
||||||
|
using namespace Quotient;
|
||||||
|
|
||||||
|
NeoChatConnection *ProfileFieldsHelper::connection() const
|
||||||
|
{
|
||||||
|
return m_connection.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileFieldsHelper::setConnection(NeoChatConnection *connection)
|
||||||
|
{
|
||||||
|
if (m_connection != connection) {
|
||||||
|
m_connection = connection;
|
||||||
|
Q_EMIT connectionChanged();
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileFieldsHelper::userId() const
|
||||||
|
{
|
||||||
|
return m_userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileFieldsHelper::setUserId(const QString &id)
|
||||||
|
{
|
||||||
|
if (m_userId != id) {
|
||||||
|
m_userId = id;
|
||||||
|
Q_EMIT userIdChanged();
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileFieldsHelper::timezone() const
|
||||||
|
{
|
||||||
|
if (m_timezone.isEmpty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return QTimeZone(m_timezone.toUtf8()).displayName(QTimeZone::GenericTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileFieldsHelper::pronouns() const
|
||||||
|
{
|
||||||
|
return m_pronouns;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProfileFieldsHelper::loading() const
|
||||||
|
{
|
||||||
|
return m_loading;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileFieldsHelper::load()
|
||||||
|
{
|
||||||
|
if (!m_connection || m_userId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_connection->supportsProfileFields()) {
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
m_connection->callApi<NeoChatGetProfileFieldJob>(BackgroundRequest, m_userId, QStringLiteral("us.cloke.msc4175.tz"))
|
||||||
|
.then(
|
||||||
|
[this](const auto &job) {
|
||||||
|
m_timezone = job->value();
|
||||||
|
Q_EMIT timezoneChanged();
|
||||||
|
m_fetchedTimezone = true;
|
||||||
|
checkIfFinished();
|
||||||
|
},
|
||||||
|
[this] {
|
||||||
|
m_fetchedTimezone = true;
|
||||||
|
checkIfFinished();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_connection->callApi<NeoChatGetProfileFieldJob>(BackgroundRequest, m_userId, QStringLiteral("io.fsky.nyx.pronouns"))
|
||||||
|
.then(
|
||||||
|
[this](const auto &job) {
|
||||||
|
const QJsonDocument document = QJsonDocument::fromJson(job->value().toUtf8());
|
||||||
|
m_pronouns = document["summary"_L1].toString();
|
||||||
|
Q_EMIT pronounsChanged();
|
||||||
|
m_fetchedPronouns = true;
|
||||||
|
checkIfFinished();
|
||||||
|
},
|
||||||
|
[this] {
|
||||||
|
m_fetchedPronouns = true;
|
||||||
|
checkIfFinished();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileFieldsHelper::checkIfFinished()
|
||||||
|
{
|
||||||
|
if (m_fetchedTimezone && m_fetchedPronouns) {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProfileFieldsHelper::setLoading(const bool loading)
|
||||||
|
{
|
||||||
|
m_loading = loading;
|
||||||
|
Q_EMIT loadingChanged();
|
||||||
|
}
|
||||||
79
src/libneochat/profilefieldshelper.h
Normal file
79
src/libneochat/profilefieldshelper.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include <Quotient/jobs/basejob.h>
|
||||||
|
|
||||||
|
class NeoChatConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class ProfileFieldsHelper
|
||||||
|
*
|
||||||
|
* This class is designed to help grabbing the profile fields of a user.
|
||||||
|
*/
|
||||||
|
class ProfileFieldsHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The connection to use.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged REQUIRED)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The id of the user to grab profile fields from.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged REQUIRED)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The timezone field of the user.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString timezone READ timezone NOTIFY timezoneChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The pronouns field of the user.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(QString pronouns READ pronouns NOTIFY pronounsChanged)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief If the fields are loading.
|
||||||
|
*/
|
||||||
|
Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] NeoChatConnection *connection() const;
|
||||||
|
void setConnection(NeoChatConnection *connection);
|
||||||
|
|
||||||
|
[[nodiscard]] QString userId() const;
|
||||||
|
void setUserId(const QString &id);
|
||||||
|
|
||||||
|
[[nodiscard]] QString timezone() const;
|
||||||
|
[[nodiscard]] QString pronouns() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool loading() const;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void connectionChanged();
|
||||||
|
void userIdChanged();
|
||||||
|
void timezoneChanged();
|
||||||
|
void pronounsChanged();
|
||||||
|
void loadingChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void load();
|
||||||
|
void checkIfFinished();
|
||||||
|
void setLoading(bool loading);
|
||||||
|
|
||||||
|
QPointer<NeoChatConnection> m_connection;
|
||||||
|
QString m_userId;
|
||||||
|
bool m_loading = true;
|
||||||
|
QString m_timezone;
|
||||||
|
bool m_fetchedTimezone = false;
|
||||||
|
QString m_pronouns;
|
||||||
|
bool m_fetchedPronouns = false;
|
||||||
|
};
|
||||||
@@ -115,6 +115,39 @@ FormCard.FormCardPage {
|
|||||||
text: root.connection ? root.connection.label : ""
|
text: root.connection ? root.connection.label : ""
|
||||||
}
|
}
|
||||||
FormCard.FormDelegateSeparator {}
|
FormCard.FormDelegateSeparator {}
|
||||||
|
FormCard.FormComboBoxDelegate {
|
||||||
|
id: timezoneLabel
|
||||||
|
|
||||||
|
property string textValue: root.connection ? root.connection.timezone : ""
|
||||||
|
|
||||||
|
visible: root.connection.supportsProfileFields
|
||||||
|
enabled: root.connection.canChangeProfileFields && root.connection.profileFieldAllowed("us.cloke.msc4175.tz")
|
||||||
|
text: i18nc("@label:combobox", "Timezone:")
|
||||||
|
model: TimeZoneModel {}
|
||||||
|
textRole: "display"
|
||||||
|
valueRole: "display"
|
||||||
|
onActivated: index => {
|
||||||
|
// "Prefer not to say" choice clears it.
|
||||||
|
if (index === 0) {
|
||||||
|
textValue = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, set it to the text value which is the IANA identifier
|
||||||
|
textValue = timezoneLabel.currentValue;
|
||||||
|
}
|
||||||
|
Component.onCompleted: currentIndex = model.indexOfValue(textValue)
|
||||||
|
}
|
||||||
|
FormCard.FormDelegateSeparator {}
|
||||||
|
FormCard.FormTextFieldDelegate {
|
||||||
|
id: pronounsLabel
|
||||||
|
visible: root.connection.supportsProfileFields
|
||||||
|
enabled: root.connection.canChangeProfileFields && root.connection.profileFieldAllowed("io.fsky.nyx.pronouns")
|
||||||
|
label: i18nc("@label:textbox", "Pronouns:")
|
||||||
|
placeholderText: i18nc("@placeholder", "she/her")
|
||||||
|
text: root.connection ? root.connection.pronouns : ""
|
||||||
|
}
|
||||||
|
FormCard.FormDelegateSeparator {}
|
||||||
FormCard.FormButtonDelegate {
|
FormCard.FormButtonDelegate {
|
||||||
text: i18nc("@action:button", "Show QR Code")
|
text: i18nc("@action:button", "Show QR Code")
|
||||||
icon.name: "view-barcode-qr-symbolic"
|
icon.name: "view-barcode-qr-symbolic"
|
||||||
@@ -146,6 +179,12 @@ FormCard.FormCardPage {
|
|||||||
if (root.connection.label !== accountLabel.text) {
|
if (root.connection.label !== accountLabel.text) {
|
||||||
root.connection.label = accountLabel.text;
|
root.connection.label = accountLabel.text;
|
||||||
}
|
}
|
||||||
|
if (root.connection.timezone !== timezoneLabel.textValue) {
|
||||||
|
root.connection.timezone = timezoneLabel.textValue;
|
||||||
|
}
|
||||||
|
if (root.connection.pronouns !== pronounsLabel.text) {
|
||||||
|
root.connection.pronouns = pronounsLabel.text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user