From 27520f33374afb5ad3fb379369ab8b94cbe4aac4 Mon Sep 17 00:00:00 2001 From: DSeeLP <46624152+DSeeLP@users.noreply.github.com> Date: Thu, 17 Apr 2025 08:18:23 +0200 Subject: [PATCH] implement unread count --- bank_core/src/chat.rs | 6 ++---- openapi-def.yaml | 4 +++- src/api/chats.rs | 2 +- src/model/chats.rs | 9 +++++---- tests/integration/chats.hurl | 3 +++ 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/bank_core/src/chat.rs b/bank_core/src/chat.rs index 471251c..465dba5 100644 --- a/bank_core/src/chat.rs +++ b/bank_core/src/chat.rs @@ -21,6 +21,7 @@ pub struct ChatInfo { pub created: DateTime, pub read_until: Option, pub members: Vec, + pub unread: u32, } #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] @@ -33,9 +34,6 @@ pub struct ChatMessage { pub extra: Option, } -impl PaginationType for Chat { - const NAME: &str = "Chats"; -} impl PaginationType for ChatInfo { const NAME: &str = "ChatInfos"; } @@ -57,4 +55,4 @@ pub struct StartChat { pub user: NameOrUuid, } -make_schemas!((StartChat, SendMessage); (Chat, ChatInfo, ChatMessage, Pagination, Pagination, Pagination)); +make_schemas!((StartChat, SendMessage); (Chat, ChatInfo, ChatMessage, Pagination, Pagination)); diff --git a/openapi-def.yaml b/openapi-def.yaml index 2ea2d05..d4721be 100644 --- a/openapi-def.yaml +++ b/openapi-def.yaml @@ -425,7 +425,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PaginatedChats' + $ref: '#/components/schemas/PaginatedChatInfos' 400: $ref: '#/components/responses/BadRequest' 401: @@ -504,6 +504,8 @@ paths: - bearer: [] parameters: - $ref: '#/components/parameters/ChatId' + - $ref: '#/components/parameters/PaginationOffset' + - $ref: '#/components/parameters/PaginationLimit' responses: 200: description: Ok diff --git a/src/api/chats.rs b/src/api/chats.rs index 737a430..17c02ad 100644 --- a/src/api/chats.rs +++ b/src/api/chats.rs @@ -35,7 +35,7 @@ pub async fn list_chats( EState(state): State, auth: Auth, PaginationQuery(pagination): PaginationQuery, -) -> Result>, Error> { +) -> Result>, Error> { let client = state.conn().await?; let chats = Chats::list_for_user(&client, auth.user_id(), pagination).await?; Ok(Json(chats)) diff --git a/src/model/chats.rs b/src/model/chats.rs index 8936f52..f8c7166 100644 --- a/src/model/chats.rs +++ b/src/model/chats.rs @@ -23,6 +23,7 @@ fn chat_info_from_row(row: Row) -> ChatInfo { created: row.get("created"), read_until: row.get("read_until"), members: row.get("members"), + unread: row.get::<_, i64>("unread") as u32, } } @@ -84,7 +85,7 @@ impl Chats { id: Uuid, user: Uuid, ) -> Result, 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?; Ok(res.map(chat_info_from_row)) } @@ -148,14 +149,14 @@ impl Chats { client: &impl GenericClient, user: Uuid, pagination: RequestPagination, - ) -> Result, 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?; + ) -> Result, tokio_postgres::Error> { + 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 result = client .query(&stmt, &[&user, &pagination.limit(), &pagination.offset()]) .await? .into_iter() - .map(chat_from_row) + .map(chat_info_from_row) .collect(); let total = count(client, &count_stmt, &[&user]).await?; Ok(Pagination::new(result, total, pagination)) diff --git a/tests/integration/chats.hurl b/tests/integration/chats.hurl index 22361ee..0473642 100644 --- a/tests/integration/chats.hurl +++ b/tests/integration/chats.hurl @@ -146,6 +146,7 @@ HTTP 200 [Asserts] jsonpath "$.id" == {{chat}} jsonpath "$.read_until" == {{message2}} +jsonpath "$.unread" == 0 POST {{host}}/api/chats/{{chat}}/messages/{{message1}}/read @@ -158,6 +159,7 @@ HTTP 200 [Asserts] jsonpath "$.id" == {{chat}} jsonpath "$.read_until" == {{message1}} +jsonpath "$.unread" == 1 GET {{host}}/api/chats/{{chat}} @@ -166,6 +168,7 @@ HTTP 200 [Asserts] jsonpath "$.id" == {{chat}} jsonpath "$.read_until" == null +jsonpath "$.unread" == 2 # Verify list messages endpoint