nyxmuks/pkg/hicli/database/unread.go
2024-10-18 00:57:27 +03:00

84 lines
2.5 KiB
Go

// Copyright (c) 2024 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package database
import (
"context"
"maunium.net/go/mautrix/id"
)
const (
// TODO find out if this needs to be wrapped in another query that limits the number of events it evaluates
// (or maybe the timeline store just shouldn't be allowed to grow that big?)
calculateUnreadsQuery = `
SELECT
COALESCE(SUM(CASE WHEN unread_type & 0100 THEN 1 ELSE 0 END), 0) AS highlights,
COALESCE(SUM(CASE WHEN unread_type & 0010 THEN 1 ELSE 0 END), 0) AS notifications,
COALESCE(SUM(CASE WHEN unread_type & 0001 THEN 1 ELSE 0 END), 0) AS messages
FROM timeline
JOIN event ON event.rowid = timeline.event_rowid
WHERE timeline.room_id = $1 AND timeline.rowid > (
SELECT MAX(rowid)
FROM timeline
WHERE room_id = $1 AND event_rowid IN (
SELECT event.rowid
FROM receipt
JOIN event ON receipt.event_id=event.event_id
WHERE receipt.room_id = $1 AND receipt.user_id = $2
)
) AND unread_type > 0 AND redacted_by IS NULL
`
)
func (rq *RoomQuery) CalculateUnreads(ctx context.Context, roomID id.RoomID, userID id.UserID) (uc UnreadCounts, err error) {
err = rq.GetDB().QueryRow(ctx, calculateUnreadsQuery, roomID, userID).
Scan(&uc.UnreadHighlights, &uc.UnreadNotifications, &uc.UnreadMessages)
return
}
type UnreadType int
func (ut UnreadType) Is(flag UnreadType) bool {
return ut&flag != 0
}
const (
UnreadTypeNone UnreadType = 0b0000
UnreadTypeNormal UnreadType = 0b0001
UnreadTypeNotify UnreadType = 0b0010
UnreadTypeHighlight UnreadType = 0b0100
UnreadTypeSound UnreadType = 0b1000
)
type UnreadCounts struct {
UnreadHighlights int `json:"unread_highlights"`
UnreadNotifications int `json:"unread_notifications"`
UnreadMessages int `json:"unread_messages"`
}
func (uc *UnreadCounts) IsZero() bool {
return uc.UnreadHighlights == 0 && uc.UnreadNotifications == 0 && uc.UnreadMessages == 0
}
func (uc *UnreadCounts) Add(other UnreadCounts) {
uc.UnreadHighlights += other.UnreadHighlights
uc.UnreadNotifications += other.UnreadNotifications
uc.UnreadMessages += other.UnreadMessages
}
func (uc *UnreadCounts) AddOne(ut UnreadType) {
if ut.Is(UnreadTypeNormal) {
uc.UnreadMessages++
}
if ut.Is(UnreadTypeNotify) {
uc.UnreadNotifications++
}
if ut.Is(UnreadTypeHighlight) {
uc.UnreadHighlights++
}
}