Skip to content

Commit

Permalink
Merge pull request #2539 from acterglobal/ben-rust-notifications-basics
Browse files Browse the repository at this point in the history
Implement rust notifications for creation, title and description change of major objects
  • Loading branch information
gnunicorn authored Jan 31, 2025
2 parents 940bbb9 + 334a733 commit e16c5b3
Show file tree
Hide file tree
Showing 8 changed files with 1,927 additions and 7 deletions.
268 changes: 264 additions & 4 deletions native/acter/src/api/push/notification_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,28 +166,35 @@ pub enum NotificationItemParent {
parent_id: OwnedEventId,
title: String,
},
TaskList {
parent_id: OwnedEventId,
title: String,
},
}

impl NotificationItemParent {
pub fn object_type_str(&self) -> String {
match self {
NotificationItemParent::News { .. } => "news",
NotificationItemParent::Pin { parent_id, title } => "pin",
NotificationItemParent::CalendarEvent { parent_id, title } => "event",
NotificationItemParent::Pin { .. } => "pin",
NotificationItemParent::CalendarEvent { .. } => "event",
NotificationItemParent::TaskList { .. } => "task-list",
}
.to_owned()
}
pub fn object_id_str(&self) -> String {
match self {
NotificationItemParent::News { parent_id }
| NotificationItemParent::Pin { parent_id, .. }
| NotificationItemParent::TaskList { parent_id, .. }
| NotificationItemParent::CalendarEvent { parent_id, .. } => parent_id.to_string(),
}
}
pub fn title(&self) -> Option<String> {
match self {
NotificationItemParent::News { parent_id } => None,
NotificationItemParent::Pin { title, .. }
| NotificationItemParent::TaskList { title, .. }
| NotificationItemParent::CalendarEvent { title, .. } => Some(title.clone()),
}
}
Expand All @@ -196,6 +203,7 @@ impl NotificationItemParent {
match self {
NotificationItemParent::News { parent_id } => format!("/updates/{}", parent_id),
NotificationItemParent::Pin { parent_id, .. } => format!("/pins/{}", parent_id),
NotificationItemParent::TaskList { parent_id, .. } => format!("/tasks/{}", parent_id),
NotificationItemParent::CalendarEvent { parent_id, .. } => {
format!("/events/{}", parent_id)
} //
Expand All @@ -206,6 +214,7 @@ impl NotificationItemParent {
match self {
NotificationItemParent::News { .. } => "🚀", // boost rocket
NotificationItemParent::Pin { .. } => "📌", // pin
NotificationItemParent::TaskList { .. } => "📋", // clipboard
NotificationItemParent::CalendarEvent { .. } => "🗓️", // calendar
}
.to_owned()
Expand All @@ -228,9 +237,12 @@ impl TryFrom<&AnyActerModel> for NotificationItemParent {
parent_id: e.event_id().to_owned(),
title: e.title().clone(),
}),
AnyActerModel::TaskList(e) => Ok(NotificationItemParent::TaskList {
parent_id: e.event_id().to_owned(),
title: e.name().clone(),
}),
AnyActerModel::RedactedActerModel(_)
| AnyActerModel::CalendarEventUpdate(_)
| AnyActerModel::TaskList(_)
| AnyActerModel::TaskListUpdate(_)
| AnyActerModel::Task(_)
| AnyActerModel::TaskUpdate(_)
Expand Down Expand Up @@ -288,6 +300,30 @@ pub enum NotificationItemInner {
event_id: OwnedEventId,
key: String,
},
Creation {
parent_obj: NotificationItemParent,
room_id: OwnedRoomId,
event_id: OwnedEventId,
},
TitleChange {
parent_obj: Option<NotificationItemParent>,
parent_id: OwnedEventId,
room_id: OwnedRoomId,
event_id: OwnedEventId,
},
DescriptionChange {
parent_obj: Option<NotificationItemParent>,
parent_id: OwnedEventId,
room_id: OwnedRoomId,
event_id: OwnedEventId,
content: Option<TextMessageEventContent>,
},
OtherChanges {
parent_obj: Option<NotificationItemParent>,
parent_id: OwnedEventId,
room_id: OwnedRoomId,
event_id: OwnedEventId,
},
}

impl NotificationItemInner {
Expand All @@ -305,6 +341,10 @@ impl NotificationItemInner {
}
}
NotificationItemInner::Boost { .. } => "news",
NotificationItemInner::Creation { .. } => "creation",
NotificationItemInner::TitleChange { .. } => "titleChange",
NotificationItemInner::DescriptionChange { .. } => "descriptionChange",
NotificationItemInner::OtherChanges { .. } => "otherChanges",
}
.to_owned()
}
Expand All @@ -318,6 +358,19 @@ impl NotificationItemInner {
NotificationItemInner::Invite { room_id } => "/activities/invites".to_string(),
NotificationItemInner::ChatMessage { room_id, .. } => format!("/chat/{room_id}"),
NotificationItemInner::Boost { event_id, .. } => format!("/updates/{event_id}"),
NotificationItemInner::TitleChange {
parent_obj: Some(parent_obj),
..
}
| NotificationItemInner::DescriptionChange {
parent_obj: Some(parent_obj),
..
}
| NotificationItemInner::DescriptionChange {
parent_obj: Some(parent_obj),
..
}
| NotificationItemInner::Creation { parent_obj, .. } => parent_obj.target_url(),
NotificationItemInner::Comment {
parent_obj: Some(parent),
event_id,
Expand All @@ -337,7 +390,25 @@ impl NotificationItemInner {
encode(event_id.as_str()),
),
// -- fallback when the parent isn't there.
NotificationItemInner::Comment {
NotificationItemInner::TitleChange {
parent_id,
room_id,
event_id,
..
}
| NotificationItemInner::DescriptionChange {
parent_id,
room_id,
event_id,
..
}
| NotificationItemInner::OtherChanges {
parent_id,
room_id,
event_id,
..
}
| NotificationItemInner::Comment {
event_id,
room_id,
parent_id,
Expand Down Expand Up @@ -369,13 +440,21 @@ impl NotificationItemInner {

pub fn parent(&self) -> Option<NotificationItemParent> {
match self {
NotificationItemInner::Creation { parent_obj, .. } => Some(parent_obj.clone()),
NotificationItemInner::TitleChange { parent_obj, .. }
| NotificationItemInner::DescriptionChange { parent_obj, .. }
| NotificationItemInner::OtherChanges { parent_obj, .. } => parent_obj.clone(),
NotificationItemInner::Comment { parent_obj, .. }
| NotificationItemInner::Reaction { parent_obj, .. } => parent_obj.clone(),
_ => None,
}
}
pub fn parent_id_str(&self) -> Option<String> {
match self {
NotificationItemInner::Creation { parent_obj, .. } => Some(parent_obj.object_id_str()),
NotificationItemInner::TitleChange { parent_id, .. }
| NotificationItemInner::DescriptionChange { parent_id, .. }
| NotificationItemInner::OtherChanges { parent_id, .. } => Some(parent_id.to_string()),
NotificationItemInner::Comment { parent_id, .. }
| NotificationItemInner::Reaction { parent_id, .. } => Some(parent_id.to_string()),
_ => None,
Expand Down Expand Up @@ -424,6 +503,9 @@ impl NotificationItemInner {
| NewsContent::Location(msg_content) => Some(MsgContent::from(msg_content)),
_ => None,
},
NotificationItemInner::DescriptionChange { content, .. } => {
content.as_ref().map(|e| MsgContent::from(e.clone()))
}

_ => None,
}
Expand Down Expand Up @@ -665,6 +747,184 @@ impl NotificationItem {
})
.build()?)
}

// -- Pin
AnyActerEvent::Pin(MessageLikeEvent::Original(e)) => {
let parent_obj = NotificationItemParent::Pin {
parent_id: e.event_id.clone(),
title: e.content.title,
};
Ok(builder
.inner(NotificationItemInner::Creation {
parent_obj,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
}

AnyActerEvent::PinUpdate(MessageLikeEvent::Original(e)) => {
let parent_obj = client
.store()
.get(&e.content.pin.event_id)
.await
.map_err(|error| {
tracing::error!(?error, "Error loading parent of comment");
})
.ok()
.and_then(|o| NotificationItemParent::try_from(&o).ok());

if let Some(new_title) = e.content.title {
Ok(builder
.title(new_title)
.inner(NotificationItemInner::TitleChange {
parent_obj,
parent_id: e.content.pin.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
} else if let Some(Some(new_content)) = e.content.content {
return Ok(builder
.inner(NotificationItemInner::DescriptionChange {
parent_obj,
parent_id: e.content.pin.event_id,
room_id: e.room_id,
event_id: e.event_id,
content: Some(new_content),
})
.build()?);
} else {
// fallback: other changes
return Ok(builder
.inner(NotificationItemInner::OtherChanges {
parent_obj,
parent_id: e.content.pin.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?);
}
}

// ---- Event
AnyActerEvent::CalendarEvent(MessageLikeEvent::Original(e)) => {
let parent_obj = NotificationItemParent::CalendarEvent {
parent_id: e.event_id.clone(),
title: e.content.title,
};
Ok(builder
.inner(NotificationItemInner::Creation {
parent_obj,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
}

AnyActerEvent::CalendarEventUpdate(MessageLikeEvent::Original(e)) => {
let parent_obj = client
.store()
.get(&e.content.calendar_event.event_id)
.await
.map_err(|error| {
tracing::error!(?error, "Error loading parent of comment");
})
.ok()
.and_then(|o| NotificationItemParent::try_from(&o).ok());

if let Some(new_title) = e.content.title {
Ok(builder
.title(new_title)
.inner(NotificationItemInner::TitleChange {
parent_obj,
parent_id: e.content.calendar_event.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
} else if let Some(Some(new_content)) = e.content.description {
return Ok(builder
.inner(NotificationItemInner::DescriptionChange {
parent_obj,
parent_id: e.content.calendar_event.event_id,
room_id: e.room_id,
event_id: e.event_id,
content: Some(new_content),
})
.build()?);
} else {
// fallback: other changes
return Ok(builder
.inner(NotificationItemInner::OtherChanges {
parent_obj,
parent_id: e.content.calendar_event.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?);
}
}

// --- Task listss
AnyActerEvent::TaskList(MessageLikeEvent::Original(e)) => {
let parent_obj = NotificationItemParent::TaskList {
parent_id: e.event_id.clone(),
title: e.content.name,
};
Ok(builder
.inner(NotificationItemInner::Creation {
parent_obj,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
}

AnyActerEvent::TaskListUpdate(MessageLikeEvent::Original(e)) => {
let parent_obj = client
.store()
.get(&e.content.task_list.event_id)
.await
.map_err(|error| {
tracing::error!(?error, "Error loading parent of comment");
})
.ok()
.and_then(|o| NotificationItemParent::try_from(&o).ok());

if let Some(new_title) = e.content.name {
Ok(builder
.title(new_title)
.inner(NotificationItemInner::TitleChange {
parent_obj,
parent_id: e.content.task_list.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?)
} else if let Some(Some(new_content)) = e.content.description {
return Ok(builder
.inner(NotificationItemInner::DescriptionChange {
parent_obj,
parent_id: e.content.task_list.event_id,
room_id: e.room_id,
event_id: e.event_id,
content: Some(new_content),
})
.build()?);
} else {
// fallback: other changes
return Ok(builder
.inner(NotificationItemInner::OtherChanges {
parent_obj,
parent_id: e.content.task_list.event_id,
room_id: e.room_id,
event_id: e.event_id,
})
.build()?);
}
}

_ => {
tracing::warn!(?event, "Notification not support");
Ok(builder.build()?)
Expand Down
3 changes: 0 additions & 3 deletions native/test/src/tests/notifications.rs

This file was deleted.

Loading

0 comments on commit e16c5b3

Please sign in to comment.