From 8071b192b8cecf0b0f422d74678038dd3afbe3bc Mon Sep 17 00:00:00 2001 From: Hiers <47784553+Hiers@users.noreply.github.com> Date: Sun, 11 Sep 2022 23:05:20 +0000 Subject: Line to indicate first unread message (#1147) * First draft of unread line feature. * Minor visual fix. * Removed unnecessary ternary operator. * Extended unread line functionality to work on minimised window or focusing another window. * Fix for unread line not showing when last read message is hidden. * Minor performance improvement. Fix for misbehaving event2order DB at application start. * Fix for possible performance issues when user has joined a large number of rooms. * Fix for breaking macos and clazy builds. * Changed on windows focus function to refresh unread line if room is unread. * Unread line is removed when user sends a message. * Linting. * Fixed unread line to work in standalone room windows. * Switch isRoomUnread for index 0. * Merged try/catch blocks. * Fix for crash on opening a room invite. * Call fullyReadEventId function when used instead of storing it and passing it through. * Function that was meant to sync the unread line was relying on an async function, oops. * Linting again. * More linting... * Minor changes. --- src/Cache.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 8 deletions(-) (limited to 'src/Cache.cpp') diff --git a/src/Cache.cpp b/src/Cache.cpp index 90e93bed..02b456db 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -1537,6 +1537,21 @@ Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Recei } } +std::string +Cache::getFullyReadEventId(const std::string &room_id) +{ + auto txn = ro_txn(env_); + + if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) { + if (auto fr = + std::get_if>( + &ev.value())) { + return fr->content.event_id; + } + } + return std::string(); +} + void Cache::calculateRoomReadStatus() { @@ -1561,14 +1576,7 @@ Cache::calculateRoomReadStatus(const std::string &room_id) const auto last_event_id = getLastEventId(txn, room_id); const auto localUser = utils::localUser().toStdString(); - std::string fullyReadEventId; - if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) { - if (auto fr = - std::get_if>( - &ev.value())) { - fullyReadEventId = fr->content.event_id; - } - } + std::string fullyReadEventId = getFullyReadEventId(room_id); if (last_event_id.empty() || fullyReadEventId.empty()) return true; @@ -2503,6 +2511,50 @@ Cache::lastInvisibleEventAfter(const std::string &room_id, std::string_view even } } +std::optional> +Cache::lastVisibleEvent(const std::string &room_id, std::string_view event_id) +{ + if (room_id.empty() || event_id.empty()) + return {}; + + auto txn = ro_txn(env_); + lmdb::dbi orderDb; + lmdb::dbi eventOrderDb; + lmdb::dbi timelineDb; + try { + orderDb = getEventToOrderDb(txn, room_id); + eventOrderDb = getEventOrderDb(txn, room_id); + timelineDb = getMessageToOrderDb(txn, room_id); + + std::string_view indexVal; + + bool success = orderDb.get(txn, event_id, indexVal); + if (!success) { + return {}; + } + + uint64_t idx = lmdb::from_sv(indexVal); + std::string evId{event_id}; + + auto cursor = lmdb::cursor::open(txn, eventOrderDb); + if (cursor.get(indexVal, event_id, MDB_SET)) { + do { + evId = nlohmann::json::parse(event_id)["event_id"].get(); + std::string_view temp; + idx = lmdb::from_sv(indexVal); + if (timelineDb.get(txn, evId, temp)) { + return std::pair{idx, evId}; + } + } while (cursor.get(indexVal, event_id, MDB_PREV)); + } + + return std::pair{idx, evId}; + } catch (lmdb::runtime_error &e) { + nhlog::db()->error("Failed to get last visible event after {}", event_id, e.what()); + return {}; + } +} + std::optional Cache::getArrivalIndex(const std::string &room_id, std::string_view event_id) { @@ -5317,6 +5369,12 @@ lastInvisibleEventAfter(const std::string &room_id, std::string_view event_id) return instance_->lastInvisibleEventAfter(room_id, event_id); } +std::optional> +lastVisibleEvent(const std::string &room_id, std::string_view event_id) +{ + return instance_->lastVisibleEvent(room_id, event_id); +} + RoomInfo singleRoomInfo(const std::string &room_id) { @@ -5336,6 +5394,11 @@ getRoomInfo(const std::vector &rooms) //! Calculates which the read status of a room. //! Whether all the events in the timeline have been read. +std::string +getFullyReadEventId(const std::string &room_id) +{ + return instance_->getFullyReadEventId(room_id); +} bool calculateRoomReadStatus(const std::string &room_id) { -- cgit 1.5.1