use gtk::prelude::*; use lemmy_api_common::lemmy_db_views_actor::structs::CommentReplyView; use relm4::prelude::*; use relm4_components::web_image::WebImage; use crate::util; use crate::util::get_web_image_url; use crate::util::markdown_to_pango_markup; use super::voting_row::VotingRowModel; use super::voting_row::VotingStats; #[derive(Debug)] pub struct MentionRow { comment: CommentReplyView, creator_image: Controller, community_image: Controller, voting_row: Controller, } #[derive(Debug)] pub enum MentionRowMsg { OpenPerson, OpenPost, OpenCommunity, } #[relm4::factory(pub)] impl FactoryComponent for MentionRow { type Init = CommentReplyView; type Input = MentionRowMsg; type Output = crate::AppMsg; type CommandOutput = (); type ParentInput = crate::AppMsg; type ParentWidget = gtk::Box; view! { root = gtk::Box { set_orientation: gtk::Orientation::Vertical, set_spacing: 10, set_margin_end: 10, set_margin_start: 10, set_margin_top: 10, set_vexpand: false, gtk::Label { set_label: &self.comment.post.name, add_css_class: "font-bold", set_halign: gtk::Align::Start, set_wrap: true, add_controller = gtk::GestureClick { connect_pressed[sender] => move |_, _, _, _| { sender.input(MentionRowMsg::OpenCommunity); } }, }, gtk::Box { set_orientation: gtk::Orientation::Horizontal, gtk::Label { set_label: "in", }, #[local_ref] community_image -> gtk::Box { set_hexpand: false, set_margin_start: 10, set_margin_end: 10, set_visible: self.comment.community.icon.clone().is_some(), }, gtk::Button { set_label: &self.comment.community.title, connect_clicked => MentionRowMsg::OpenCommunity, }, }, gtk::Box { set_orientation: gtk::Orientation::Horizontal, set_spacing: 10, set_margin_top: 10, set_vexpand: false, #[local_ref] creator_image -> gtk::Box { set_hexpand: false, set_visible: self.comment.creator.avatar.is_some(), }, gtk::Button { set_label: &self.comment.creator.name, connect_clicked => MentionRowMsg::OpenPerson, }, gtk::Label { set_margin_start: 10, set_label: &util::format_elapsed_time(self.comment.comment.published), } }, gtk::Label { #[watch] set_markup: &markdown_to_pango_markup(self.comment.comment.content.clone()), set_wrap: true, set_halign: gtk::Align::Start, set_use_markup: true, }, #[local_ref] voting_row -> gtk::Box {}, gtk::Separator {} } } fn forward_to_parent(output: Self::Output) -> Option { Some(output) } fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender) -> Self { let creator_image = WebImage::builder() .launch(get_web_image_url(value.creator.avatar.clone())) .detach(); let community_image = WebImage::builder() .launch(get_web_image_url(value.community.icon.clone())) .detach(); let voting_row = VotingRowModel::builder() .launch(VotingStats::from_comment( value.counts.clone(), value.my_vote, )) .detach(); Self { comment: value, creator_image, community_image, voting_row, } } fn init_widgets( &mut self, _index: &Self::Index, root: &Self::Root, _returned_widget: &::ReturnedWidget, sender: FactorySender, ) -> Self::Widgets { let creator_image = self.creator_image.widget(); let community_image = self.community_image.widget(); let voting_row = self.voting_row.widget(); let widgets = view_output!(); widgets } fn update(&mut self, message: Self::Input, sender: FactorySender) { match message { MentionRowMsg::OpenPerson => { sender.output(crate::AppMsg::OpenPerson(self.comment.creator.id)); } MentionRowMsg::OpenPost => { sender.output(crate::AppMsg::OpenPost(self.comment.post.id)); } MentionRowMsg::OpenCommunity => { sender.output(crate::AppMsg::OpenCommunity(self.comment.community.id)); } } } }