// SPDX-FileCopyrightText: Tobias Fella // SPDX-License-Identifier: GPL-2.0-or-later #include "devicesmodel.h" #include "controller.h" #include "jobs/neochatdeletedevicejob.h" #include #include #include #include #include #include using namespace Quotient; DevicesModel::DevicesModel(QObject *parent) : QAbstractListModel(parent) { } void DevicesModel::fetchDevices() { if (Controller::instance().activeConnection()) { auto job = Controller::instance().activeConnection()->callApi(); connect(job, &BaseJob::success, this, [this, job]() { beginResetModel(); m_devices = job->devices(); endResetModel(); Q_EMIT countChanged(); }); } } QVariant DevicesModel::data(const QModelIndex &index, int role) const { if (index.row() < 0 || index.row() >= rowCount(QModelIndex())) { return {}; } const auto &device = m_devices[index.row()]; switch (role) { case Id: return device.deviceId; case DisplayName: return device.displayName; case LastIp: return device.lastSeenIp; case LastTimestamp: if (device.lastSeenTs) { return *device.lastSeenTs; } else { return false; } case TimestampString: if (device.lastSeenTs) { return QDateTime::fromMSecsSinceEpoch(*device.lastSeenTs).toString(QLocale().dateTimeFormat(QLocale::ShortFormat)); } else { return false; } case Type: if (device.deviceId == m_connection->deviceId()) { return This; } if (!m_connection->isKnownE2eeCapableDevice(m_connection->userId(), device.deviceId)) { return Unencrypted; } if (m_connection->isVerifiedDevice(m_connection->userId(), device.deviceId)) { return Verified; } else { return Unverified; } } return {}; } int DevicesModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_devices.size(); } QHash DevicesModel::roleNames() const { return { {Id, "id"}, {DisplayName, "displayName"}, {LastIp, "lastIp"}, {LastTimestamp, "lastTimestamp"}, {TimestampString, "timestamp"}, {Type, "type"}, }; } void DevicesModel::logout(const QString &deviceId, const QString &password) { int index; for (index = 0; m_devices[index].deviceId != deviceId; index++) ; auto job = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId); connect(job, &BaseJob::result, this, [this, job, password, index] { auto onSuccess = [this, index]() { beginRemoveRows(QModelIndex(), index, index); m_devices.remove(index); endRemoveRows(); Q_EMIT countChanged(); }; if (job->error() != BaseJob::Success) { QJsonObject replyData = job->jsonData(); QJsonObject authData; authData["session"_ls] = replyData["session"_ls]; authData["password"_ls] = password; authData["type"_ls] = "m.login.password"_ls; QJsonObject identifier = {{"type"_ls, "m.id.user"_ls}, {"user"_ls, Controller::instance().activeConnection()->user()->id()}}; authData["identifier"_ls] = identifier; auto *innerJob = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId, authData); connect(innerJob, &BaseJob::success, this, onSuccess); } else { onSuccess(); } }); } void DevicesModel::setName(const QString &deviceId, const QString &name) { int index; for (index = 0; m_devices[index].deviceId != deviceId; index++); auto job = Controller::instance().activeConnection()->callApi(m_devices[index].deviceId, name); QString oldName = m_devices[index].displayName; beginResetModel(); m_devices[index].displayName = name; endResetModel(); connect(job, &BaseJob::failure, this, [this, index, oldName]() { beginResetModel(); m_devices[index].displayName = oldName; endResetModel(); }); } Connection *DevicesModel::connection() const { return m_connection; } void DevicesModel::setConnection(Connection *connection) { if (m_connection) { disconnect(m_connection, nullptr, this, nullptr); } m_connection = connection; Q_EMIT connectionChanged(); fetchDevices(); connect(m_connection, &Connection::sessionVerified, this, [this](const QString &userId, const QString &deviceId) { Q_UNUSED(deviceId); if (userId == Controller::instance().activeConnection()->userId()) { fetchDevices(); } }); connect(m_connection, &Connection::finishedQueryingKeys, this, [this]() { fetchDevices(); }); } #include "moc_devicesmodel.cpp"