use kordophone::model::message::AttachmentMetadata; use pretty::RcDoc; use std::collections::HashMap; use std::fmt::Display; use time::OffsetDateTime; pub struct PrintableConversation { pub guid: String, pub date: OffsetDateTime, pub unread_count: i32, pub last_message_preview: Option, pub participants: Vec, pub display_name: Option, } impl From for PrintableConversation { fn from(value: kordophone::model::Conversation) -> Self { Self { guid: value.guid, date: value.date, unread_count: value.unread_count, last_message_preview: value.last_message_preview, participants: value.participant_display_names, display_name: value.display_name, } } } impl From for PrintableConversation { fn from(value: kordophone_db::models::Conversation) -> Self { Self { guid: value.guid, date: OffsetDateTime::from_unix_timestamp(value.date.and_utc().timestamp()).unwrap(), unread_count: value.unread_count.into(), last_message_preview: value.last_message_preview, participants: value .participants .into_iter() .map(|p| p.display_name()) .collect(), display_name: value.display_name, } } } #[cfg(target_os = "linux")] impl From for PrintableConversation { fn from(value: dbus::arg::PropMap) -> Self { Self { guid: value.get("guid").unwrap().as_str().unwrap().to_string(), date: OffsetDateTime::from_unix_timestamp(value.get("date").unwrap().as_i64().unwrap()) .unwrap(), unread_count: value .get("unread_count") .unwrap() .as_i64() .unwrap() .try_into() .unwrap(), last_message_preview: value .get("last_message_preview") .unwrap() .as_str() .map(|s| s.to_string()), participants: value .get("participants") .unwrap() .0 .as_iter() .unwrap() .map(|s| s.as_str().unwrap().to_string()) .collect(), display_name: value .get("display_name") .unwrap() .as_str() .map(|s| s.to_string()), } } } pub struct PrintableMessage { pub guid: String, pub date: OffsetDateTime, pub sender: String, pub text: String, pub file_transfer_guids: Vec, pub attachment_metadata: Option>, } impl From for PrintableMessage { fn from(value: kordophone::model::Message) -> Self { Self { guid: value.guid, date: value.date, sender: value.sender.unwrap_or("".to_string()), text: value.text, file_transfer_guids: value.file_transfer_guids, attachment_metadata: value.attachment_metadata, } } } impl From for PrintableMessage { fn from(value: kordophone_db::models::Message) -> Self { Self { guid: value.id, date: OffsetDateTime::from_unix_timestamp(value.date.and_utc().timestamp()).unwrap(), sender: value.sender.display_name(), text: value.text, file_transfer_guids: value.file_transfer_guids, attachment_metadata: value.attachment_metadata, } } } #[cfg(target_os = "linux")] impl From for PrintableMessage { fn from(value: dbus::arg::PropMap) -> Self { // Parse file transfer GUIDs from JSON if present let file_transfer_guids = value .get("file_transfer_guids") .and_then(|v| v.as_str()) .and_then(|json_str| serde_json::from_str(json_str).ok()) .unwrap_or_default(); // Parse attachment metadata from JSON if present let attachment_metadata = value .get("attachment_metadata") .and_then(|v| v.as_str()) .and_then(|json_str| serde_json::from_str(json_str).ok()); Self { guid: value.get("id").unwrap().as_str().unwrap().to_string(), date: OffsetDateTime::from_unix_timestamp(value.get("date").unwrap().as_i64().unwrap()) .unwrap(), sender: value.get("sender").unwrap().as_str().unwrap().to_string(), text: value.get("text").unwrap().as_str().unwrap().to_string(), file_transfer_guids, attachment_metadata, } } } pub struct ConversationPrinter<'a> { doc: RcDoc<'a, PrintableConversation>, } impl<'a> ConversationPrinter<'a> { pub fn new(conversation: &'a PrintableConversation) -> Self { let preview = conversation .last_message_preview .as_deref() .unwrap_or("") .replace('\n', " "); let doc = RcDoc::text(format!("")) .append(RcDoc::line()) .append("Date: ") .append(conversation.date.to_string()) .append(RcDoc::line()) .append("Unread Count: ") .append(conversation.unread_count.to_string()) .append(RcDoc::line()) .append("Participants: ") .append("[") .append( RcDoc::line() .append( conversation .participants .iter() .map(|name| RcDoc::text(name).append(",").append(RcDoc::line())) .fold(RcDoc::nil(), |acc, x| acc.append(x)), ) .nest(4), ) .append("]") .append(RcDoc::line()) .append("Last Message Preview: ") .append(preview) .nest(4), ) .append(RcDoc::line()) .append(">"); ConversationPrinter { doc } } } impl Display for ConversationPrinter<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.doc.render_fmt(180, f) } } pub struct MessagePrinter<'a> { doc: RcDoc<'a, PrintableMessage>, } impl Display for MessagePrinter<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.doc.render_fmt(180, f) } } impl<'a> MessagePrinter<'a> { pub fn new(message: &'a PrintableMessage) -> Self { let mut doc = RcDoc::text(format!(""); MessagePrinter { doc } } }