Sort rooms in completer by 'activity' and make tombstoned rooms italic

pull/1456/head
Nicolas Werner 2 years ago
parent b0e4841caf
commit 7dd3339477
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
  1. 2
      resources/qml/Completer.qml
  2. 36
      src/Cache.cpp
  3. 4
      src/CacheStructs.h
  4. 2
      src/Cache_p.h
  5. 12
      src/CompletionProxyModel.h
  6. 12
      src/RoomsModel.cpp
  7. 1
      src/RoomsModel.h

@ -292,6 +292,7 @@ Control {
text: model.roomName text: model.roomName
font.pixelSize: popup.avatarHeight * 0.5 font.pixelSize: popup.avatarHeight * 0.5
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
font.italic: model.isTombstoned
textFormat: Text.RichText textFormat: Text.RichText
} }
@ -320,6 +321,7 @@ Control {
Label { Label {
text: model.roomName text: model.roomName
color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
font.italic: model.isTombstoned
textFormat: Text.RichText textFormat: Text.RichText
} }

@ -1792,7 +1792,9 @@ Cache::updateState(const std::string &room, const mtx::responses::StateEvents &s
updatedInfo.topic = getRoomTopic(txn, statesdb).toStdString(); updatedInfo.topic = getRoomTopic(txn, statesdb).toStdString();
updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString(); updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
updatedInfo.version = getRoomVersion(txn, statesdb).toStdString(); updatedInfo.version = getRoomVersion(txn, statesdb).toStdString();
updatedInfo.is_space = getRoomIsSpace(txn, statesdb); updatedInfo.is_space = getRoomIsSpace(txn, statesdb);
updatedInfo.is_tombstoned = getRoomIsTombstoned(txn, statesdb);
roomsDb_.put(txn, room, nlohmann::json(updatedInfo).dump()); roomsDb_.put(txn, room, nlohmann::json(updatedInfo).dump());
updateSpaces(txn, {room}, {room}); updateSpaces(txn, {room}, {room});
@ -2558,9 +2560,13 @@ Cache::roomNamesAndAliases()
alias = aliases->content.alias; alias = aliases->content.alias;
} }
result.push_back(RoomNameAlias{.id = std::move(room_id_str), result.push_back(RoomNameAlias{
.id = std::move(room_id_str),
.name = std::move(info.name), .name = std::move(info.name),
.alias = std::move(alias)}); .alias = std::move(alias),
.recent_activity = info.approximate_last_modification_ts,
.is_tombstoned = info.is_tombstoned,
});
} catch (std::exception &e) { } catch (std::exception &e) {
nhlog::db()->warn("Failed to add room {} to result: {}", room_id, e.what()); nhlog::db()->warn("Failed to add room {} to result: {}", room_id, e.what());
} }
@ -3091,6 +3097,28 @@ Cache::getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb)
return false; return false;
} }
bool
Cache::getRoomIsTombstoned(lmdb::txn &txn, lmdb::dbi &statesdb)
{
using namespace mtx::events;
using namespace mtx::events::state;
std::string_view event;
bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
if (res) {
try {
StateEvent<Tombstone> msg = nlohmann::json::parse(event).get<StateEvent<Tombstone>>();
return true;
} catch (const nlohmann::json::exception &e) {
nhlog::db()->warn("failed to parse m.room.tombstone event: {}", e.what());
}
}
return false;
}
QString QString
Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb) Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
{ {
@ -5138,6 +5166,7 @@ to_json(nlohmann::json &j, const RoomInfo &info)
j["version"] = info.version; j["version"] = info.version;
j["is_invite"] = info.is_invite; j["is_invite"] = info.is_invite;
j["is_space"] = info.is_space; j["is_space"] = info.is_space;
j["tombst"] = info.is_tombstoned;
j["join_rule"] = info.join_rule; j["join_rule"] = info.join_rule;
j["guest_access"] = info.guest_access; j["guest_access"] = info.guest_access;
@ -5161,8 +5190,11 @@ from_json(const nlohmann::json &j, RoomInfo &info)
info.avatar_url = j.at("avatar_url").get<std::string>(); info.avatar_url = j.at("avatar_url").get<std::string>();
info.version = j.value( info.version = j.value(
"version", QCoreApplication::translate("RoomInfo", "no version stored").toStdString()); "version", QCoreApplication::translate("RoomInfo", "no version stored").toStdString());
info.is_invite = j.at("is_invite").get<bool>(); info.is_invite = j.at("is_invite").get<bool>();
info.is_space = j.value("is_space", false); info.is_space = j.value("is_space", false);
info.is_tombstoned = j.value("tombst", false);
info.join_rule = j.at("join_rule").get<mtx::events::state::JoinRule>(); info.join_rule = j.at("join_rule").get<mtx::events::state::JoinRule>();
info.guest_access = j.at("guest_access").get<bool>(); info.guest_access = j.at("guest_access").get<bool>();

@ -81,6 +81,8 @@ struct RoomInfo
bool is_invite = false; bool is_invite = false;
//! Wheter or not the room is a space //! Wheter or not the room is a space
bool is_space = false; bool is_space = false;
//! Wheter or not the room has a tombstone event
bool is_tombstoned = false;
//! Total number of members in the room. //! Total number of members in the room.
size_t member_count = 0; size_t member_count = 0;
//! Who can access to the room. //! Who can access to the room.
@ -106,6 +108,8 @@ from_json(const nlohmann::json &j, RoomInfo &info);
struct RoomNameAlias struct RoomNameAlias
{ {
std::string id, name, alias; std::string id, name, alias;
std::uint64_t recent_activity;
bool is_tombstoned;
}; };
//! Basic information per member. //! Basic information per member.

@ -84,6 +84,8 @@ public:
QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb); QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Retrieve if the room is a space //! Retrieve if the room is a space
bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb); bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Retrieve if the room is tombstoned (closed or replaced by a different room)
bool getRoomIsTombstoned(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Get a specific state event //! Get a specific state event
template<typename T> template<typename T>

@ -8,6 +8,8 @@
#include <QAbstractProxyModel> #include <QAbstractProxyModel>
#include <algorithm>
enum class ElementRank enum class ElementRank
{ {
first, first,
@ -17,7 +19,7 @@ enum class ElementRank
template<typename Key, typename Value> template<typename Key, typename Value>
struct trie struct trie
{ {
std::vector<Value> values; std::vector<std::pair<ElementRank, Value>> values;
std::map<Key, trie> next; std::map<Key, trie> next;
template<ElementRank r> template<ElementRank r>
@ -29,9 +31,11 @@ struct trie
} }
if constexpr (r == ElementRank::first) { if constexpr (r == ElementRank::first) {
t->values.insert(t->values.begin(), v); auto it =
std::ranges::upper_bound(t->values, r, {}, &std::pair<ElementRank, Value>::first);
t->values.emplace(it, r, v);
} else if constexpr (r == ElementRank::second) { } else if constexpr (r == ElementRank::second) {
t->values.push_back(v); t->values.emplace_back(r, v);
} }
} }
@ -45,7 +49,7 @@ struct trie
if (ret.size() >= limit) if (ret.size() >= limit)
return ret; return ret;
else else
ret.push_back(v); ret.push_back(v.second);
} }
for (const auto &[k, t] : next) { for (const auto &[k, t] : next) {

@ -20,18 +20,24 @@ RoomsModel::RoomsModel(bool showOnlyRoomWithAliases, QObject *parent)
if (showOnlyRoomWithAliases_) if (showOnlyRoomWithAliases_)
utils::erase_if(rooms, [](auto &r) { return r.alias.empty(); }); utils::erase_if(rooms, [](auto &r) { return r.alias.empty(); });
std::ranges::sort(rooms,
[](auto &a, auto &b) { return a.recent_activity > b.recent_activity; });
} }
QHash<int, QByteArray> QHash<int, QByteArray>
RoomsModel::roleNames() const RoomsModel::roleNames() const
{ {
return {{CompletionModel::CompletionRole, "completionRole"}, return {
{CompletionModel::CompletionRole, "completionRole"},
{CompletionModel::SearchRole, "searchRole"}, {CompletionModel::SearchRole, "searchRole"},
{CompletionModel::SearchRole2, "searchRole2"}, {CompletionModel::SearchRole2, "searchRole2"},
{Roles::RoomAlias, "roomAlias"}, {Roles::RoomAlias, "roomAlias"},
{Roles::AvatarUrl, "avatarUrl"}, {Roles::AvatarUrl, "avatarUrl"},
{Roles::RoomID, "roomid"}, {Roles::RoomID, "roomid"},
{Roles::RoomName, "roomName"}}; {Roles::RoomName, "roomName"},
{Roles::IsTombstoned, "isTombstoned"},
};
} }
QVariant QVariant
@ -62,6 +68,8 @@ RoomsModel::data(const QModelIndex &index, int role) const
cache::client()->singleRoomInfo(rooms[index.row()].id).avatar_url); cache::client()->singleRoomInfo(rooms[index.row()].id).avatar_url);
case Roles::RoomID: case Roles::RoomID:
return QString::fromStdString(rooms[index.row()].id).toHtmlEscaped(); return QString::fromStdString(rooms[index.row()].id).toHtmlEscaped();
case Roles::IsTombstoned:
return rooms[index.row()].is_tombstoned;
} }
} }
return {}; return {};

@ -18,6 +18,7 @@ public:
RoomAlias, RoomAlias,
RoomID, RoomID,
RoomName, RoomName,
IsTombstoned,
}; };
RoomsModel(bool showOnlyRoomWithAliases = false, QObject *parent = nullptr); RoomsModel(bool showOnlyRoomWithAliases = false, QObject *parent = nullptr);

Loading…
Cancel
Save