use lemmy_api_common::lemmy_db_views::structs::PostView; use relm4::prelude::*; use gtk::prelude::*; use relm4_components::web_image::WebImage; use crate::{util::get_web_image_url, api}; use crate::settings; use super::voting_row::{VotingRowModel, VotingStats}; #[derive(Debug)] pub struct PostRow { post: PostView, author_image: Controller, community_image: Controller, voting_row: Controller } #[derive(Debug)] pub enum PostViewMsg { OpenPost, OpenCommunity, OpenPerson, DeletePost } #[relm4::factory(pub)] impl FactoryComponent for PostRow { type Init = PostView; type Input = PostViewMsg; type Output = crate::AppMsg; type CommandOutput = (); type Widgets = PostViewWidgets; 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, gtk::Box { set_orientation: gtk::Orientation::Horizontal, set_margin_top: 10, set_spacing: 10, set_vexpand: false, set_hexpand: true, if self.post.community.icon.clone().is_some() { gtk::Box { set_hexpand: false, #[local_ref] community_image -> gtk::Box {} } } else { gtk::Box {} }, gtk::Button { set_label: &self.post.community.title, connect_clicked => PostViewMsg::OpenCommunity, }, if self.post.creator.avatar.clone().is_some() { gtk::Box { set_hexpand: false, set_margin_start: 10, #[local_ref] author_image -> gtk::Box {} } } else { gtk::Box {} }, gtk::Button { set_label: &self.post.creator.name, connect_clicked => PostViewMsg::OpenPerson, }, gtk::Box { set_hexpand: true, }, gtk::Button { set_label: "View", set_margin_end: 10, connect_clicked => PostViewMsg::OpenPost, } }, gtk::Label { set_halign: gtk::Align::Start, set_text: &self.post.post.name, add_css_class: "font-bold", }, gtk::Box { set_orientation: gtk::Orientation::Horizontal, #[local_ref] voting_row -> gtk::Box { set_margin_end: 10, }, gtk::Label { set_halign: gtk::Align::Start, set_text: &format!("{} comments", self.post.counts.comments.clone()), }, if self.post.creator.id.0 == settings::get_current_account().id { gtk::Button { set_icon_name: "edit-delete", connect_clicked => PostViewMsg::DeletePost, set_margin_start: 10, } } else { gtk::Box {} } }, gtk::Separator { set_margin_top: 10, } } } fn forward_to_parent(output: Self::Output) -> Option { Some(output) } fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender) -> Self { let author_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_post(value.counts.clone(), value.my_vote)).detach(); Self { post: value, author_image, community_image, voting_row } } fn init_widgets( &mut self, _index: &Self::Index, root: &Self::Root, _returned_widget: &::ReturnedWidget, sender: FactorySender, ) -> Self::Widgets { let author_image = self.author_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 { PostViewMsg::OpenCommunity => { sender.output(crate::AppMsg::OpenCommunity(self.post.community.name.clone())) } PostViewMsg::OpenPerson => { sender.output(crate::AppMsg::OpenPerson(self.post.creator.name.clone())) } PostViewMsg::OpenPost => { sender.output(crate::AppMsg::OpenPost(self.post.post.id.clone())) } PostViewMsg::DeletePost => { let post_id = self.post.post.id; std::thread::spawn(move || { let _ = api::post::delete_post(post_id); let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true)); }); } } } }