Support for commenting on posts

This commit is contained in:
Bnyro 2023-06-20 12:20:28 +02:00
parent 99f35bfe7a
commit 10b5059420
4 changed files with 99 additions and 29 deletions

View File

@ -1,17 +1,18 @@
use lemmy_api_common::{sensitive::Sensitive, comment::{CommentResponse, CreateComment}, lemmy_db_schema::newtypes::{PostId, CommentId}};
use lemmy_api_common::{comment::{CommentResponse, CreateComment}, lemmy_db_schema::newtypes::{PostId, CommentId}};
use crate::util;
pub fn create_comment(
post_id: i32,
content: String,
parent_id: Option<i32>,
auth: Sensitive<String>,
) -> Result<CommentResponse, reqwest::Error> {
let params = CreateComment {
post_id: PostId(post_id),
content,
parent_id: parent_id.map(CommentId),
auth,
auth: util::get_auth_token().unwrap(),
..Default::default()
};
super::post("/comment", &params)

View File

@ -1,4 +1,4 @@
use crate::{util::markdown_to_pango_markup, dialogs::create_post::{CreatePostDialog, CREATE_POST_DIALOG_BROKER, DialogMsg, CreatePostDialogOutput}};
use crate::{util::markdown_to_pango_markup, dialogs::create_post::{CreatePostDialog, CREATE_POST_DIALOG_BROKER, DialogMsg, CreatePostDialogOutput, DialogType}};
use lemmy_api_common::{community::GetCommunityResponse, lemmy_db_views::structs::PostView};
use relm4::{prelude::*, factory::FactoryVecDeque};
use gtk::prelude::*;
@ -101,9 +101,9 @@ impl SimpleComponent for CommunityPage {
let dialog = CreatePostDialog::builder()
.transient_for(root)
.launch_with_broker((), &CREATE_POST_DIALOG_BROKER)
.launch_with_broker(DialogType::Post, &CREATE_POST_DIALOG_BROKER)
.forward(sender.input_sender(), |msg| match msg {
CreatePostDialogOutput::CreatePostRequest(name, body) => CommunityInput::CreatePostRequest(name, body)
CreatePostDialogOutput::CreateRequest(name, body) => CommunityInput::CreatePostRequest(name, body)
});
let model = CommunityPage { info: init, avatar, posts, create_post_dialog: dialog };

View File

@ -1,9 +1,9 @@
use lemmy_api_common::{lemmy_db_views::structs::{CommentView}, post::GetPostResponse};
use lemmy_api_common::{lemmy_db_views::structs::CommentView, post::GetPostResponse};
use relm4::{prelude::*, factory::FactoryVecDeque};
use gtk::prelude::*;
use relm4_components::web_image::WebImage;
use crate::{api, util::{get_web_image_msg, get_web_image_url, markdown_to_pango_markup}};
use crate::{api, util::{get_web_image_msg, get_web_image_url, markdown_to_pango_markup}, dialogs::create_post::{CreatePostDialog, CreatePostDialogOutput, DialogMsg, CREATE_COMMENT_DIALOG_BROKER, DialogType}};
use super::comment_row::CommentRow;
@ -12,7 +12,9 @@ pub struct PostPage {
image: Controller<WebImage>,
creator_avatar: Controller<WebImage>,
community_avatar: Controller<WebImage>,
comments: FactoryVecDeque<CommentRow>
comments: FactoryVecDeque<CommentRow>,
#[allow(dead_code)]
create_comment_dialog: Controller<CreatePostDialog>
}
#[derive(Debug)]
@ -21,7 +23,10 @@ pub enum PostInput {
DoneFetchComments(Vec<CommentView>),
OpenPerson,
OpenCommunity,
OpenLink
OpenLink,
OpenCreateCommentDialog,
CreateCommentRequest(String),
CreatedComment(CommentView)
}
#[relm4::component(pub)]
@ -123,6 +128,12 @@ impl SimpleComponent for PostPage {
#[watch]
set_text: &format!("{} score", model.info.post_view.counts.score),
},
gtk::Button {
set_label: "Comment",
set_margin_start: 10,
connect_clicked => PostInput::OpenCreateCommentDialog,
}
},
gtk::Separator {},
@ -144,7 +155,13 @@ impl SimpleComponent for PostPage {
let comments = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
let creator_avatar = WebImage::builder().launch("".to_string()).detach();
let community_avatar = WebImage::builder().launch("".to_string()).detach();
let model = PostPage { info: init, image, comments, creator_avatar, community_avatar };
let dialog = CreatePostDialog::builder()
.transient_for(root)
.launch_with_broker(DialogType::Comment, &CREATE_COMMENT_DIALOG_BROKER)
.forward(sender.input_sender(), |msg| match msg {
CreatePostDialogOutput::CreateRequest(_name, body) => PostInput::CreateCommentRequest(body)
});
let model = PostPage { info: init, image, comments, creator_avatar, community_avatar, create_comment_dialog: dialog, };
let image = model.image.widget();
let comments = model.comments.widget();
@ -199,6 +216,22 @@ impl SimpleComponent for PostPage {
if link.is_empty() { return; }
gtk::show_uri(None::<&relm4::gtk::Window>, &link, 0);
}
PostInput::OpenCreateCommentDialog => {
CREATE_COMMENT_DIALOG_BROKER.send(DialogMsg::Show)
}
PostInput::CreatedComment(comment) => {
self.comments.guard().push_front(comment);
}
PostInput::CreateCommentRequest(body) => {
let id = self.info.post_view.post.id.0;
std::thread::spawn(move || {
let message = match api::comment::create_comment(id, body, None) {
Ok(comment) => Some(PostInput::CreatedComment(comment.comment_view)),
Err(err) => { println!("{}", err.to_string()); None }
};
if message.is_some() { sender.input(message.unwrap()) };
});
}
}
}
}

View File

@ -2,11 +2,20 @@ use relm4::{prelude::*, MessageBroker};
use gtk::prelude::*;
pub static CREATE_POST_DIALOG_BROKER: MessageBroker<DialogMsg> = MessageBroker::new();
pub static CREATE_COMMENT_DIALOG_BROKER: MessageBroker<DialogMsg> = MessageBroker::new();
pub struct CreatePostDialog {
type_: DialogType,
visible: bool,
}
#[derive(Debug, Clone, Copy)]
pub enum DialogType {
Post,
Comment
}
#[derive(Debug)]
pub enum DialogMsg {
Show,
@ -16,12 +25,12 @@ pub enum DialogMsg {
#[derive(Debug)]
pub enum CreatePostDialogOutput {
CreatePostRequest(String, String)
CreateRequest(String, String)
}
#[relm4::component(pub)]
impl SimpleComponent for CreatePostDialog {
type Init = ();
type Init = DialogType;
type Input = DialogMsg;
type Output = CreatePostDialogOutput;
@ -38,6 +47,10 @@ impl SimpleComponent for CreatePostDialog {
set_width_request: 600,
set_margin_all: 20,
match model.type_ {
DialogType::Post => {
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
gtk::Label {
set_halign: gtk::Align::Center,
set_valign: gtk::Align::Center,
@ -50,12 +63,27 @@ impl SimpleComponent for CreatePostDialog {
set_margin_top: 10,
set_margin_bottom: 10,
},
}
}
DialogType::Comment => {
gtk::Box {
gtk::Label {
set_halign: gtk::Align::Center,
set_valign: gtk::Align::Center,
set_label: "Create comment",
add_css_class: "font-bold"
},
}
}
},
gtk::Label {
set_text: "Body:",
set_halign: gtk::Align::Start,
},
#[name(body)]
gtk::TextView {
set_editable: true,
set_margin_top: 5,
set_margin_bottom: 10,
set_vexpand: true,
},
@ -74,8 +102,16 @@ impl SimpleComponent for CreatePostDialog {
let body_buffer = body.buffer();
let (start, end) = &body_buffer.bounds();
let body = body_buffer.text(start, end, true).to_string();
match model.type_ {
DialogType::Post => {
if name.is_empty() || body.is_empty() { return; }
sender.input(DialogMsg::Okay(name, body))
}
DialogType::Comment => {
if name.is_empty() { return; }
sender.input(DialogMsg::Okay(name, body))
}
}
},
}
}
@ -89,11 +125,11 @@ impl SimpleComponent for CreatePostDialog {
}
fn init(
_init: Self::Init,
init: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = CreatePostDialog { visible: false };
let model = CreatePostDialog { type_: init, visible: false };
let widgets = view_output!();
ComponentParts { model, widgets }
}
@ -103,7 +139,7 @@ impl SimpleComponent for CreatePostDialog {
DialogMsg::Show => self.visible = true,
DialogMsg::Hide => self.visible = false,
DialogMsg::Okay(name, body) => {
let _ = sender.output(CreatePostDialogOutput::CreatePostRequest(name, body));
let _ = sender.output(CreatePostDialogOutput::CreateRequest(name, body));
self.visible = false;
}
}