implement unread count

This commit is contained in:
DSeeLP 2025-04-17 08:18:23 +02:00
parent 0972bedc49
commit 27520f3337
5 changed files with 14 additions and 10 deletions

View File

@ -21,6 +21,7 @@ pub struct ChatInfo {
pub created: DateTime<Utc>, pub created: DateTime<Utc>,
pub read_until: Option<Uuid>, pub read_until: Option<Uuid>,
pub members: Vec<Uuid>, pub members: Vec<Uuid>,
pub unread: u32,
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
@ -33,9 +34,6 @@ pub struct ChatMessage {
pub extra: Option<serde_json::Value>, pub extra: Option<serde_json::Value>,
} }
impl PaginationType for Chat {
const NAME: &str = "Chats";
}
impl PaginationType for ChatInfo { impl PaginationType for ChatInfo {
const NAME: &str = "ChatInfos"; const NAME: &str = "ChatInfos";
} }
@ -57,4 +55,4 @@ pub struct StartChat {
pub user: NameOrUuid, pub user: NameOrUuid,
} }
make_schemas!((StartChat, SendMessage); (Chat, ChatInfo, ChatMessage, Pagination<Chat>, Pagination<ChatInfo>, Pagination<ChatMessage>)); make_schemas!((StartChat, SendMessage); (Chat, ChatInfo, ChatMessage, Pagination<ChatInfo>, Pagination<ChatMessage>));

View File

@ -425,7 +425,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/PaginatedChats' $ref: '#/components/schemas/PaginatedChatInfos'
400: 400:
$ref: '#/components/responses/BadRequest' $ref: '#/components/responses/BadRequest'
401: 401:
@ -504,6 +504,8 @@ paths:
- bearer: [] - bearer: []
parameters: parameters:
- $ref: '#/components/parameters/ChatId' - $ref: '#/components/parameters/ChatId'
- $ref: '#/components/parameters/PaginationOffset'
- $ref: '#/components/parameters/PaginationLimit'
responses: responses:
200: 200:
description: Ok description: Ok

View File

@ -35,7 +35,7 @@ pub async fn list_chats(
EState(state): State, EState(state): State,
auth: Auth, auth: Auth,
PaginationQuery(pagination): PaginationQuery, PaginationQuery(pagination): PaginationQuery,
) -> Result<Json<Pagination<Chat>>, Error> { ) -> Result<Json<Pagination<ChatInfo>>, Error> {
let client = state.conn().await?; let client = state.conn().await?;
let chats = Chats::list_for_user(&client, auth.user_id(), pagination).await?; let chats = Chats::list_for_user(&client, auth.user_id(), pagination).await?;
Ok(Json(chats)) Ok(Json(chats))

View File

@ -23,6 +23,7 @@ fn chat_info_from_row(row: Row) -> ChatInfo {
created: row.get("created"), created: row.get("created"),
read_until: row.get("read_until"), read_until: row.get("read_until"),
members: row.get("members"), members: row.get("members"),
unread: row.get::<_, i64>("unread") as u32,
} }
} }
@ -84,7 +85,7 @@ impl Chats {
id: Uuid, id: Uuid,
user: Uuid, user: Uuid,
) -> Result<Option<ChatInfo>, tokio_postgres::Error> { ) -> Result<Option<ChatInfo>, tokio_postgres::Error> {
let stmt = client.prepare_cached("select c.*, cmru.read_until, array_agg(cm.\"user\") as members from chats c join chat_members cm on cm.chat = c.id join chat_members cmru on cmru.chat = c.id and cmru.\"user\" = $2 where c.id = $1 group by c.id, cmru.read_until").await?; let stmt = client.prepare_cached("select c.*, cmru.read_until, array_agg(cm.\"user\") as members, (select count(id) from chat_messages where chat = c.id and (cmru.read_until is null or id > cmru.read_until)) as unread from chats c join chat_members cm on cm.chat = c.id join chat_members cmru on cmru.chat = c.id and cmru.\"user\" = $2 where c.id = $1 group by c.id, cmru.read_until").await?;
let res = client.query_opt(&stmt, &[&id, &user]).await?; let res = client.query_opt(&stmt, &[&id, &user]).await?;
Ok(res.map(chat_info_from_row)) Ok(res.map(chat_info_from_row))
} }
@ -148,14 +149,14 @@ impl Chats {
client: &impl GenericClient, client: &impl GenericClient,
user: Uuid, user: Uuid,
pagination: RequestPagination, pagination: RequestPagination,
) -> Result<Pagination<Chat>, tokio_postgres::Error> { ) -> Result<Pagination<ChatInfo>, tokio_postgres::Error> {
let stmt = client.prepare_cached("select c.*, cmru.read_until, array_agg(cm.\"user\") as members from chats c join chat_members cm on cm.chat = c.id join chat_members cmru on cmru.chat = c.id and cmru.\"user\" = $1 where cm.\"user\" = $1 group by c.id, cmru.read_until order by c.created desc limit $2 offset $3").await?; let stmt = client.prepare_cached("select c.*, cmru.read_until, array_agg(cm.\"user\") as members, (select count(id) from chat_messages where chat = c.id and (cmru.read_until is null or id > cmru.read_until)) as unread from chats c join chat_members cm on cm.chat = c.id join chat_members cmru on cmru.chat = c.id and cmru.\"user\" = $1 group by c.id, cmru.read_until order by c.created desc limit $2 offset $3").await?;
let count_stmt = client.prepare_cached("select count(c.id) from chat_members cm join chats c on cm.chat = c.id where cm.\"user\" = $1").await?; let count_stmt = client.prepare_cached("select count(c.id) from chat_members cm join chats c on cm.chat = c.id where cm.\"user\" = $1").await?;
let result = client let result = client
.query(&stmt, &[&user, &pagination.limit(), &pagination.offset()]) .query(&stmt, &[&user, &pagination.limit(), &pagination.offset()])
.await? .await?
.into_iter() .into_iter()
.map(chat_from_row) .map(chat_info_from_row)
.collect(); .collect();
let total = count(client, &count_stmt, &[&user]).await?; let total = count(client, &count_stmt, &[&user]).await?;
Ok(Pagination::new(result, total, pagination)) Ok(Pagination::new(result, total, pagination))

View File

@ -146,6 +146,7 @@ HTTP 200
[Asserts] [Asserts]
jsonpath "$.id" == {{chat}} jsonpath "$.id" == {{chat}}
jsonpath "$.read_until" == {{message2}} jsonpath "$.read_until" == {{message2}}
jsonpath "$.unread" == 0
POST {{host}}/api/chats/{{chat}}/messages/{{message1}}/read POST {{host}}/api/chats/{{chat}}/messages/{{message1}}/read
@ -158,6 +159,7 @@ HTTP 200
[Asserts] [Asserts]
jsonpath "$.id" == {{chat}} jsonpath "$.id" == {{chat}}
jsonpath "$.read_until" == {{message1}} jsonpath "$.read_until" == {{message1}}
jsonpath "$.unread" == 1
GET {{host}}/api/chats/{{chat}} GET {{host}}/api/chats/{{chat}}
@ -166,6 +168,7 @@ HTTP 200
[Asserts] [Asserts]
jsonpath "$.id" == {{chat}} jsonpath "$.id" == {{chat}}
jsonpath "$.read_until" == null jsonpath "$.read_until" == null
jsonpath "$.unread" == 2
# Verify list messages endpoint # Verify list messages endpoint