Port some things away from Controller::activeConnection

This commit is contained in:
Tobias Fella
2023-11-04 23:26:41 +01:00
parent ff4cf86ea5
commit 0e55c3b38f
29 changed files with 289 additions and 154 deletions

View File

@@ -99,10 +99,6 @@ Controller::Controller(QObject *parent)
} }
oldAccountCount = m_accountRegistry.size(); oldAccountCount = m_accountRegistry.size();
}); });
QTimer::singleShot(0, this, [this] {
m_pushRuleModel = new PushRuleModel;
});
} }
Controller &Controller::instance() Controller &Controller::instance()
@@ -353,11 +349,6 @@ void Controller::setActiveConnection(NeoChatConnection *connection)
Q_EMIT activeConnectionIndexChanged(); Q_EMIT activeConnectionIndexChanged();
} }
PushRuleModel *Controller::pushRuleModel() const
{
return m_pushRuleModel;
}
void Controller::saveWindowGeometry() void Controller::saveWindowGeometry()
{ {
WindowController::instance().saveGeometry(); WindowController::instance().saveGeometry();

View File

@@ -3,7 +3,6 @@
#pragma once #pragma once
#include "models/pushrulemodel.h"
#include <QObject> #include <QObject>
#include <QQmlEngine> #include <QQmlEngine>
#include <QQuickItem> #include <QQuickItem>
@@ -47,11 +46,6 @@ class Controller : public QObject
*/ */
Q_PROPERTY(NeoChatConnection *activeConnection READ activeConnection WRITE setActiveConnection NOTIFY activeConnectionChanged) Q_PROPERTY(NeoChatConnection *activeConnection READ activeConnection WRITE setActiveConnection NOTIFY activeConnectionChanged)
/**
* @brief The PushRuleModel that has the active connection's push rules.
*/
Q_PROPERTY(PushRuleModel *pushRuleModel READ pushRuleModel CONSTANT)
/** /**
* @brief The row number in the accounts directory of the active connection. * @brief The row number in the accounts directory of the active connection.
*/ */
@@ -95,8 +89,6 @@ public:
void setActiveConnection(NeoChatConnection *connection); void setActiveConnection(NeoChatConnection *connection);
[[nodiscard]] NeoChatConnection *activeConnection() const; [[nodiscard]] NeoChatConnection *activeConnection() const;
[[nodiscard]] PushRuleModel *pushRuleModel() const;
/** /**
* @brief Add a new connection to the account registry. * @brief Add a new connection to the account registry.
*/ */
@@ -154,7 +146,6 @@ private:
bool m_isOnline = true; bool m_isOnline = true;
QMap<Quotient::Room *, int> m_notificationCounts; QMap<Quotient::Room *, int> m_notificationCounts;
QPointer<PushRuleModel> m_pushRuleModel;
Quotient::AccountRegistry m_accountRegistry; Quotient::AccountRegistry m_accountRegistry;
private Q_SLOTS: private Q_SLOTS:

View File

@@ -13,11 +13,13 @@
#include <KLocalizedString> #include <KLocalizedString>
#include "controller.h" #include "controller.h"
#include "neochatconnection.h"
#include <Quotient/connection.h> #include <Quotient/connection.h>
using namespace Quotient; using namespace Quotient;
ThumbnailResponse::ThumbnailResponse(QString id, QSize size) ThumbnailResponse::ThumbnailResponse(QString id, QSize size, NeoChatConnection *connection)
: mediaId(std::move(id)) : mediaId(std::move(id))
, requestedSize(size) , requestedSize(size)
, localFile(QStringLiteral("%1/image_provider/%2-%3x%4.png") , localFile(QStringLiteral("%1/image_provider/%2-%3x%4.png")
@@ -25,6 +27,7 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size)
mediaId, mediaId,
QString::number(requestedSize.width()), QString::number(requestedSize.width()),
QString::number(requestedSize.height()))) QString::number(requestedSize.height())))
, m_connection(connection)
, errorStr("Image request hasn't started"_ls) , errorStr("Image request hasn't started"_ls)
{ {
if (requestedSize.isEmpty()) { if (requestedSize.isEmpty()) {
@@ -51,24 +54,24 @@ ThumbnailResponse::ThumbnailResponse(QString id, QSize size)
return; return;
} }
if (!Controller::instance().activeConnection()) { if (!m_connection) {
qWarning() << "Current connection is null"; qWarning() << "Current connection is null";
return; return;
} }
// Execute a request on the main thread asynchronously // Execute a request on the main thread asynchronously
moveToThread(Controller::instance().activeConnection()->thread()); moveToThread(m_connection->thread());
QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest, Qt::QueuedConnection); QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest, Qt::QueuedConnection);
} }
void ThumbnailResponse::startRequest() void ThumbnailResponse::startRequest()
{ {
if (!Controller::instance().activeConnection()) { if (!m_connection) {
return; return;
} }
// Runs in the main thread, not QML thread // Runs in the main thread, not QML thread
Q_ASSERT(QThread::currentThread() == Controller::instance().activeConnection()->thread()); Q_ASSERT(QThread::currentThread() == m_connection->thread());
job = Controller::instance().activeConnection()->getThumbnail(mediaId, requestedSize); job = m_connection->getThumbnail(mediaId, requestedSize);
// Connect to any possible outcome including abandonment // Connect to any possible outcome including abandonment
// to make sure the QML thread is not left stuck forever. // to make sure the QML thread is not left stuck forever.
connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult); connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult);
@@ -118,7 +121,7 @@ QString ThumbnailResponse::errorString() const
QQuickImageResponse *MatrixImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize) QQuickImageResponse *MatrixImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{ {
return new ThumbnailResponse(id, requestedSize); return new ThumbnailResponse(id, requestedSize, m_connection);
} }
#include "moc_matriximageprovider.cpp" #include "moc_matriximageprovider.cpp"

View File

@@ -10,6 +10,8 @@
#include <QReadWriteLock> #include <QReadWriteLock>
class NeoChatConnection;
/** /**
* @class ThumbnailResponse * @class ThumbnailResponse
* *
@@ -21,7 +23,7 @@ class ThumbnailResponse : public QQuickImageResponse
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ThumbnailResponse(QString mediaId, QSize requestedSize); explicit ThumbnailResponse(QString mediaId, QSize requestedSize, NeoChatConnection *m_connection);
~ThumbnailResponse() override = default; ~ThumbnailResponse() override = default;
private Q_SLOTS: private Q_SLOTS:
@@ -33,6 +35,7 @@ private:
QSize requestedSize; QSize requestedSize;
const QString localFile; const QString localFile;
Quotient::MediaThumbnailJob *job = nullptr; Quotient::MediaThumbnailJob *job = nullptr;
NeoChatConnection *m_connection;
QImage image; QImage image;
QString errorStr; QString errorStr;
@@ -51,6 +54,11 @@ private:
*/ */
class MatrixImageProvider : public QQuickAsyncImageProvider class MatrixImageProvider : public QQuickAsyncImageProvider
{ {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(NeoChatConnection *connection MEMBER m_connection)
public: public:
/** /**
* @brief Return a job to provide the image with the given ID. * @brief Return a job to provide the image with the given ID.
@@ -58,4 +66,7 @@ public:
* @sa QQuickAsyncImageProvider::requestImageResponse * @sa QQuickAsyncImageProvider::requestImageResponse
*/ */
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override; QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
private:
NeoChatConnection *m_connection = nullptr;
}; };

View File

@@ -261,7 +261,7 @@ QList<ActionsModel::Action> actions{
return QString(); return QString();
} }
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "Knocking room %1.", text)); Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("Knocking room <roomname>.", "Knocking room %1.", text));
auto connection = Controller::instance().activeConnection(); auto connection = room->connection();
const auto knownServer = roomName.mid(roomName.indexOf(":"_ls) + 1); const auto knownServer = roomName.mid(roomName.indexOf(":"_ls) + 1);
if (parts.length() >= 2) { if (parts.length() >= 2) {
RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer}); RoomManager::instance().knockRoom(connection, roomName, parts[1], QStringList{knownServer});
@@ -285,7 +285,7 @@ QList<ActionsModel::Action> actions{
i18nc("'<text>' does not look like a room id or alias.", "'%1' does not look like a room id or alias.", text)); i18nc("'<text>' does not look like a room id or alias.", "'%1' does not look like a room id or alias.", text));
return QString(); return QString();
} }
if (Controller::instance().activeConnection()->room(text) || Controller::instance().activeConnection()->roomByAlias(text)) { if (room->connection()->room(text) || room->connection()->roomByAlias(text)) {
Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("You are already in room <roomname>.", "You are already in room %1.", text)); Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc("You are already in room <roomname>.", "You are already in room %1.", text));
return QString(); return QString();
} }

View File

@@ -15,13 +15,28 @@
using namespace Quotient; using namespace Quotient;
void CustomEmojiModel::setConnection(NeoChatConnection *connection)
{
if (connection == m_connection) {
return;
}
m_connection = connection;
Q_EMIT connectionChanged();
fetchEmojis();
}
NeoChatConnection *CustomEmojiModel::connection() const
{
return m_connection;
}
void CustomEmojiModel::fetchEmojis() void CustomEmojiModel::fetchEmojis()
{ {
if (!Controller::instance().activeConnection()) { if (!m_connection) {
return; return;
} }
const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls);
if (data == nullptr) { if (data == nullptr) {
return; return;
} }
@@ -53,10 +68,10 @@ void CustomEmojiModel::addEmoji(const QString &name, const QUrl &location)
{ {
using namespace Quotient; using namespace Quotient;
auto job = Controller::instance().activeConnection()->uploadFile(location.toLocalFile()); auto job = m_connection->uploadFile(location.toLocalFile());
connect(job, &BaseJob::success, this, [name, location, job] { connect(job, &BaseJob::success, this, [name, location, job, this] {
const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls);
auto json = data != nullptr ? data->contentJson() : QJsonObject(); auto json = data != nullptr ? data->contentJson() : QJsonObject();
auto emojiData = json["images"_ls].toObject(); auto emojiData = json["images"_ls].toObject();
@@ -78,7 +93,7 @@ void CustomEmojiModel::addEmoji(const QString &name, const QUrl &location)
}); });
json["images"_ls] = emojiData; json["images"_ls] = emojiData;
Controller::instance().activeConnection()->setAccountData("im.ponies.user_emotes"_ls, json); m_connection->setAccountData("im.ponies.user_emotes"_ls, json);
}); });
} }
@@ -86,7 +101,7 @@ void CustomEmojiModel::removeEmoji(const QString &name)
{ {
using namespace Quotient; using namespace Quotient;
const auto &data = Controller::instance().activeConnection()->accountData("im.ponies.user_emotes"_ls); const auto &data = m_connection->accountData("im.ponies.user_emotes"_ls);
Q_ASSERT(data); Q_ASSERT(data);
auto json = data->contentJson(); auto json = data->contentJson();
const QString _name = name.mid(1).chopped(1); const QString _name = name.mid(1).chopped(1);
@@ -109,18 +124,18 @@ void CustomEmojiModel::removeEmoji(const QString &name)
emojiData.remove(_name); emojiData.remove(_name);
json["emoticons"_ls] = emojiData; json["emoticons"_ls] = emojiData;
} }
Controller::instance().activeConnection()->setAccountData("im.ponies.user_emotes"_ls, json); m_connection->setAccountData("im.ponies.user_emotes"_ls, json);
} }
CustomEmojiModel::CustomEmojiModel(QObject *parent) CustomEmojiModel::CustomEmojiModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
{ {
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() { connect(this, &CustomEmojiModel::connectionChanged, this, [this]() {
if (!Controller::instance().activeConnection()) { if (!m_connection) {
return; return;
} }
CustomEmojiModel::fetchEmojis(); CustomEmojiModel::fetchEmojis();
connect(Controller::instance().activeConnection(), &Connection::accountDataChanged, this, [this](const QString &id) { connect(m_connection, &Connection::accountDataChanged, this, [this](const QString &id) {
if (id != QStringLiteral("im.ponies.user_emotes")) { if (id != QStringLiteral("im.ponies.user_emotes")) {
return; return;
} }

View File

@@ -8,6 +8,8 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <memory> #include <memory>
class NeoChatConnection;
struct CustomEmoji { struct CustomEmoji {
QString name; // with :semicolons: QString name; // with :semicolons:
QString url; // mxc:// QString url; // mxc://
@@ -31,6 +33,8 @@ class CustomEmojiModel : public QAbstractListModel
QML_ELEMENT QML_ELEMENT
QML_SINGLETON QML_SINGLETON
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
public: public:
/** /**
* @brief Defines the model roles. * @brief Defines the model roles.
@@ -98,9 +102,16 @@ public:
*/ */
Q_INVOKABLE void removeEmoji(const QString &name); Q_INVOKABLE void removeEmoji(const QString &name);
void setConnection(NeoChatConnection *connection);
NeoChatConnection *connection() const;
Q_SIGNALS:
void connectionChanged();
private: private:
explicit CustomEmojiModel(QObject *parent = nullptr); explicit CustomEmojiModel(QObject *parent = nullptr);
QList<CustomEmoji> m_emojis; QList<CustomEmoji> m_emojis;
NeoChatConnection *m_connection = nullptr;
void fetchEmojis(); void fetchEmojis();
}; };

View File

@@ -24,8 +24,8 @@ DevicesModel::DevicesModel(QObject *parent)
void DevicesModel::fetchDevices() void DevicesModel::fetchDevices()
{ {
if (Controller::instance().activeConnection()) { if (m_connection) {
auto job = Controller::instance().activeConnection()->callApi<GetDevicesJob>(); auto job = m_connection->callApi<GetDevicesJob>();
connect(job, &BaseJob::success, this, [this, job]() { connect(job, &BaseJob::success, this, [this, job]() {
beginResetModel(); beginResetModel();
m_devices = job->devices(); m_devices = job->devices();
@@ -102,7 +102,7 @@ void DevicesModel::logout(const QString &deviceId, const QString &password)
for (index = 0; m_devices[index].deviceId != deviceId; index++) for (index = 0; m_devices[index].deviceId != deviceId; index++)
; ;
auto job = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId); auto job = m_connection->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId);
connect(job, &BaseJob::result, this, [this, job, password, index] { connect(job, &BaseJob::result, this, [this, job, password, index] {
auto onSuccess = [this, index]() { auto onSuccess = [this, index]() {
@@ -117,9 +117,9 @@ void DevicesModel::logout(const QString &deviceId, const QString &password)
authData["session"_ls] = replyData["session"_ls]; authData["session"_ls] = replyData["session"_ls];
authData["password"_ls] = password; authData["password"_ls] = password;
authData["type"_ls] = "m.login.password"_ls; authData["type"_ls] = "m.login.password"_ls;
QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, Controller::instance().activeConnection()->user()->id()}}; QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, m_connection->user()->id()}};
authData["identifier"_ls] = identifier; authData["identifier"_ls] = identifier;
auto *innerJob = Controller::instance().activeConnection()->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId, authData); auto *innerJob = m_connection->callApi<NeochatDeleteDeviceJob>(m_devices[index].deviceId, authData);
connect(innerJob, &BaseJob::success, this, onSuccess); connect(innerJob, &BaseJob::success, this, onSuccess);
} else { } else {
onSuccess(); onSuccess();
@@ -132,7 +132,7 @@ void DevicesModel::setName(const QString &deviceId, const QString &name)
int index; int index;
for (index = 0; m_devices[index].deviceId != deviceId; index++); for (index = 0; m_devices[index].deviceId != deviceId; index++);
auto job = Controller::instance().activeConnection()->callApi<UpdateDeviceJob>(m_devices[index].deviceId, name); auto job = m_connection->callApi<UpdateDeviceJob>(m_devices[index].deviceId, name);
QString oldName = m_devices[index].displayName; QString oldName = m_devices[index].displayName;
beginResetModel(); beginResetModel();
m_devices[index].displayName = name; m_devices[index].displayName = name;
@@ -160,7 +160,7 @@ void DevicesModel::setConnection(Connection *connection)
connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) { connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) {
Q_UNUSED(deviceId); Q_UNUSED(deviceId);
if (userId == Controller::instance().activeConnection()->userId()) { if (userId == m_connection->userId()) {
fetchDevices(); fetchDevices();
} }
}); });

View File

@@ -66,19 +66,6 @@ PushRuleModel::PushRuleModel(QObject *parent)
: QAbstractListModel(parent) : QAbstractListModel(parent)
{ {
m_defaultKeywordAction = static_cast<PushNotificationAction::Action>(NeoChatConfig::self()->keywordPushRuleDefault()); m_defaultKeywordAction = static_cast<PushNotificationAction::Action>(NeoChatConfig::self()->keywordPushRuleDefault());
if (Controller::instance().activeConnection()) {
controllerConnectionChanged();
}
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &PushRuleModel::controllerConnectionChanged);
}
void PushRuleModel::controllerConnectionChanged()
{
if (Controller::instance().activeConnection()) {
connect(Controller::instance().activeConnection(), &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules);
updateNotificationRules(QStringLiteral("m.push_rules"));
}
} }
void PushRuleModel::updateNotificationRules(const QString &type) void PushRuleModel::updateNotificationRules(const QString &type)
@@ -87,7 +74,7 @@ void PushRuleModel::updateNotificationRules(const QString &type)
return; return;
} }
const QJsonObject ruleDataJson = Controller::instance().activeConnection()->accountDataJson(QStringLiteral("m.push_rules")); const QJsonObject ruleDataJson = m_connection->accountDataJson(QStringLiteral("m.push_rules"));
const Quotient::PushRuleset ruleData = Quotient::fromJson<Quotient::PushRuleset>(ruleDataJson[QStringLiteral("global")].toObject()); const Quotient::PushRuleset ruleData = Quotient::fromJson<Quotient::PushRuleset>(ruleDataJson[QStringLiteral("global")].toObject());
beginResetModel(); beginResetModel();
@@ -156,8 +143,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru
* *
* Rooms that the user hasn't joined shouldn't have a rule. * Rooms that the user hasn't joined shouldn't have a rule.
*/ */
auto connection = Controller::instance().activeConnection(); if (m_connection->room(ruleId) != nullptr) {
if (connection->room(ruleId) != nullptr) {
return PushNotificationSection::Undefined; return PushNotificationSection::Undefined;
} }
/** /**
@@ -171,7 +157,7 @@ PushNotificationSection::Section PushRuleModel::getSection(Quotient::PushRule ru
if (!testUserId.startsWith(u'@')) { if (!testUserId.startsWith(u'@')) {
testUserId.prepend(u'@'); testUserId.prepend(u'@');
} }
if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && connection->user(testUserId) != nullptr) { if (testUserId.startsWith(u'@') && !Quotient::serverPart(testUserId).isEmpty() && m_connection->user(testUserId) != nullptr) {
return PushNotificationSection::Undefined; return PushNotificationSection::Undefined;
} }
// If the rule has push conditions and one is a room ID it is a room only keyword. // If the rule has push conditions and one is a room ID it is a room only keyword.
@@ -325,14 +311,14 @@ void PushRuleModel::addKeyword(const QString &keyword, const QString &roomId)
pushConditions.append(keywordCondition); pushConditions.append(keywordCondition);
} }
auto job = Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleJob>(QLatin1String("global"), auto job = m_connection->callApi<Quotient::SetPushRuleJob>(QLatin1String("global"),
PushNotificationKind::kindString(kind), PushNotificationKind::kindString(kind),
keyword, keyword,
actions, actions,
QString(), QString(),
QString(), QString(),
pushConditions, pushConditions,
roomId.isEmpty() ? keyword : QString()); roomId.isEmpty() ? keyword : QString());
connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() { connect(job, &Quotient::BaseJob::failure, this, [job, keyword]() {
qWarning() << QLatin1String("Unable to set push rule for keyword %1: ").arg(keyword) << job->errorString(); qWarning() << QLatin1String("Unable to set push rule for keyword %1: ").arg(keyword) << job->errorString();
}); });
@@ -351,7 +337,7 @@ void PushRuleModel::removeKeyword(const QString &keyword)
} }
auto kind = PushNotificationKind::kindString(m_rules[index].kind); auto kind = PushNotificationKind::kindString(m_rules[index].kind);
auto job = Controller::instance().activeConnection()->callApi<Quotient::DeletePushRuleJob>(QStringLiteral("global"), kind, m_rules[index].id); auto job = m_connection->callApi<Quotient::DeletePushRuleJob>(QStringLiteral("global"), kind, m_rules[index].id);
connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() { connect(job, &Quotient::BaseJob::failure, this, [this, job, index]() {
qWarning() << QLatin1String("Unable to remove push rule for keyword %1: ").arg(m_rules[index].id) << job->errorString(); qWarning() << QLatin1String("Unable to remove push rule for keyword %1: ").arg(m_rules[index].id) << job->errorString();
}); });
@@ -359,10 +345,10 @@ void PushRuleModel::removeKeyword(const QString &keyword)
void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled) void PushRuleModel::setNotificationRuleEnabled(const QString &kind, const QString &ruleId, bool enabled)
{ {
auto job = Controller::instance().activeConnection()->callApi<Quotient::IsPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId); auto job = m_connection->callApi<Quotient::IsPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId);
connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled]() { connect(job, &Quotient::BaseJob::success, this, [job, kind, ruleId, enabled, this]() {
if (job->enabled() != enabled) { if (job->enabled() != enabled) {
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId, enabled); m_connection->callApi<Quotient::SetPushRuleEnabledJob>(QStringLiteral("global"), kind, ruleId, enabled);
} }
}); });
} }
@@ -376,7 +362,7 @@ void PushRuleModel::setNotificationRuleActions(const QString &kind, const QStrin
actions = actionToVariant(action); actions = actionToVariant(action);
} }
Controller::instance().activeConnection()->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions); m_connection->callApi<Quotient::SetPushRuleActionsJob>(QStringLiteral("global"), kind, ruleId, actions);
} }
PushNotificationAction::Action PushRuleModel::variantToAction(const QList<QVariant> &actions, bool enabled) PushNotificationAction::Action PushRuleModel::variantToAction(const QList<QVariant> &actions, bool enabled)
@@ -453,4 +439,23 @@ QList<QVariant> PushRuleModel::actionToVariant(PushNotificationAction::Action ac
return actions; return actions;
} }
NeoChatConnection *PushRuleModel::connection() const
{
return m_connection;
}
void PushRuleModel::setConnection(NeoChatConnection *connection)
{
if (connection == m_connection) {
return;
}
m_connection = connection;
Q_EMIT connectionChanged();
if (m_connection) {
connect(m_connection, &Quotient::Connection::accountDataChanged, this, &PushRuleModel::updateNotificationRules);
updateNotificationRules(QStringLiteral("m.push_rules"));
}
}
#include "moc_pushrulemodel.cpp" #include "moc_pushrulemodel.cpp"

View File

@@ -157,6 +157,8 @@ class PushRuleModel : public QAbstractListModel
*/ */
Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged) Q_PROPERTY(bool globalNotificationsSet READ globalNotificationsSet NOTIFY globalNotificationsSetChanged)
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
public: public:
struct Rule { struct Rule {
QString id; QString id;
@@ -225,18 +227,22 @@ public:
*/ */
Q_INVOKABLE void removeKeyword(const QString &keyword); Q_INVOKABLE void removeKeyword(const QString &keyword);
void setConnection(NeoChatConnection *connection);
NeoChatConnection *connection() const;
Q_SIGNALS: Q_SIGNALS:
void defaultStateChanged(); void defaultStateChanged();
void globalNotificationsEnabledChanged(); void globalNotificationsEnabledChanged();
void globalNotificationsSetChanged(); void globalNotificationsSetChanged();
void connectionChanged();
private Q_SLOTS: private Q_SLOTS:
void controllerConnectionChanged();
void updateNotificationRules(const QString &type); void updateNotificationRules(const QString &type);
private: private:
PushNotificationAction::Action m_defaultKeywordAction; PushNotificationAction::Action m_defaultKeywordAction;
QList<Rule> m_rules; QList<Rule> m_rules;
NeoChatConnection *m_connection;
void setRules(QList<Quotient::PushRule> rules, PushNotificationKind::Kind kind); void setRules(QList<Quotient::PushRule> rules, PushNotificationKind::Kind kind);

View File

@@ -19,7 +19,7 @@ ServerListModel::ServerListModel(QObject *parent)
const auto stateConfig = KSharedConfig::openStateConfig(); const auto stateConfig = KSharedConfig::openStateConfig();
const KConfigGroup serverGroup = stateConfig->group(QStringLiteral("Servers")); const KConfigGroup serverGroup = stateConfig->group(QStringLiteral("Servers"));
QString domain = Controller::instance().activeConnection()->domain(); QString domain = m_connection->domain();
// Add the user's homeserver // Add the user's homeserver
m_servers.append(Server{ m_servers.append(Server{
@@ -100,7 +100,7 @@ void ServerListModel::checkServer(const QString &url)
m_checkServerJob->abandon(); m_checkServerJob->abandon();
} }
m_checkServerJob = Controller::instance().activeConnection()->callApi<Quotient::QueryPublicRoomsJob>(url, 1); m_checkServerJob = m_connection->callApi<Quotient::QueryPublicRoomsJob>(url, 1);
connect(m_checkServerJob, &Quotient::BaseJob::success, this, [this, url] { connect(m_checkServerJob, &Quotient::BaseJob::success, this, [this, url] {
Q_EMIT serverCheckComplete(url, true); Q_EMIT serverCheckComplete(url, true);
}); });
@@ -153,4 +153,18 @@ QHash<int, QByteArray> ServerListModel::roleNames() const
}; };
} }
NeoChatConnection *ServerListModel::connection() const
{
return m_connection;
}
void ServerListModel::setConnection(NeoChatConnection *connection)
{
if (m_connection == connection) {
return;
}
m_connection = connection;
Q_EMIT connectionChanged();
}
#include "moc_serverlistmodel.cpp" #include "moc_serverlistmodel.cpp"

View File

@@ -10,6 +10,8 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QUrl> #include <QUrl>
class NeoChatConnection;
/** /**
* @class ServerListModel * @class ServerListModel
* *
@@ -27,6 +29,8 @@ class ServerListModel : public QAbstractListModel
Q_OBJECT Q_OBJECT
QML_ELEMENT QML_ELEMENT
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
public: public:
/** /**
* @brief Define the data required to represent a server. * @brief Define the data required to represent a server.
@@ -96,10 +100,15 @@ public:
*/ */
Q_INVOKABLE void removeServerAtIndex(int index); Q_INVOKABLE void removeServerAtIndex(int index);
NeoChatConnection *connection() const;
void setConnection(NeoChatConnection *connection);
Q_SIGNALS: Q_SIGNALS:
void serverCheckComplete(QString url, bool valid); void serverCheckComplete(QString url, bool valid);
void connectionChanged();
private: private:
QList<Server> m_servers; QList<Server> m_servers;
QPointer<Quotient::QueryPublicRoomsJob> m_checkServerJob = nullptr; QPointer<Quotient::QueryPublicRoomsJob> m_checkServerJob = nullptr;
NeoChatConnection *m_connection = nullptr;
}; };

View File

@@ -12,7 +12,7 @@
SpaceChildrenModel::SpaceChildrenModel(QObject *parent) SpaceChildrenModel::SpaceChildrenModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
{ {
m_rootItem = new SpaceTreeItem(); m_rootItem = new SpaceTreeItem(nullptr);
} }
SpaceChildrenModel::~SpaceChildrenModel() SpaceChildrenModel::~SpaceChildrenModel()
@@ -71,7 +71,8 @@ void SpaceChildrenModel::refreshModel()
delete m_rootItem; delete m_rootItem;
m_loading = true; m_loading = true;
Q_EMIT loadingChanged(); Q_EMIT loadingChanged();
m_rootItem = new SpaceTreeItem(nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias()); m_rootItem =
new SpaceTreeItem(dynamic_cast<NeoChatConnection *>(m_space->connection()), nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias());
endResetModel(); endResetModel();
auto job = m_space->connection()->callApi<Quotient::GetSpaceHierarchyJob>(m_space->id(), Quotient::none, Quotient::none, 1); auto job = m_space->connection()->callApi<Quotient::GetSpaceHierarchyJob>(m_space->id(), Quotient::none, Quotient::none, 1);
m_currentJobs.append(job); m_currentJobs.append(job);
@@ -112,7 +113,8 @@ void SpaceChildrenModel::insertChildren(std::vector<Quotient::GetSpaceHierarchyJ
} }
} }
parentItem->insertChild(insertRow, parentItem->insertChild(insertRow,
new SpaceTreeItem(parentItem, new SpaceTreeItem(dynamic_cast<NeoChatConnection *>(m_space->connection()),
parentItem,
children[i].roomId, children[i].roomId,
children[i].name, children[i].name,
children[i].canonicalAlias, children[i].canonicalAlias,

View File

@@ -5,7 +5,8 @@
#include "controller.h" #include "controller.h"
SpaceTreeItem::SpaceTreeItem(SpaceTreeItem *parent, SpaceTreeItem::SpaceTreeItem(NeoChatConnection *connection,
SpaceTreeItem *parent,
const QString &id, const QString &id,
const QString &name, const QString &name,
const QString &canonicalAlias, const QString &canonicalAlias,
@@ -15,7 +16,8 @@ SpaceTreeItem::SpaceTreeItem(SpaceTreeItem *parent,
bool allowGuests, bool allowGuests,
bool worldReadable, bool worldReadable,
bool isSpace) bool isSpace)
: m_parentItem(parent) : m_connection(connection)
, m_parentItem(parent)
, m_id(id) , m_id(id)
, m_name(name) , m_name(name)
, m_canonicalAlias(canonicalAlias) , m_canonicalAlias(canonicalAlias)
@@ -107,8 +109,7 @@ QUrl SpaceTreeItem::avatarUrl() const
if (m_avatarUrl.isEmpty() || m_avatarUrl.scheme() != QLatin1String("mxc")) { if (m_avatarUrl.isEmpty() || m_avatarUrl.scheme() != QLatin1String("mxc")) {
return {}; return {};
} }
auto connection = Controller::instance().activeConnection(); auto url = m_connection->makeMediaUrl(m_avatarUrl);
auto url = connection->makeMediaUrl(m_avatarUrl);
if (url.scheme() == QLatin1String("mxc")) { if (url.scheme() == QLatin1String("mxc")) {
return url; return url;
} }
@@ -127,11 +128,10 @@ bool SpaceTreeItem::worldReadable() const
bool SpaceTreeItem::isJoined() const bool SpaceTreeItem::isJoined() const
{ {
auto connection = Controller::instance().activeConnection(); if (!m_connection) {
if (!connection) {
return false; return false;
} }
return connection->room(id(), Quotient::JoinState::Join) != nullptr; return m_connection->room(id(), Quotient::JoinState::Join) != nullptr;
} }
bool SpaceTreeItem::isSpace() const bool SpaceTreeItem::isSpace() const

View File

@@ -3,6 +3,8 @@
#include <Quotient/csapi/space_hierarchy.h> #include <Quotient/csapi/space_hierarchy.h>
class NeoChatConnection;
/** /**
* @class SpaceTreeItem * @class SpaceTreeItem
* *
@@ -18,7 +20,8 @@
class SpaceTreeItem class SpaceTreeItem
{ {
public: public:
explicit SpaceTreeItem(SpaceTreeItem *parent = nullptr, explicit SpaceTreeItem(NeoChatConnection *connection,
SpaceTreeItem *parent = nullptr,
const QString &id = {}, const QString &id = {},
const QString &name = {}, const QString &name = {},
const QString &canonicalAlias = {}, const QString &canonicalAlias = {},
@@ -121,6 +124,7 @@ public:
bool isSpace() const; bool isSpace() const;
private: private:
NeoChatConnection *m_connection;
QList<SpaceTreeItem *> m_children; QList<SpaceTreeItem *> m_children;
SpaceTreeItem *m_parentItem; SpaceTreeItem *m_parentItem;

View File

@@ -1338,7 +1338,7 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
for (const auto &i : roomRuleArray) { for (const auto &i : roomRuleArray) {
QJsonObject roomRule = i.toObject(); QJsonObject roomRule = i.toObject();
if (roomRule["rule_id"_ls] == id()) { if (roomRule["rule_id"_ls] == id()) {
Controller::instance().activeConnection()->callApi<DeletePushRuleJob>("global"_ls, "room"_ls, id()); connection()->callApi<DeletePushRuleJob>("global"_ls, "room"_ls, id());
} }
} }
} }
@@ -1349,7 +1349,7 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
for (const auto &i : overrideRuleArray) { for (const auto &i : overrideRuleArray) {
QJsonObject overrideRule = i.toObject(); QJsonObject overrideRule = i.toObject();
if (overrideRule["rule_id"_ls] == id()) { if (overrideRule["rule_id"_ls] == id()) {
Controller::instance().activeConnection()->callApi<DeletePushRuleJob>("global"_ls, "override"_ls, id()); connection()->callApi<DeletePushRuleJob>("global"_ls, "override"_ls, id());
} }
} }
} }
@@ -1385,11 +1385,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
const QList<PushCondition> conditions = {pushCondition}; const QList<PushCondition> conditions = {pushCondition};
// Add new override rule and make sure it's enabled // Add new override rule and make sure it's enabled
auto job = Controller::instance() auto job = connection()->callApi<SetPushRuleJob>("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString());
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "override"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(job, &BaseJob::success, this, [this]() { connect(job, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "override"_ls, id(), true); auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("global"_ls, "override"_ls, id(), true);
connect(enableJob, &BaseJob::success, this, [this]() { connect(enableJob, &BaseJob::success, this, [this]() {
m_pushNotificationStateUpdating = false; m_pushNotificationStateUpdating = false;
}); });
@@ -1413,11 +1411,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
// No conditions for a room rule // No conditions for a room rule
const QList<PushCondition> conditions; const QList<PushCondition> conditions;
auto setJob = Controller::instance() auto setJob = connection()->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(setJob, &BaseJob::success, this, [this]() { connect(setJob, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true); auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true);
connect(enableJob, &BaseJob::success, this, [this]() { connect(enableJob, &BaseJob::success, this, [this]() {
m_pushNotificationStateUpdating = false; m_pushNotificationStateUpdating = false;
}); });
@@ -1446,11 +1442,9 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
const QList<PushCondition> conditions; const QList<PushCondition> conditions;
// Add new room rule and make sure enabled // Add new room rule and make sure enabled
auto setJob = Controller::instance() auto setJob = connection()->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
.activeConnection()
->callApi<SetPushRuleJob>("global"_ls, "room"_ls, id(), actions, QString(), QString(), conditions, QString());
connect(setJob, &BaseJob::success, this, [this]() { connect(setJob, &BaseJob::success, this, [this]() {
auto enableJob = Controller::instance().activeConnection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true); auto enableJob = connection()->callApi<SetPushRuleEnabledJob>("global"_ls, "room"_ls, id(), true);
connect(enableJob, &BaseJob::success, this, [this]() { connect(enableJob, &BaseJob::success, this, [this]() {
m_pushNotificationStateUpdating = false; m_pushNotificationStateUpdating = false;
}); });

View File

@@ -210,9 +210,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room,
if (!room) { if (!room) {
return; return;
} }
if (room->localUser()->id() != Controller::instance().activeConnection()->userId()) { Controller::instance().setActiveConnection(dynamic_cast<NeoChatConnection *>(Controller::instance().accounts().get(room->localUser()->id())));
Controller::instance().setActiveConnection(dynamic_cast<NeoChatConnection *>(Controller::instance().accounts().get(room->localUser()->id())));
}
RoomManager::instance().enterRoom(room); RoomManager::instance().enterRoom(room);
}); });

View File

@@ -14,17 +14,23 @@ import org.kde.neochat
FormCard.FormCardPage { FormCard.FormCardPage {
id: root id: root
required property NeoChatConnection connection
title: i18nc("@title:window", "Notifications") title: i18nc("@title:window", "Notifications")
property PushRuleModel pushRuleModel: PushRuleModel {
connection: root.connection
}
FormCard.FormCard { FormCard.FormCard {
Layout.topMargin: Kirigami.Units.largeSpacing Layout.topMargin: Kirigami.Units.largeSpacing
FormCard.FormCheckDelegate { FormCard.FormCheckDelegate {
text: i18n("Enable notifications for this account") text: i18n("Enable notifications for this account")
description: i18n("Whether push notifications are generated by your Matrix server") description: i18n("Whether push notifications are generated by your Matrix server")
checked: Controller.pushRuleModel.globalNotificationsEnabled checked: root.pushRuleModel.globalNotificationsEnabled
enabled: Controller.pushRuleModel.globalNotificationsSet enabled: root.pushRuleModel.globalNotificationsSet
onToggled: { onToggled: {
Controller.pushRuleModel.globalNotificationsEnabled = checked root.pushRuleModel.globalNotificationsEnabled = checked
} }
} }
} }
@@ -35,7 +41,7 @@ FormCard.FormCardPage {
FormCard.FormCard { FormCard.FormCard {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Room; return sectionRole == PushNotificationSection.Room;
@@ -52,7 +58,7 @@ FormCard.FormCardPage {
FormCard.FormCard { FormCard.FormCard {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Mentions; return sectionRole == PushNotificationSection.Mentions;
@@ -69,7 +75,7 @@ FormCard.FormCardPage {
FormCard.FormCard { FormCard.FormCard {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
@@ -100,7 +106,7 @@ FormCard.FormCardPage {
} }
onAccepted: { onAccepted: {
Controller.pushRuleModel.addKeyword(keywordAddField.text) root.pushRuleModel.addKeyword(keywordAddField.text)
keywordAddField.text = "" keywordAddField.text = ""
} }
} }
@@ -114,7 +120,7 @@ FormCard.FormCardPage {
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown
onClicked: { onClicked: {
Controller.pushRuleModel.addKeyword(keywordAddField.text) root.pushRuleModel.addKeyword(keywordAddField.text)
keywordAddField.text = "" keywordAddField.text = ""
} }
@@ -133,7 +139,7 @@ FormCard.FormCardPage {
FormCard.FormCard { FormCard.FormCard {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Invites; return sectionRole == PushNotificationSection.Invites;
@@ -154,7 +160,7 @@ FormCard.FormCardPage {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
id: unknownModel id: unknownModel
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
return sectionRole == PushNotificationSection.Unknown; return sectionRole == PushNotificationSection.Unknown;
@@ -169,9 +175,9 @@ FormCard.FormCardPage {
id: ruleDelegate id: ruleDelegate
NotificationRuleItem { NotificationRuleItem {
onDeleteRule: { onDeleteRule: {
Controller.pushRuleModel.removeKeyword(id) root.pushRuleModel.removeKeyword(id)
} }
onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action) onActionChanged: (action) => root.pushRuleModel.setPushRuleAction(id, action)
} }
} }
} }

View File

@@ -69,6 +69,7 @@ Kirigami.ScrollablePage {
valueRole: "url" valueRole: "url"
model: ServerListModel { model: ServerListModel {
id: serverListModel id: serverListModel
connection: root.connection
} }
delegate: Delegates.RoundedItemDelegate { delegate: Delegates.RoundedItemDelegate {

View File

@@ -16,6 +16,10 @@ FormCard.FormCardPage {
property NeoChatRoom room property NeoChatRoom room
property PushRuleModel pushRuleModel: PushRuleModel {
connection: root.room.connection
}
title: i18nc('@title:window', 'Notifications') title: i18nc('@title:window', 'Notifications')
FormCard.FormHeader { FormCard.FormHeader {
@@ -63,7 +67,7 @@ FormCard.FormCardPage {
FormCard.FormCard { FormCard.FormCard {
Repeater { Repeater {
model: KSortFilterProxyModel { model: KSortFilterProxyModel {
sourceModel: Controller.pushRuleModel sourceModel: root.pushRuleModel
filterRowCallback: function(source_row, source_parent) { filterRowCallback: function(source_row, source_parent) {
let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole) let sectionRole = sourceModel.data(sourceModel.index(source_row, 0, source_parent), PushRuleModel.SectionRole)
@@ -78,9 +82,9 @@ FormCard.FormCardPage {
id: ruleDelegate id: ruleDelegate
NotificationRuleItem { NotificationRuleItem {
onDeleteRule: { onDeleteRule: {
Controller.pushRuleModel.removeKeyword(id) root.pushRuleModel.removeKeyword(id)
} }
onActionChanged: (action) => Controller.pushRuleModel.setPushRuleAction(id, action) onActionChanged: (action) => root.pushRuleModel.setPushRuleAction(id, action)
} }
} }
} }
@@ -105,7 +109,7 @@ FormCard.FormCardPage {
} }
onAccepted: { onAccepted: {
Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id)
keywordAddField.text = "" keywordAddField.text = ""
} }
} }
@@ -119,7 +123,7 @@ FormCard.FormCardPage {
enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown && keywordAddField.text.length > 0 enabled: NotificationsManager.keywordNotificationAction !== PushNotificationAction.Unknown && keywordAddField.text.length > 0
onClicked: { onClicked: {
Controller.pushRuleModel.addKeyword(keywordAddField.text, root.room.id) root.pushRuleModel.addKeyword(keywordAddField.text, root.room.id)
keywordAddField.text = "" keywordAddField.text = ""
} }

View File

@@ -39,6 +39,8 @@ Kirigami.Page {
sortFilterRoomListModel.filterText = ""; sortFilterRoomListModel.filterText = "";
} }
Component.onCompleted: Runner.roomListModel = root.roomListModel
Connections { Connections {
target: RoomManager target: RoomManager
function onCurrentRoomChanged() { function onCurrentRoomChanged() {

View File

@@ -32,6 +32,11 @@ KirigamiSettings.CategorizedSettings {
text: i18n("Notifications") text: i18n("Notifications")
icon.name: "preferences-desktop-notification" icon.name: "preferences-desktop-notification"
page: Qt.resolvedUrl("GlobalNotificationsPage.qml") page: Qt.resolvedUrl("GlobalNotificationsPage.qml")
initialProperties: {
return {
connection: root.connection
}
}
}, },
KirigamiSettings.SettingAction { KirigamiSettings.SettingAction {
actionName: "security" actionName: "security"

View File

@@ -40,6 +40,13 @@ Kirigami.ApplicationWindow {
} }
} }
onConnectionChanged: {
CustomEmojiModel.connection = root.connection
MatrixImageProvider.connection = root.connection
RoomManager.connection = root.connection
SpaceHierarchyCache.connection = root.connection
}
Connections { Connections {
target: root.quitAction target: root.quitAction
function onTriggered() { function onTriggered() {
@@ -190,6 +197,10 @@ Kirigami.ApplicationWindow {
} }
Component.onCompleted: { Component.onCompleted: {
CustomEmojiModel.connection = root.connection
MatrixImageProvider.connection = root.connection
RoomManager.connection = root.connection
SpaceHierarchyCache.connection = root.connection
WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout); WindowController.setBlur(pageStack, Config.blur && !Config.compactLayout);
if (Config.minimizeToSystemTrayOnStartup && !Kirigami.Settings.isMobile && Controller.supportSystemTray && Config.systemTray) { if (Config.minimizeToSystemTrayOnStartup && !Kirigami.Settings.isMobile && Controller.supportSystemTray && Config.systemTray) {
restoreWindowGeometryConnections.enabled = true; // To restore window size and position restoreWindowGeometryConnections.enabled = true; // To restore window size and position

View File

@@ -77,10 +77,9 @@ void RoomManager::openResource(const QString &idOrUri, const QString &action)
Q_EMIT warning(i18n("Malformed or empty Matrix id"), i18n("%1 is not a correct Matrix identifier", idOrUri)); Q_EMIT warning(i18n("Malformed or empty Matrix id"), i18n("%1 is not a correct Matrix identifier", idOrUri));
return; return;
} }
auto account = Controller::instance().activeConnection();
if (uri.type() != Uri::NonMatrix) { if (uri.type() != Uri::NonMatrix) {
if (!account) { if (!m_connection) {
return; return;
} }
if (!action.isEmpty()) { if (!action.isEmpty()) {
@@ -89,7 +88,7 @@ void RoomManager::openResource(const QString &idOrUri, const QString &action)
// TODO we should allow the user to select a connection. // TODO we should allow the user to select a connection.
} }
const auto result = visitResource(account, uri); const auto result = visitResource(m_connection, uri);
if (result == Quotient::CouldNotResolve) { if (result == Quotient::CouldNotResolve) {
Q_EMIT warning(i18n("Room not found"), i18n("There's no room %1 in the room list. Check the spelling and the account.", idOrUri)); Q_EMIT warning(i18n("Room not found"), i18n("There's no room %1 in the room list. Check the spelling and the account.", idOrUri));
} else { // Invalid cases should have been eliminated earlier } else { // Invalid cases should have been eliminated earlier
@@ -145,7 +144,7 @@ void RoomManager::setUrlArgument(const QString &arg)
void RoomManager::loadInitialRoom() void RoomManager::loadInitialRoom()
{ {
Q_ASSERT(Controller::instance().activeConnection()); Q_ASSERT(m_connection);
if (!m_arg.isEmpty()) { if (!m_arg.isEmpty()) {
openResource(m_arg); openResource(m_arg);
@@ -158,16 +157,16 @@ void RoomManager::loadInitialRoom()
openRoomForActiveConnection(); openRoomForActiveConnection();
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &RoomManager::openRoomForActiveConnection); connect(this, &RoomManager::connectionChanged, this, &RoomManager::openRoomForActiveConnection);
} }
void RoomManager::openRoomForActiveConnection() void RoomManager::openRoomForActiveConnection()
{ {
if (!Controller::instance().activeConnection()) { if (!m_connection) {
return; return;
} }
// Read from last open room // Read from last open room
QString roomId = m_lastRoomConfig.readEntry(Controller::instance().activeConnection()->userId(), QString()); QString roomId = m_lastRoomConfig.readEntry(m_connection->userId(), QString());
// TODO remove legacy check at some point. // TODO remove legacy check at some point.
if (roomId.isEmpty()) { if (roomId.isEmpty()) {
@@ -177,7 +176,7 @@ void RoomManager::openRoomForActiveConnection()
if (!roomId.isEmpty()) { if (!roomId.isEmpty()) {
// Here we can cast because the controller has been configured to // Here we can cast because the controller has been configured to
// return NeoChatRoom instead of simple Quotient::Room // return NeoChatRoom instead of simple Quotient::Room
const auto room = qobject_cast<NeoChatRoom *>(Controller::instance().activeConnection()->room(roomId)); const auto room = qobject_cast<NeoChatRoom *>(m_connection->room(roomId));
if (room) { if (room) {
if (room->isSpace()) { if (room->isSpace()) {
@@ -219,7 +218,7 @@ void RoomManager::enterRoom(NeoChatRoom *room)
} }
// Save last open room // Save last open room
m_lastRoomConfig.writeEntry(Controller::instance().activeConnection()->userId(), room->id()); m_lastRoomConfig.writeEntry(m_connection->userId(), room->id());
} }
void RoomManager::openWindow(NeoChatRoom *room) void RoomManager::openWindow(NeoChatRoom *room)
@@ -253,7 +252,7 @@ void RoomManager::enterSpaceHome(NeoChatRoom *spaceRoom)
} }
// Save last open room // Save last open room
m_lastRoomConfig.writeEntry(Controller::instance().activeConnection()->userId(), spaceRoom->id()); m_lastRoomConfig.writeEntry(m_connection->userId(), spaceRoom->id());
} }
UriResolveResult RoomManager::visitUser(User *user, const QString &action) UriResolveResult RoomManager::visitUser(User *user, const QString &action)
@@ -381,4 +380,18 @@ void RoomManager::setChatDocumentHandler(ChatDocumentHandler *handler)
Q_EMIT chatDocumentHandlerChanged(); Q_EMIT chatDocumentHandlerChanged();
} }
NeoChatConnection *RoomManager::connection() const
{
return m_connection;
}
void RoomManager::setConnection(NeoChatConnection *connection)
{
if (m_connection == connection) {
return;
}
m_connection = connection;
Q_EMIT connectionChanged();
}
#include "moc_roommanager.cpp" #include "moc_roommanager.cpp"

View File

@@ -17,6 +17,7 @@
#include "models/messagefiltermodel.h" #include "models/messagefiltermodel.h"
class NeoChatRoom; class NeoChatRoom;
class NeoChatConnection;
namespace Quotient namespace Quotient
{ {
@@ -37,6 +38,8 @@ class RoomManager : public QObject, public UriResolverBase
QML_ELEMENT QML_ELEMENT
QML_SINGLETON QML_SINGLETON
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
/** /**
* @brief The current open room in NeoChat, if any. * @brief The current open room in NeoChat, if any.
* *
@@ -247,6 +250,9 @@ public:
*/ */
void setUrlArgument(const QString &arg); void setUrlArgument(const QString &arg);
NeoChatConnection *connection() const;
void setConnection(NeoChatConnection *connection);
Q_SIGNALS: Q_SIGNALS:
void currentRoomChanged(); void currentRoomChanged();
@@ -365,6 +371,8 @@ Q_SIGNALS:
void chatDocumentHandlerChanged(); void chatDocumentHandlerChanged();
void connectionChanged();
private: private:
void openRoomForActiveConnection(); void openRoomForActiveConnection();
@@ -378,4 +386,5 @@ private:
MessageEventModel *m_messageEventModel; MessageEventModel *m_messageEventModel;
MessageFilterModel *m_messageFilterModel; MessageFilterModel *m_messageFilterModel;
MediaMessageFilterModel *m_mediaMessageFilterModel; MediaMessageFilterModel *m_mediaMessageFilterModel;
NeoChatConnection *m_connection;
}; };

View File

@@ -33,15 +33,17 @@ Runner::Runner()
qDBusRegisterMetaType<RemoteAction>(); qDBusRegisterMetaType<RemoteAction>();
qDBusRegisterMetaType<RemoteActions>(); qDBusRegisterMetaType<RemoteActions>();
qDBusRegisterMetaType<RemoteImage>(); qDBusRegisterMetaType<RemoteImage>();
m_model.setSourceModel(&m_sourceModel);
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, &Runner::activeConnectionChanged);
} }
void Runner::activeConnectionChanged() void Runner::setRoomListModel(RoomListModel *roomListModel)
{ {
m_sourceModel.setConnection(Controller::instance().activeConnection()); m_model.setSourceModel(roomListModel);
Q_EMIT roomListModelChanged();
}
RoomListModel *Runner::roomListModel() const
{
return dynamic_cast<RoomListModel *>(m_model.sourceModel());
} }
RemoteActions Runner::Actions() RemoteActions Runner::Actions()
@@ -84,7 +86,7 @@ void Runner::Run(const QString &id, const QString &actionId)
{ {
Q_UNUSED(actionId); Q_UNUSED(actionId);
NeoChatRoom *room = qobject_cast<NeoChatRoom *>(Controller::instance().activeConnection()->room(id)); NeoChatRoom *room = qobject_cast<NeoChatRoom *>(roomListModel()->connection()->room(id));
if (!room) { if (!room) {
return; return;

View File

@@ -165,6 +165,10 @@ class Runner : public QObject, protected QDBusContext
{ {
Q_OBJECT Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.krunner1") Q_CLASSINFO("D-Bus Interface", "org.kde.krunner1")
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(RoomListModel *roomListModel READ roomListModel WRITE setRoomListModel NOTIFY roomListModelChanged)
public: public:
Runner(); Runner();
@@ -185,9 +189,14 @@ public:
*/ */
Q_SCRIPTABLE void Run(const QString &id, const QString &actionId); Q_SCRIPTABLE void Run(const QString &id, const QString &actionId);
void setRoomListModel(RoomListModel *roomListModel);
RoomListModel *roomListModel() const;
Q_SIGNALS:
void roomListModelChanged();
private: private:
RemoteImage serializeImage(const QImage &image); RemoteImage serializeImage(const QImage &image);
void activeConnectionChanged();
SortFilterRoomListModel m_model; SortFilterRoomListModel m_model;
RoomListModel m_sourceModel; RoomListModel m_sourceModel;

View File

@@ -14,22 +14,15 @@ using namespace Quotient;
SpaceHierarchyCache::SpaceHierarchyCache(QObject *parent) SpaceHierarchyCache::SpaceHierarchyCache(QObject *parent)
: QObject{parent} : QObject{parent}
{ {
cacheSpaceHierarchy();
connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this]() {
cacheSpaceHierarchy();
connect(Controller::instance().activeConnection(), &Connection::joinedRoom, this, &SpaceHierarchyCache::addSpaceToHierarchy);
connect(Controller::instance().activeConnection(), &Connection::aboutToDeleteRoom, this, &SpaceHierarchyCache::removeSpaceFromHierarchy);
});
} }
void SpaceHierarchyCache::cacheSpaceHierarchy() void SpaceHierarchyCache::cacheSpaceHierarchy()
{ {
auto connection = Controller::instance().activeConnection(); if (!m_connection) {
if (!connection) {
return; return;
} }
const auto &roomList = connection->allRooms(); const auto &roomList = m_connection->allRooms();
for (const auto &room : roomList) { for (const auto &room : roomList) {
const auto neoChatRoom = static_cast<NeoChatRoom *>(room); const auto neoChatRoom = static_cast<NeoChatRoom *>(room);
if (neoChatRoom->isSpace()) { if (neoChatRoom->isSpace()) {
@@ -46,11 +39,10 @@ void SpaceHierarchyCache::cacheSpaceHierarchy()
void SpaceHierarchyCache::populateSpaceHierarchy(const QString &spaceId) void SpaceHierarchyCache::populateSpaceHierarchy(const QString &spaceId)
{ {
auto connection = Controller::instance().activeConnection(); if (!m_connection) {
if (!connection) {
return; return;
} }
auto job = connection->callApi<GetSpaceHierarchyJob>(spaceId); auto job = m_connection->callApi<GetSpaceHierarchyJob>(spaceId);
connect(job, &BaseJob::success, this, [this, job, spaceId]() { connect(job, &BaseJob::success, this, [this, job, spaceId]() {
const auto rooms = job->rooms(); const auto rooms = job->rooms();
@@ -102,4 +94,22 @@ bool SpaceHierarchyCache::isChildSpace(const QString &spaceId) const
return false; return false;
} }
NeoChatConnection *SpaceHierarchyCache::connection() const
{
return m_connection;
}
void SpaceHierarchyCache::setConnection(NeoChatConnection *connection)
{
if (m_connection == connection) {
return;
}
m_connection = connection;
Q_EMIT connectionChanged();
m_spaceHierarchy.clear();
cacheSpaceHierarchy();
connect(connection, &Connection::joinedRoom, this, &SpaceHierarchyCache::addSpaceToHierarchy);
connect(connection, &Connection::aboutToDeleteRoom, this, &SpaceHierarchyCache::removeSpaceFromHierarchy);
}
#include "moc_spacehierarchycache.cpp" #include "moc_spacehierarchycache.cpp"

View File

@@ -10,6 +10,8 @@
#include <QQmlEngine> #include <QQmlEngine>
#include <QString> #include <QString>
#include "neochatconnection.h"
namespace Quotient namespace Quotient
{ {
class Room; class Room;
@@ -28,6 +30,8 @@ class SpaceHierarchyCache : public QObject
QML_ELEMENT QML_ELEMENT
QML_SINGLETON QML_SINGLETON
Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged)
public: public:
static SpaceHierarchyCache &instance() static SpaceHierarchyCache &instance()
{ {
@@ -50,8 +54,12 @@ public:
*/ */
[[nodiscard]] bool isChildSpace(const QString &spaceId) const; [[nodiscard]] bool isChildSpace(const QString &spaceId) const;
NeoChatConnection *connection() const;
void setConnection(NeoChatConnection *connection);
Q_SIGNALS: Q_SIGNALS:
void spaceHierarchyChanged(); void spaceHierarchyChanged();
void connectionChanged();
private Q_SLOTS: private Q_SLOTS:
void addSpaceToHierarchy(Quotient::Room *room); void addSpaceToHierarchy(Quotient::Room *room);
@@ -64,4 +72,5 @@ private:
QHash<QString, QList<QString>> m_spaceHierarchy; QHash<QString, QList<QString>> m_spaceHierarchy;
void cacheSpaceHierarchy(); void cacheSpaceHierarchy();
void populateSpaceHierarchy(const QString &spaceId); void populateSpaceHierarchy(const QString &spaceId);
NeoChatConnection *m_connection;
}; };