Support for subscribing and unsubscribing communities

This commit is contained in:
Bnyro 2023-06-20 15:46:40 +02:00
parent 0417cea437
commit 99e122ed9a
3 changed files with 61 additions and 24 deletions

View File

@ -12,7 +12,7 @@ pub fn get_community(name: String) -> std::result::Result<GetCommunityResponse,
super::get("/community", &params)
}
pub async fn follow_community(
pub fn follow_community(
community_id: i32,
follow: bool,
) -> Result<CommunityResponse, reqwest::Error> {

View File

@ -1,5 +1,5 @@
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 lemmy_api_common::{lemmy_db_views::structs::PostView, lemmy_db_views_actor::structs::CommunityView, lemmy_db_schema::SubscribedType};
use relm4::{prelude::*, factory::FactoryVecDeque};
use gtk::prelude::*;
use relm4_components::web_image::WebImage;
@ -9,25 +9,27 @@ use crate::{api, util::get_web_image_msg};
use super::post_row::PostRow;
pub struct CommunityPage {
info: GetCommunityResponse,
info: CommunityView,
avatar: Controller<WebImage>,
posts: FactoryVecDeque<PostRow>,
#[allow(dead_code)]
create_post_dialog: Controller<CreatePostDialog>
create_post_dialog: Controller<CreatePostDialog>,
}
#[derive(Debug)]
pub enum CommunityInput {
UpdateCommunity(GetCommunityResponse),
UpdateCommunity(CommunityView),
DoneFetchPosts(Vec<PostView>),
OpenCreatePostDialog,
CreatePostRequest(String, String),
CreatedPost(PostView)
CreatedPost(PostView),
ToggleSubscription,
UpdateSubscriptionState(SubscribedType)
}
#[relm4::component(pub)]
impl SimpleComponent for CommunityPage {
type Init = GetCommunityResponse;
type Init = CommunityView;
type Input = CommunityInput;
type Output = crate::AppMsg;
@ -48,29 +50,47 @@ impl SimpleComponent for CommunityPage {
},
gtk::Label {
#[watch]
set_text: &model.info.community_view.community.name,
set_text: &model.info.community.name,
add_css_class: "font-very-bold",
},
gtk::Label {
#[watch]
set_markup: &markdown_to_pango_markup(model.info.clone().community_view.community.description.unwrap_or("".to_string())),
set_markup: &markdown_to_pango_markup(model.info.clone().community.description.unwrap_or("".to_string())),
set_use_markup: true,
},
gtk::Label {
#[watch]
set_text: &format!("{} subscribers", model.info.community_view.counts.subscribers),
},
gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
set_margin_top: 10,
set_margin_bottom: 10,
set_hexpand: false,
set_halign: gtk::Align::Center,
set_margin_bottom: 10,
gtk::Label {
#[watch]
set_text: &format!("{} posts, {} comments", model.info.community_view.counts.posts, model.info.community_view.counts.comments),
set_text: &format!("{} subscribers", model.info.counts.subscribers),
set_margin_end: 10,
},
match model.info.subscribed {
SubscribedType::Subscribed => {
gtk::Button {
set_label: "Unsubscribe",
connect_clicked => CommunityInput::ToggleSubscription,
}
}
SubscribedType::NotSubscribed => {
gtk::Button {
set_label: "Subscribe",
connect_clicked => CommunityInput::ToggleSubscription,
}
}
SubscribedType::Pending => {
gtk::Label {
set_label: "Subscription pending",
}
}
},
gtk::Label {
#[watch]
set_text: &format!("{} posts, {} comments", model.info.counts.posts, model.info.counts.comments),
set_margin_start: 10,
},
gtk::Button {
@ -118,12 +138,12 @@ impl SimpleComponent for CommunityPage {
match message {
CommunityInput::UpdateCommunity(community) => {
self.info = community.clone();
self.avatar.emit(get_web_image_msg(community.community_view.community.icon));
self.avatar.emit(get_web_image_msg(community.community.icon));
self.posts.guard().clear();
std::thread::spawn(move || {
if community.community_view.counts.posts == 0 { return; }
let community_posts = api::posts::list_posts(1, Some(community.community_view.community.name), None);
if community.counts.posts == 0 { return; }
let community_posts = api::posts::list_posts(1, Some(community.community.name), None);
if let Ok(community_posts) = community_posts {
sender.input(CommunityInput::DoneFetchPosts(community_posts));
}
@ -141,7 +161,7 @@ impl SimpleComponent for CommunityPage {
self.posts.guard().push_front(post);
}
CommunityInput::CreatePostRequest(name, body) => {
let id = self.info.community_view.community.id.0.clone();
let id = self.info.community.id.0.clone();
std::thread::spawn(move || {
let message = match api::post::create_post(name, body, id) {
Ok(post) => Some(CommunityInput::CreatedPost(post.post_view)),
@ -150,6 +170,23 @@ impl SimpleComponent for CommunityPage {
if message.is_some() { sender.input(message.unwrap()) };
});
}
CommunityInput::ToggleSubscription => {
let community_id = self.info.community.id.0;
let new_state = match self.info.subscribed {
SubscribedType::NotSubscribed => true,
_ => false
};
std::thread::spawn(move || {
let message = match api::community::follow_community(community_id, new_state) {
Ok(community) => Some(CommunityInput::UpdateSubscriptionState(community.community_view.subscribed)),
Err(err) => { println!("{}", err.to_string()); None }
};
if message.is_some() { sender.input(message.unwrap()) };
});
}
CommunityInput::UpdateSubscriptionState(state) => {
self.info.subscribed = state;
}
}
}
}

View File

@ -272,7 +272,7 @@ impl SimpleComponent for App {
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
let communities = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
let profile_page = ProfilePage::builder().launch(default_person()).forward(sender.input_sender(), |msg| msg);
let community_page = CommunityPage::builder().launch(default_community()).forward(sender.input_sender(), |msg| msg);
let community_page = CommunityPage::builder().launch(default_community().community_view).forward(sender.input_sender(), |msg| msg);
let post_page = PostPage::builder().launch(default_post()).forward(sender.input_sender(), |msg| msg);
let model = App { state, posts, communities, profile_page, community_page, post_page, message: None, latest_action: None };
@ -383,7 +383,7 @@ impl SimpleComponent for App {
});
}
AppMsg::DoneFetchCommunity(community) => {
self.community_page.sender().emit(community_page::CommunityInput::UpdateCommunity(community));
self.community_page.sender().emit(community_page::CommunityInput::UpdateCommunity(community.community_view));
self.state = AppState::Community;
}
AppMsg::OpenPost(post_id) => {