//! Read state and notification event handlers on `MessageService`. use std::sync::Arc; use uuid::Uuid; use crate::ImksError; use crate::socket::socket::Socket; use super::message::MessageService; impl MessageService { // Read state handlers /// Handle `read_state:mark` — mark a channel as read up to a message. pub async fn mark_read( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let channel_id: Uuid = Self::parse_field(arr, "channel_id")?; let message_id: Uuid = Self::parse_field(arr, "message_id")?; let state = self.repo.mark_read(channel_id, user_id, message_id).await?; let _ = socket.emit( "read_state:updated", serde_json::to_value(&state).unwrap_or_default(), ); Ok(()) } /// Handle `read_state:get` — get read state for a channel. pub async fn get_read_state( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let channel_id: Uuid = Self::parse_field(arr, "channel_id")?; let state = self.repo.get_read_state(channel_id, user_id).await?; let _ = socket.emit( "read_state:loaded", serde_json::to_value(&state).unwrap_or_default(), ); Ok(()) } // Notification handlers /// Handle `notification:list` — list a user's notifications. pub async fn list_notifications( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let before: Option = Self::parse_optional(arr, "before")?; let limit: Option = Self::parse_optional(arr, "limit")?; let page = self.repo.list_notifications(user_id, before, limit).await?; let _ = socket.emit( "notification:loaded", serde_json::to_value(&page).unwrap_or_default(), ); Ok(()) } /// Handle `notification:mark_read` — mark one notification as read. pub async fn mark_notification_read( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let notification_id: Uuid = Self::parse_field(arr, "notification_id")?; self.repo.mark_notification_read(notification_id).await?; let unread = self.repo.get_unread_notification_count(user_id).await?; let _ = socket.emit( "notification:unread_count", serde_json::json!({ "count": unread }), ); Ok(()) } /// Handle `notification:mark_all_read` — mark all as read. pub async fn mark_all_notifications_read( &self, socket: Arc, _data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let affected = self.repo.mark_all_notifications_read(user_id).await?; tracing::info!(%user_id, %affected, "All notifications marked read"); let _ = socket.emit( "notification:unread_count", serde_json::json!({ "count": 0 }), ); Ok(()) } }