- Add gitignore and prettier configuration files for project scaffolding - Implement room access control service with project member verification - Create user access key management with CRUD operations and activity logging - Add accordion UI component for frontend expandable sections - Implement room AI configuration with list, upsert, and delete operations - Add AI event types for agent join/leave/status change tracking - Create streaming AI processing services for mode and react patterns - Build room AI service with model detection and idempotency handling - Integrate chat service orchestration for AI message processing - Add typing indicators and stream cancellation for AI interactions - Implement mention parsing and context extraction for AI agents
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
use crate::push::{PushPayload, WebPushService};
|
|
use db::database::AppDatabase;
|
|
use models::users::user_notification;
|
|
use sea_orm::EntityTrait;
|
|
use std::sync::Arc;
|
|
use uuid::Uuid;
|
|
|
|
/// Helper function to send push notification to a user.
|
|
/// Reads the user's push subscription from `user_notification` table.
|
|
/// Non-blocking: failures are logged but don't affect the caller.
|
|
pub async fn send_push_notification(
|
|
push: &WebPushService,
|
|
db: &AppDatabase,
|
|
user_id: Uuid,
|
|
payload: &PushPayload,
|
|
) -> Result<(), String> {
|
|
let prefs = user_notification::Entity::find_by_id(user_id)
|
|
.one(db)
|
|
.await
|
|
.map_err(|e| format!("Failed to read push subscription: {}", e))?;
|
|
|
|
if let Some(prefs) = prefs {
|
|
if prefs.push_enabled
|
|
&& let Some(endpoint) = &prefs.push_subscription_endpoint
|
|
&& let Some(p256dh) = &prefs.push_subscription_keys_p256dh
|
|
&& let Some(auth) = &prefs.push_subscription_keys_auth
|
|
{
|
|
push.send(endpoint, p256dh, auth, payload)
|
|
.await
|
|
.map_err(|e| format!("WebPush send failed: {}", e))?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Spawn a background task to send push notification.
|
|
/// Failures are logged but don't affect the caller.
|
|
pub fn spawn_push_notification(
|
|
push: Option<Arc<WebPushService>>,
|
|
db: AppDatabase,
|
|
user_id: Uuid,
|
|
payload: PushPayload,
|
|
) {
|
|
tokio::spawn(async move {
|
|
if let Some(push) = push {
|
|
if let Err(e) = send_push_notification(&push, &db, user_id, &payload).await {
|
|
tracing::warn!(user_id = %user_id, error = %e, "Push notification failed");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Create a push notification callback for RoomService.
|
|
pub fn create_push_notification_fn(
|
|
push: Arc<WebPushService>,
|
|
db: AppDatabase,
|
|
) -> room::PushNotificationFn {
|
|
Arc::new(
|
|
move |user_id: Uuid, title: String, body: Option<String>, url: Option<String>| {
|
|
let push = push.clone();
|
|
let db = db.clone();
|
|
let payload = PushPayload {
|
|
title,
|
|
body: body.unwrap_or_default(),
|
|
url,
|
|
icon: None,
|
|
};
|
|
tokio::spawn(async move {
|
|
if let Err(e) = send_push_notification(&push, &db, user_id, &payload).await {
|
|
tracing::warn!(user_id = %user_id, error = %e, "Push notification failed");
|
|
}
|
|
});
|
|
},
|
|
)
|
|
}
|