mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 20:48:52 +03:00
Make notification count calculation more efficient
This commit is contained in:
parent
f76fd4ca83
commit
7b33d14277
6 changed files with 103 additions and 89 deletions
|
@ -71,30 +71,20 @@ Page {
|
|||
property color unimportantText: Nheko.colors.buttonText
|
||||
property color bubbleBackground: Nheko.colors.highlight
|
||||
property color bubbleText: Nheko.colors.highlightedText
|
||||
required property string avatarUrl
|
||||
required property string displayName
|
||||
required property string tooltip
|
||||
required property bool collapsed
|
||||
required property bool collapsible
|
||||
required property bool hidden
|
||||
required property int depth
|
||||
required property string id
|
||||
required property int unreadMessages
|
||||
required property bool hasLoudNotification
|
||||
required property bool muted
|
||||
required property var model
|
||||
|
||||
height: avatarSize + 2 * Nheko.paddingMedium
|
||||
width: ListView.view.width
|
||||
state: "normal"
|
||||
ToolTip.visible: hovered && collapsed
|
||||
ToolTip.text: communityItem.tooltip
|
||||
ToolTip.text: model.tooltip
|
||||
ToolTip.delay: Nheko.tooltipDelay
|
||||
onClicked: Communities.setCurrentTagId(communityItem.id)
|
||||
onPressAndHold: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted)
|
||||
onClicked: Communities.setCurrentTagId(model.id)
|
||||
onPressAndHold: communityContextMenu.show(model.id, model.hidden, model.muted)
|
||||
states: [
|
||||
State {
|
||||
name: "highlight"
|
||||
when: (communityItem.hovered || communityItem.hidden) && !(Communities.currentTagId === communityItem.id)
|
||||
when: (communityItem.hovered || model.hidden) && !(Communities.currentTagId === model.id)
|
||||
|
||||
PropertyChanges {
|
||||
target: communityItem
|
||||
|
@ -108,7 +98,7 @@ Page {
|
|||
},
|
||||
State {
|
||||
name: "selected"
|
||||
when: Communities.currentTagId == communityItem.id
|
||||
when: Communities.currentTagId == model.id
|
||||
|
||||
PropertyChanges {
|
||||
target: communityItem
|
||||
|
@ -127,7 +117,7 @@ Page {
|
|||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.RightButton
|
||||
onSingleTapped: communityContextMenu.show(communityItem.id, communityItem.hidden, communityItem.muted)
|
||||
onSingleTapped: communityContextMenu.show(model.id, model.hidden, model.muted)
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
|
||||
}
|
||||
|
@ -139,27 +129,27 @@ Page {
|
|||
spacing: Nheko.paddingMedium
|
||||
anchors.fill: parent
|
||||
anchors.margins: Nheko.paddingMedium
|
||||
anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * communityItem.depth))
|
||||
anchors.leftMargin: Nheko.paddingMedium + (communitySidebar.collapsed ? 0 : (fontMetrics.lineSpacing * model.depth))
|
||||
|
||||
ImageButton {
|
||||
visible: !communitySidebar.collapsed && communityItem.collapsible
|
||||
visible: !communitySidebar.collapsed && model.collapsible
|
||||
Layout.preferredHeight: fontMetrics.lineSpacing
|
||||
Layout.preferredWidth: fontMetrics.lineSpacing
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
height: fontMetrics.lineSpacing
|
||||
width: fontMetrics.lineSpacing
|
||||
image: communityItem.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg"
|
||||
image: model.collapsed ? ":/icons/icons/ui/collapsed.svg" : ":/icons/icons/ui/expanded.svg"
|
||||
ToolTip.visible: hovered
|
||||
ToolTip.delay: Nheko.tooltipDelay
|
||||
ToolTip.text: communityItem.collapsed ? qsTr("Expand") : qsTr("Collapse")
|
||||
ToolTip.text: model.collapsed ? qsTr("Expand") : qsTr("Collapse")
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: communityItem.collapsed = !communityItem.collapsed
|
||||
onClicked: model.collapsed = !model.collapsed
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: fontMetrics.lineSpacing
|
||||
visible: !communitySidebar.collapsed && !communityItem.collapsible && Communities.containsSubspaces
|
||||
visible: !communitySidebar.collapsed && !model.collapsible && Communities.containsSubspaces
|
||||
}
|
||||
|
||||
Avatar {
|
||||
|
@ -170,22 +160,22 @@ Page {
|
|||
height: avatarSize
|
||||
width: avatarSize
|
||||
url: {
|
||||
if (communityItem.avatarUrl.startsWith("mxc://"))
|
||||
return communityItem.avatarUrl.replace("mxc://", "image://MxcImage/");
|
||||
if (model.avatarUrl.startsWith("mxc://"))
|
||||
return model.avatarUrl.replace("mxc://", "image://MxcImage/");
|
||||
else
|
||||
return "image://colorimage/" + communityItem.avatarUrl + "?" + communityItem.unimportantText;
|
||||
return "image://colorimage/" + model.avatarUrl + "?" + communityItem.unimportantText;
|
||||
}
|
||||
roomid: communityItem.id
|
||||
displayName: communityItem.displayName
|
||||
roomid: model.id
|
||||
displayName: model.displayName
|
||||
color: communityItem.backgroundColor
|
||||
|
||||
NotificationBubble {
|
||||
notificationCount: communityItem.unreadMessages
|
||||
hasLoudNotification: communityItem.hasLoudNotification
|
||||
notificationCount: model.unreadMessages
|
||||
hasLoudNotification: model.hasLoudNotification
|
||||
bubbleBackgroundColor: communityItem.bubbleBackground
|
||||
bubbleTextColor: communityItem.bubbleText
|
||||
font.pixelSize: fontMetrics.font.pixelSize * 0.6
|
||||
mayBeVisible: communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications
|
||||
mayBeVisible: communitySidebar.collapsed && !model.muted && Settings.spaceNotifications
|
||||
anchors.right: avatar.right
|
||||
anchors.bottom: avatar.bottom
|
||||
anchors.margins: -Nheko.paddingSmall
|
||||
|
@ -199,7 +189,7 @@ Page {
|
|||
color: communityItem.importantText
|
||||
Layout.fillWidth: true
|
||||
elideWidth: width
|
||||
fullText: communityItem.displayName
|
||||
fullText: model.displayName
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
|
@ -208,11 +198,11 @@ Page {
|
|||
}
|
||||
|
||||
NotificationBubble {
|
||||
notificationCount: communityItem.unreadMessages
|
||||
hasLoudNotification: communityItem.hasLoudNotification
|
||||
notificationCount: model.unreadMessages
|
||||
hasLoudNotification: model.hasLoudNotification
|
||||
bubbleBackgroundColor: communityItem.bubbleBackground
|
||||
bubbleTextColor: communityItem.bubbleText
|
||||
mayBeVisible: !communitySidebar.collapsed && !communityItem.muted && Settings.spaceNotifications
|
||||
mayBeVisible: !communitySidebar.collapsed && !model.muted && Settings.spaceNotifications
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.leftMargin: Nheko.paddingSmall
|
||||
}
|
||||
|
|
|
@ -881,21 +881,3 @@ utils::markRoomAsDirect(QString roomid, std::vector<RoomMember> members)
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
QPair<int, int>
|
||||
utils::getChildNotificationsForSpace(const QString &spaceId)
|
||||
{
|
||||
auto children = cache::getRoomInfo(cache::client()->getChildRoomIds(spaceId.toStdString()));
|
||||
QPair<int, int> retVal;
|
||||
for (const auto &[childId, child] : children) {
|
||||
if (child.is_space) {
|
||||
auto temp{utils::getChildNotificationsForSpace(childId)};
|
||||
retVal.first += temp.first;
|
||||
retVal.second += temp.second;
|
||||
} else {
|
||||
retVal.first += child.notification_count;
|
||||
retVal.second += child.highlight_count;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -311,9 +311,4 @@ removeDirectFromRoom(QString roomid);
|
|||
|
||||
void
|
||||
markRoomAsDirect(QString roomid, std::vector<RoomMember> members);
|
||||
|
||||
//! Returns a pair of integers representing the unread notifications in a space and how many of them
|
||||
//! are loud notifications, respectively.
|
||||
QPair<int, int>
|
||||
getChildNotificationsForSpace(const QString &spaceId);
|
||||
}
|
||||
|
|
|
@ -208,9 +208,15 @@ CommunitiesModel::data(const QModelIndex &index, int role) const
|
|||
case CommunitiesModel::Roles::Id:
|
||||
return "tag:" + tag;
|
||||
case CommunitiesModel::Roles::UnreadMessages:
|
||||
return (int)tagNotificationCache.at(tag).notification_count;
|
||||
if (auto it = tagNotificationCache.find(tag); it != tagNotificationCache.end())
|
||||
return (int)it->second.notification_count;
|
||||
else
|
||||
return 0;
|
||||
case CommunitiesModel::Roles::HasLoudNotification:
|
||||
return (int)tagNotificationCache.at(tag).highlight_count > 0;
|
||||
if (auto it = tagNotificationCache.find(tag); it != tagNotificationCache.end())
|
||||
return it->second.highlight_count > 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
|
@ -265,6 +271,21 @@ CommunitiesModel::initializeSidebar()
|
|||
tags_.clear();
|
||||
spaceOrder_.tree.clear();
|
||||
spaces_.clear();
|
||||
tagNotificationCache.clear();
|
||||
globalUnreads.notification_count = {};
|
||||
dmUnreads.notification_count = {};
|
||||
|
||||
auto e = cache::client()->getAccountData(mtx::events::EventType::Direct);
|
||||
if (e) {
|
||||
if (auto event =
|
||||
std::get_if<mtx::events::AccountDataEvent<mtx::events::account_data::Direct>>(
|
||||
&e.value())) {
|
||||
directMessages_.clear();
|
||||
for (const auto &[userId, roomIds] : event->content.user_to_rooms)
|
||||
for (const auto &roomId : roomIds)
|
||||
directMessages_.push_back(roomId);
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::string> ts;
|
||||
|
||||
|
@ -284,6 +305,19 @@ CommunitiesModel::initializeSidebar()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &t : it->tags) {
|
||||
auto tagId = QString::fromStdString(t);
|
||||
auto &tNs = tagNotificationCache[tagId];
|
||||
tNs.notification_count += it->notification_count;
|
||||
tNs.highlight_count += it->highlight_count;
|
||||
}
|
||||
|
||||
auto &e = roomNotificationCache[it.key()];
|
||||
e.highlight_count = it->highlight_count;
|
||||
e.notification_count = it->notification_count;
|
||||
globalUnreads.notification_count += it->notification_count;
|
||||
globalUnreads.highlight_count += it->highlight_count;
|
||||
}
|
||||
|
||||
// NOTE(Nico): We build a forrest from the Directed Cyclic(!) Graph of spaces. To do that we
|
||||
|
@ -319,6 +353,14 @@ CommunitiesModel::initializeSidebar()
|
|||
|
||||
spaceOrder_.restoreCollapsed();
|
||||
|
||||
for (auto &space : spaceOrder_.tree) {
|
||||
for (const auto &c : cache::client()->getChildRoomIds(space.id.toStdString())) {
|
||||
const auto &counts = roomNotificationCache[QString::fromStdString(c)];
|
||||
space.notificationCounts.highlight_count += counts.highlight_count;
|
||||
space.notificationCounts.notification_count += counts.notification_count;
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
emit tagsChanged();
|
||||
|
@ -414,15 +456,20 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
|
|||
}
|
||||
|
||||
auto roomId = QString::fromStdString(roomid);
|
||||
auto oldUnreads = roomNotificationCache[roomId];
|
||||
int notificationCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
|
||||
static_cast<int64_t>(room.unread_notifications.highlight_count);
|
||||
int highlightCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
|
||||
auto &oldUnreads = roomNotificationCache[roomId];
|
||||
auto notificationCDiff = -static_cast<int64_t>(oldUnreads.notification_count) +
|
||||
static_cast<int64_t>(room.unread_notifications.notification_count);
|
||||
auto highlightCDiff = -static_cast<int64_t>(oldUnreads.highlight_count) +
|
||||
static_cast<int64_t>(room.unread_notifications.highlight_count);
|
||||
|
||||
auto applyDiff = [notificationCDiff,
|
||||
highlightCDiff](mtx::responses::UnreadNotifications &n) {
|
||||
n.highlight_count = static_cast<int64_t>(n.highlight_count) + highlightCDiff;
|
||||
n.notification_count = static_cast<int64_t>(n.notification_count) + notificationCDiff;
|
||||
};
|
||||
if (highlightCDiff || notificationCDiff) {
|
||||
// bool hidden = hiddenTagIds_.contains(roomId);
|
||||
globalUnreads.notification_count += notificationCDiff;
|
||||
globalUnreads.highlight_count += highlightCDiff;
|
||||
applyDiff(globalUnreads);
|
||||
emit dataChanged(index(0),
|
||||
index(0),
|
||||
{
|
||||
|
@ -431,8 +478,7 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
|
|||
});
|
||||
if (std::find(begin(directMessages_), end(directMessages_), roomid) !=
|
||||
end(directMessages_)) {
|
||||
dmUnreads.notification_count += notificationCDiff;
|
||||
dmUnreads.highlight_count += highlightCDiff;
|
||||
applyDiff(dmUnreads);
|
||||
emit dataChanged(index(1),
|
||||
index(1),
|
||||
{
|
||||
|
@ -446,11 +492,8 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
|
|||
|
||||
for (const auto &t : tags) {
|
||||
auto tagId = QString::fromStdString(t);
|
||||
auto &tNs = tagNotificationCache[tagId];
|
||||
tNs.notification_count += notificationCDiff;
|
||||
tNs.highlight_count += highlightCDiff;
|
||||
applyDiff(tagNotificationCache[tagId]);
|
||||
int idx = tags_.indexOf(tagId) + 2 + spaceOrder_.size();
|
||||
;
|
||||
emit dataChanged(index(idx),
|
||||
index(idx),
|
||||
{
|
||||
|
@ -463,8 +506,10 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
|
|||
auto spaceId = QString::fromStdString(s);
|
||||
|
||||
for (int i = 0; i < spaceOrder_.size(); i++) {
|
||||
spaceOrder_.tree[i].notificationCounts.notification_count += notificationCDiff;
|
||||
spaceOrder_.tree[i].notificationCounts.highlight_count += highlightCDiff;
|
||||
if (spaceOrder_.tree[i].id != spaceId)
|
||||
continue;
|
||||
|
||||
applyDiff(spaceOrder_.tree[i].notificationCounts);
|
||||
|
||||
int idx = i;
|
||||
do {
|
||||
|
@ -474,10 +519,13 @@ CommunitiesModel::sync(const mtx::responses::Sync &sync_)
|
|||
UnreadMessages,
|
||||
HasLoudNotification,
|
||||
});
|
||||
idx = spaceOrder_.parent(idx);
|
||||
} while (idx != -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roomNotificationCache[roomId] = room.unread_notifications;
|
||||
}
|
||||
for (const auto &[roomid, room] : sync_.rooms.leave) {
|
||||
(void)room;
|
||||
|
|
|
@ -642,15 +642,18 @@ RoomlistModel::clear()
|
|||
}
|
||||
|
||||
void
|
||||
RoomlistModel::joinPreview(QString roomid, QString parentSpace)
|
||||
RoomlistModel::joinPreview(QString roomid)
|
||||
{
|
||||
if (previewedRooms.contains(roomid)) {
|
||||
std::vector<std::string> vias;
|
||||
auto parents = cache::client()->getParentRoomIds(roomid.toStdString());
|
||||
for (const auto &p : parents) {
|
||||
auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
|
||||
parentSpace.toStdString(), roomid.toStdString());
|
||||
ChatPage::instance()->joinRoomVia(
|
||||
roomid.toStdString(),
|
||||
(child && child->content.via) ? child->content.via.value() : std::vector<std::string>{},
|
||||
false);
|
||||
p, roomid.toStdString());
|
||||
if (child && child->content.via)
|
||||
vias.insert(vias.end(), child->content.via->begin(), child->content.via->end());
|
||||
}
|
||||
ChatPage::instance()->joinRoomVia(roomid.toStdString(), vias, false);
|
||||
}
|
||||
}
|
||||
void
|
||||
|
|
|
@ -105,7 +105,7 @@ public slots:
|
|||
|
||||
return -1;
|
||||
}
|
||||
void joinPreview(QString roomid, QString parentSpace);
|
||||
void joinPreview(QString roomid);
|
||||
void acceptInvite(QString roomid);
|
||||
void declineInvite(QString roomid);
|
||||
void leave(QString roomid, QString reason = "");
|
||||
|
@ -169,11 +169,7 @@ public slots:
|
|||
{
|
||||
return mapFromSource(roomlistmodel->index(roomlistmodel->roomidToIndex(roomid))).row();
|
||||
}
|
||||
void joinPreview(QString roomid)
|
||||
{
|
||||
roomlistmodel->joinPreview(roomid,
|
||||
filterType == FilterBy::Space ? filterStr : QLatin1String(""));
|
||||
}
|
||||
void joinPreview(QString roomid) { roomlistmodel->joinPreview(roomid); }
|
||||
void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
|
||||
void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
|
||||
void leave(QString roomid, QString reason = "") { roomlistmodel->leave(roomid, reason); }
|
||||
|
|
Loading…
Reference in a new issue