Start work on notification panel

This commit is contained in:
Max Brunsfeld 2023-10-06 12:56:18 -07:00
parent 50cf25ae97
commit d1756b621f
24 changed files with 1021 additions and 241 deletions

View file

@ -1,5 +1,5 @@
use super::*;
use rpc::{Notification, NotificationEntityKind, NotificationKind};
use rpc::{Notification, NotificationKind};
impl Database {
pub async fn ensure_notification_kinds(&self) -> Result<()> {
@ -25,49 +25,16 @@ impl Database {
) -> Result<proto::AddNotifications> {
self.transaction(|tx| async move {
let mut result = proto::AddNotifications::default();
let mut rows = notification::Entity::find()
.filter(notification::Column::RecipientId.eq(recipient_id))
.order_by_desc(notification::Column::Id)
.limit(limit as u64)
.stream(&*tx)
.await?;
let mut user_ids = Vec::new();
let mut channel_ids = Vec::new();
let mut message_ids = Vec::new();
while let Some(row) = rows.next().await {
let row = row?;
let Some(kind) = NotificationKind::from_i32(row.kind) else {
continue;
};
let Some(notification) = Notification::from_parts(
kind,
[
row.entity_id_1.map(|id| id as u64),
row.entity_id_2.map(|id| id as u64),
row.entity_id_3.map(|id| id as u64),
],
) else {
continue;
};
// Gather the ids of all associated entities.
let (_, associated_entities) = notification.to_parts();
for entity in associated_entities {
let Some((id, kind)) = entity else {
break;
};
match kind {
NotificationEntityKind::User => &mut user_ids,
NotificationEntityKind::Channel => &mut channel_ids,
NotificationEntityKind::ChannelMessage => &mut message_ids,
}
.push(id);
}
result.notifications.push(proto::Notification {
id: row.id.to_proto(),
kind: row.kind as u32,
timestamp: row.created_at.assume_utc().unix_timestamp() as u64,
is_read: row.is_read,
@ -76,43 +43,7 @@ impl Database {
entity_id_3: row.entity_id_3.map(|id| id as u64),
});
}
let users = user::Entity::find()
.filter(user::Column::Id.is_in(user_ids))
.all(&*tx)
.await?;
let channels = channel::Entity::find()
.filter(user::Column::Id.is_in(channel_ids))
.all(&*tx)
.await?;
let messages = channel_message::Entity::find()
.filter(user::Column::Id.is_in(message_ids))
.all(&*tx)
.await?;
for user in users {
result.users.push(proto::User {
id: user.id.to_proto(),
github_login: user.github_login,
avatar_url: String::new(),
});
}
for channel in channels {
result.channels.push(proto::Channel {
id: channel.id.to_proto(),
name: channel.name,
});
}
for message in messages {
result.messages.push(proto::ChannelMessage {
id: message.id.to_proto(),
body: message.body,
timestamp: message.sent_at.assume_utc().unix_timestamp() as u64,
sender_id: message.sender_id.to_proto(),
nonce: None,
});
}
result.notifications.reverse();
Ok(result)
})
.await
@ -123,18 +54,27 @@ impl Database {
recipient_id: UserId,
notification: Notification,
tx: &DatabaseTransaction,
) -> Result<()> {
) -> Result<proto::Notification> {
let (kind, associated_entities) = notification.to_parts();
notification::ActiveModel {
let model = notification::ActiveModel {
recipient_id: ActiveValue::Set(recipient_id),
kind: ActiveValue::Set(kind as i32),
entity_id_1: ActiveValue::Set(associated_entities[0].map(|(id, _)| id as i32)),
entity_id_2: ActiveValue::Set(associated_entities[1].map(|(id, _)| id as i32)),
entity_id_3: ActiveValue::Set(associated_entities[2].map(|(id, _)| id as i32)),
entity_id_1: ActiveValue::Set(associated_entities[0].map(|id| id as i32)),
entity_id_2: ActiveValue::Set(associated_entities[1].map(|id| id as i32)),
entity_id_3: ActiveValue::Set(associated_entities[2].map(|id| id as i32)),
..Default::default()
}
.save(&*tx)
.await?;
Ok(())
Ok(proto::Notification {
id: model.id.as_ref().to_proto(),
kind: *model.kind.as_ref() as u32,
timestamp: model.created_at.as_ref().assume_utc().unix_timestamp() as u64,
is_read: false,
entity_id_1: model.entity_id_1.as_ref().map(|id| id as u64),
entity_id_2: model.entity_id_2.as_ref().map(|id| id as u64),
entity_id_3: model.entity_id_3.as_ref().map(|id| id as u64),
})
}
}