Return the latest message in room list for display

This commit is contained in:
oxalica 2024-09-03 15:08:35 -04:00
parent 2eb884766a
commit a37bc3f81e
3 changed files with 58 additions and 7 deletions

View file

@ -244,11 +244,24 @@ components:
rooms: rooms:
type: array type: array
items: items:
$ref: '#/components/schemas/RoomMetadata' $ref: '#/components/schemas/RoomMetadataForList'
next_token: next_token:
type: string type: string
description: An opaque token to fetch the next page. description: An opaque token to fetch the next page.
RoomMetadataForList:
type: object
required: ['ruuid', 'title', 'attrs']
properties:
ruuid:
type: string
title:
type: string
attrs:
type: int64
last_chat:
$ref: 'WithSig<ChatPayload>'
RoomMetadata: RoomMetadata:
type: object type: object
properties: properties:

View file

@ -32,3 +32,5 @@ CREATE TABLE IF NOT EXISTS `room_item` (
`sig` BLOB NOT NULL, `sig` BLOB NOT NULL,
`rich_text` TEXT NOT NULL `rich_text` TEXT NOT NULL
) STRICT; ) STRICT;
CREATE INDEX IF NOT EXISTS `room_latest_item` ON `room_item` (`rid` ASC, `cid` DESC);

View file

@ -241,11 +241,33 @@ async fn room_list(
.unwrap() .unwrap()
.prepare(sql)? .prepare(sql)?
.query_map(params, |row| { .query_map(params, |row| {
// TODO: Extract this into a function.
last_rid = Some(row.get::<_, u64>("rid")?); last_rid = Some(row.get::<_, u64>("rid")?);
let ruuid = row.get("ruuid")?;
let title = row.get("title")?;
let attrs = row.get("attrs")?;
let last_chat = row
.get::<_, Option<UserKey>>("userkey")?
.map(|user| {
Ok::<_, rusqlite::Error>(ChatItem {
sig: row.get("sig")?,
signee: Signee {
nonce: row.get("nonce")?,
timestamp: row.get("timestamp")?,
user,
payload: ChatPayload {
rich_text: row.get("rich_text")?,
room: ruuid,
},
},
})
})
.transpose()?;
Ok(RoomMetadata { Ok(RoomMetadata {
ruuid: row.get("ruuid")?, ruuid,
title: row.get("title")?, title,
attrs: row.get("attrs")?, attrs,
last_chat,
}) })
})? })?
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
@ -256,10 +278,14 @@ async fn room_list(
match params.filter { match params.filter {
ListRoomFilter::Public => query( ListRoomFilter::Public => query(
r" r"
SELECT `rid`, `ruuid`, `title`, `attrs` SELECT `rid`, `ruuid`, `title`, `attrs`,
`last_author`.`userkey` AS `userkey`, `timestamp`, `nonce`, `sig`, `rich_text`
FROM `room` FROM `room`
LEFT JOIN `room_item` USING (`rid`)
LEFT JOIN `user` AS `last_author` USING (`uid`)
WHERE `rid` > :start_rid AND WHERE `rid` > :start_rid AND
(`attrs` & :perm) = :perm (`attrs` & :perm) = :perm
GROUP BY `rid` HAVING `cid` IS MAX(`cid`)
ORDER BY `rid` ASC ORDER BY `rid` ASC
LIMIT :page_len LIMIT :page_len
", ",
@ -279,12 +305,17 @@ async fn room_list(
}; };
query( query(
r" r"
SELECT `rid`, `ruuid`, `title`, `attrs` SELECT
`rid`, `ruuid`, `title`, `attrs`,
`last_author`.`userkey`, `timestamp`, `nonce`, `sig`, `rich_text`
FROM `user` FROM `user`
JOIN `room_member` USING (`uid`) JOIN `room_member` USING (`uid`)
JOIN `room` USING (`rid`) JOIN `room` USING (`rid`)
WHERE `userkey` = :userkey AND LEFT JOIN `room_item` USING (`rid`)
LEFT JOIN `user` AS `last_author` ON (`last_author`.`uid` = `room_item`.`uid`)
WHERE `user`.`userkey` = :userkey AND
`rid` > :start_rid `rid` > :start_rid
GROUP BY `rid` HAVING `cid` IS MAX(`cid`)
ORDER BY `rid` ASC ORDER BY `rid` ASC
LIMIT :page_len LIMIT :page_len
", ",
@ -447,6 +478,7 @@ async fn room_get_metadata(
ruuid, ruuid,
title, title,
attrs, attrs,
last_chat: None,
})) }))
} }
@ -555,6 +587,10 @@ pub struct RoomMetadata {
pub ruuid: Uuid, pub ruuid: Uuid,
pub title: String, pub title: String,
pub attrs: RoomAttrs, pub attrs: RoomAttrs,
/// Optional extra information. Only included by the global room list response.
#[serde(skip_serializing_if = "Option::is_none")]
pub last_chat: Option<ChatItem>,
} }
fn get_room_if_readable<T>( fn get_room_if_readable<T>(