diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-24 01:12:01 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2023-10-24 01:12:01 +0200 |
commit | a0a49b6c2a3cf48cb4e979a92cd2065a51bff775 (patch) | |
tree | f9316cc3a1c3ceca6c875bc166a528b9cab03385 /src | |
parent | Merge branch 'ignore-users' of github.com:NepNep21/nheko into ignore-users (diff) | |
download | nheko-a0a49b6c2a3cf48cb4e979a92cd2065a51bff775.tar.xz |
Cleanup ignore user functionality slightly
Diffstat (limited to 'src')
-rw-r--r-- | src/ChatPage.cpp | 53 | ||||
-rw-r--r-- | src/timeline/TimelineModel.cpp | 12 | ||||
-rw-r--r-- | src/timeline/TimelineModel.h | 6 | ||||
-rw-r--r-- | src/timeline/TimelineViewManager.h | 3 | ||||
-rw-r--r-- | src/ui/UserProfile.cpp | 58 | ||||
-rw-r--r-- | src/ui/UserProfile.h | 7 |
6 files changed, 98 insertions, 41 deletions
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 90d542dd..e63135a9 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -6,6 +6,9 @@ #include <QInputDialog> #include <QMessageBox> +#include <algorithm> +#include <unordered_set> + #include <mtx/responses.hpp> #include "AvatarProvider.h" @@ -21,7 +24,6 @@ #include "encryption/DeviceVerificationFlow.h" #include "encryption/Olm.h" #include "ui/RoomSummary.h" -#include "ui/Theme.h" #include "ui/UserProfile.h" #include "voip/CallManager.h" @@ -29,8 +31,6 @@ #include "timeline/TimelineViewManager.h" -#include "blurhash.hpp" - ChatPage *ChatPage::instance_ = nullptr; static constexpr int CHECK_CONNECTIVITY_INTERVAL = 15'000; static constexpr int RETRY_TIMEOUT = 5'000; @@ -765,6 +765,23 @@ ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string // Ensure that we have enough one-time keys available. ensureOneTimeKeyCount(res.device_one_time_keys_count, res.device_unused_fallback_key_types); + std::optional<mtx::events::account_data::IgnoredUsers> oldIgnoredUsers; + if (auto ignoreEv = std::ranges::find_if( + res.account_data.events, + [](const mtx::events::collections::RoomAccountDataEvents &e) { + return std::holds_alternative< + mtx::events::AccountDataEvent<mtx::events::account_data::IgnoredUsers>>(e); + }); + ignoreEv != res.account_data.events.end()) { + if (auto oldEv = cache::client()->getAccountData(mtx::events::EventType::IgnoredUsers)) + oldIgnoredUsers = + std::get<mtx::events::AccountDataEvent<mtx::events::account_data::IgnoredUsers>>( + *oldEv) + .content; + else + oldIgnoredUsers = mtx::events::account_data::IgnoredUsers{}; + } + // TODO: fine grained error handling try { cache::client()->saveState(res); @@ -773,6 +790,36 @@ ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string auto updates = cache::getRoomInfo(cache::client()->roomsWithStateUpdates(res)); emit syncUI(std::move(res)); + + // if the ignored users changed, clear timeline of all affected rooms. + if (oldIgnoredUsers) { + if (auto newEv = + cache::client()->getAccountData(mtx::events::EventType::IgnoredUsers)) { + std::vector<mtx::events::account_data::IgnoredUser> changedUsers{}; + std::ranges::set_symmetric_difference( + oldIgnoredUsers->users, + std::get<mtx::events::AccountDataEvent<mtx::events::account_data::IgnoredUsers>>( + *newEv) + .content.users, + std::back_inserter(changedUsers), + {}, + &mtx::events::account_data::IgnoredUser::id, + &mtx::events::account_data::IgnoredUser::id); + + std::unordered_set<std::string> roomsToReload; + for (const auto &user : changedUsers) { + auto commonRooms = cache::client()->getCommonRooms(user.id); + for (const auto &room : commonRooms) + roomsToReload.insert(room.first); + } + + for (const auto &room : roomsToReload) { + if (auto model = + view_manager_->rooms()->getRoomById(QString::fromStdString(room))) + model->clearTimeline(); + } + } + } } catch (const lmdb::map_full_error &e) { nhlog::db()->error("lmdb is full: {}", e.what()); cache::deleteOldData(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index d85a9516..e8a0a507 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -521,8 +521,6 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj cache::client()->updateState(room_id_.toStdString(), events_, true); this->syncState({std::move(events_.events)}); }); - - connect(this, &TimelineModel::ignoredUser, this, &TimelineModel::handleIgnoredUser); } QHash<int, QByteArray> @@ -2223,16 +2221,6 @@ TimelineModel::scrollTimerEvent() } void -TimelineModel::handleIgnoredUser(const QString &id, const std::optional<QString> &err) -{ - if (err) { - MainWindow::instance()->showNotification(tr("Failed to ignore \"%1\": %2").arg(id, *err)); - } else { - this->clearTimeline(); - } -} - -void TimelineModel::requestKeyForEvent(const QString &id) { auto encrypted_event = events.get(id.toStdString(), "", false); diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index eefe921f..4ffd61ec 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -18,8 +18,6 @@ #include "CacheStructs.h" #include "EventStore.h" #include "InputBar.h" -#include "InviteesModel.h" -#include "MemberList.h" #include "Permissions.h" #include "ReadReceiptsModel.h" #include "ui/RoomSummary.h" @@ -463,7 +461,6 @@ public slots: private slots: void addPendingMessage(mtx::events::collections::TimelineEvents event); void scrollTimerEvent(); - void handleIgnoredUser(const QString &id, const std::optional<QString> &err); signals: void dataAtIdChanged(QString id); @@ -513,9 +510,6 @@ signals: void fetchedMore(); - // The user may close the profile window before we receive a response, so handle it here - void ignoredUser(const QString &id, const std::optional<QString> &err); - private: template<typename T> void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType); diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 6a825b6f..b4e176cd 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -11,7 +11,8 @@ #include <mtx/common.hpp> #include <mtx/responses/messages.hpp> -#include "ReadReceiptsModel.h" +#include "InviteesModel.h" +#include "MemberList.h" #include "timeline/CommunitiesModel.h" #include "timeline/PresenceEmitter.h" #include "timeline/RoomlistModel.h" diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp index 3b2375ad..1b66a97d 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp @@ -11,11 +11,11 @@ #include "Cache_p.h" #include "ChatPage.h" #include "Logging.h" +#include "MainWindow.h" +#include "MatrixClient.h" #include "UserProfile.h" #include "Utils.h" -#include "encryption/DeviceVerificationFlow.h" #include "encryption/VerificationManager.h" -#include "mtx/responses/crypto.hpp" #include "timeline/TimelineModel.h" #include "timeline/TimelineViewManager.h" #include "ui/UIA.h" @@ -64,6 +64,19 @@ UserProfile::UserProfile(const QString &roomid, new RoomInfoModel(cache::client()->getCommonRooms(userid.toStdString()), this); else sharedRooms_ = new RoomInfoModel({}, this); + + connect(ChatPage::instance(), &ChatPage::syncUI, this, [this](const mtx::responses::Sync &res) { + if (auto ignoreEv = std::ranges::find_if( + res.account_data.events, + [](const mtx::events::collections::RoomAccountDataEvents &e) { + return std::holds_alternative< + mtx::events::AccountDataEvent<mtx::events::account_data::IgnoredUsers>>(e); + }); + ignoreEv != res.account_data.events.end()) { + // doesn't matter much if it was actually us + emit ignoredChanged(); + } + }); } QHash<int, QByteArray> @@ -224,34 +237,45 @@ UserProfile::refreshDevices() fetchDeviceList(this->userid_); } +bool +UserProfile::ignored() const +{ + auto old = TimelineViewManager::instance()->getIgnoredUsers(); + return old.contains(userid_); +} + void -UserProfile::ignoredStatus(const QString &id, const bool ignore) +UserProfile::setIgnored(bool ignore) { auto old = TimelineViewManager::instance()->getIgnoredUsers(); if (ignore) { - if (old.contains(id)) { - emit this->room()->ignoredUser(id, tr("Already ignored")); + if (old.contains(userid_)) { + emit ignoredChanged(); return; } - old.append(id); + old.append(userid_); } else { - old.removeOne(id); + if (!old.contains(userid_)) { + emit ignoredChanged(); + return; + } + old.removeAll(userid_); } std::vector<mtx::events::account_data::IgnoredUser> content; - for (const QString &item : old) { - const mtx::events::account_data::IgnoredUser data{.id = item.toStdString()}; - content.push_back(data); + for (const QString &item : std::as_const(old)) { + content.emplace_back(item.toStdString()); } - const mtx::events::account_data::IgnoredUsers payload{.users{content}}; + mtx::events::account_data::IgnoredUsers payload{.users{content}}; + + auto userid = userid_; - http::client()->put_account_data(payload, [this, id, ignore](mtx::http::RequestErr e) { - if (ignore) { - emit this->room()->ignoredUser( - id, e ? std::optional(QString::fromStdString(e->matrix_error.error)) : std::nullopt); - } else if (e) { - emit this->unignoredUserError(id, QString::fromStdString(e->matrix_error.error)); + http::client()->put_account_data(payload, [userid](mtx::http::RequestErr e) { + if (e) { + MainWindow::instance()->showNotification( + tr("Failed to ignore \"%1\": %2") + .arg(userid, QString::fromStdString(e->matrix_error.error))); } }); } diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h index 1affe8bd..bc5b6a35 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h @@ -157,6 +157,7 @@ class UserProfile final : public QObject Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged) Q_PROPERTY(bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged) + Q_PROPERTY(bool ignored READ ignored WRITE setIgnored NOTIFY ignoredChanged) Q_PROPERTY(bool isSelf READ isSelf CONSTANT) Q_PROPERTY(TimelineModel *room READ room CONSTANT) public: @@ -184,7 +185,6 @@ public: Q_INVOKABLE void refreshDevices(); Q_INVOKABLE void banUser(); Q_INVOKABLE void signOutDevice(const QString &deviceID); - Q_INVOKABLE void ignoredStatus(const QString &id, const bool ignore); Q_INVOKABLE void kickUser(); Q_INVOKABLE void startChat(); Q_INVOKABLE void startChat(bool encryptionEnabled); @@ -193,6 +193,9 @@ public: Q_INVOKABLE void changeAvatar(); Q_INVOKABLE void openGlobalProfile(); + void setIgnored(bool ignored); + bool ignored() const; + signals: void userStatusChanged(); void loadingChanged(); @@ -201,7 +204,7 @@ signals: void displayError(const QString &errorMessage); void globalUsernameRetrieved(const QString &globalUser); void devicesChanged(); - void unignoredUserError(const QString &id, const QVariant &err); + void ignoredChanged(); // internal void verificationStatiChanged(); |