From 07343a30213690c73a016e66f6417256ebff390c Mon Sep 17 00:00:00 2001 From: Bnyro Date: Fri, 23 Jun 2023 16:26:59 +0200 Subject: [PATCH] Support for viewing the next pages of communities and posts --- README.md | 3 +- src/components/comment_row.rs | 2 +- src/components/community_page.rs | 22 +++++++-- src/components/post_page.rs | 2 +- src/components/post_row.rs | 2 +- src/main.rs | 77 ++++++++++++++++++++------------ 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 09bb5df..82e93e1 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,8 @@ Working: - Editing and deleting posts or comments - Viewing the personal inbox (mentions, replies) -Not yet working, but planned to be added soon: +Not yet supported: -- Viewing the next pages of posts or communities - Private messages # Build dependencies diff --git a/src/components/comment_row.rs b/src/components/comment_row.rs index 4cc6ead..d767477 100644 --- a/src/components/comment_row.rs +++ b/src/components/comment_row.rs @@ -137,7 +137,7 @@ impl FactoryComponent for CommentRow { let comment_id = self.comment.comment.id; std::thread::spawn(move || { let _ = api::comment::delete_comment(comment_id); - let _ = sender.output(PostInput::PassAppMessage(crate::AppMsg::StartFetchPosts(None))); + let _ = sender.output(PostInput::PassAppMessage(crate::AppMsg::StartFetchPosts(None, true))); }); } CommentRowMsg::OpenEditCommentDialog => { diff --git a/src/components/community_page.rs b/src/components/community_page.rs index 8edd327..d0fb694 100644 --- a/src/components/community_page.rs +++ b/src/components/community_page.rs @@ -16,11 +16,13 @@ pub struct CommunityPage { posts: FactoryVecDeque, #[allow(dead_code)] create_post_dialog: Controller, + current_posts_page: i64 } #[derive(Debug)] pub enum CommunityInput { UpdateCommunity(CommunityView), + FetchPosts, DoneFetchPosts(Vec), OpenCreatePostDialog, CreatePostRequest(EditorData), @@ -112,6 +114,12 @@ impl SimpleComponent for CommunityPage { #[local_ref] posts -> gtk::Box { set_orientation: gtk::Orientation::Vertical, + }, + + gtk::Button { + set_label: "More", + set_margin_all: 10, + connect_clicked => CommunityInput::FetchPosts, } } @@ -134,7 +142,7 @@ impl SimpleComponent for CommunityPage { _ => CommunityInput::None }); - let model = CommunityPage { info: init, avatar, posts, create_post_dialog: dialog }; + let model = CommunityPage { info: init, avatar, posts, create_post_dialog: dialog, current_posts_page: 0 }; let avatar = model.avatar.widget(); let posts = model.posts.widget(); let widgets = view_output!(); @@ -148,10 +156,16 @@ impl SimpleComponent for CommunityPage { self.info = community.clone(); self.avatar.emit(get_web_image_msg(community.community.icon)); self.posts.guard().clear(); - + self.current_posts_page = 0; + if community.counts.posts == 0 { return; } + sender.input(CommunityInput::FetchPosts); + } + CommunityInput::FetchPosts => { + let name = self.info.community.name.clone(); + self.current_posts_page += 1; + let page = self.current_posts_page; std::thread::spawn(move || { - if community.counts.posts == 0 { return; } - let community_posts = api::posts::list_posts(1, Some(community.community.name), None); + let community_posts = api::posts::list_posts(page, Some(name), None); if let Ok(community_posts) = community_posts { sender.input(CommunityInput::DoneFetchPosts(community_posts)); } diff --git a/src/components/post_page.rs b/src/components/post_page.rs index 30e3f98..d388119 100644 --- a/src/components/post_page.rs +++ b/src/components/post_page.rs @@ -280,7 +280,7 @@ impl SimpleComponent for PostPage { let post_id = self.info.post_view.post.id; std::thread::spawn(move || { let _ = api::post::delete_post(post_id); - let _ = sender.output(crate::AppMsg::StartFetchPosts(None)); + let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true)); }); } PostInput::OpenEditPostDialog => { diff --git a/src/components/post_row.rs b/src/components/post_row.rs index 299e1c8..7986606 100644 --- a/src/components/post_row.rs +++ b/src/components/post_row.rs @@ -162,7 +162,7 @@ impl FactoryComponent for PostRow { 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)); + let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true)); }); } } diff --git a/src/main.rs b/src/main.rs index 02aa22b..bd8f360 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,6 +40,9 @@ struct App { logged_in: bool, current_communities_type: Option, current_posts_type: Option, + current_communities_page: i64, + current_posts_page: i64, + community_search_buffer: gtk::EntryBuffer, } #[derive(Debug, Clone)] @@ -52,10 +55,10 @@ pub enum AppMsg { Retry, ShowMessage(String), DoneChoosingInstance(String), - StartFetchPosts(Option), + StartFetchPosts(Option, bool), DoneFetchPosts(Vec), DoneFetchCommunities(Vec), - ViewCommunities(Option, Option), + FetchCommunities(Option, bool), OpenCommunity(String), DoneFetchCommunity(GetCommunityResponse), OpenPerson(String), @@ -85,21 +88,21 @@ impl SimpleComponent for App { }, pack_start = >k::Button { set_label: "Home", - connect_clicked => AppMsg::StartFetchPosts(None), + connect_clicked => AppMsg::StartFetchPosts(None, true), }, pack_start = >k::Button { set_label: "Communities", - connect_clicked => AppMsg::ViewCommunities(None, None), + connect_clicked => AppMsg::FetchCommunities(None, true), }, pack_start = >k::Button { set_label: "Recommended", - connect_clicked => AppMsg::StartFetchPosts(Some(ListingType::Subscribed)), + connect_clicked => AppMsg::StartFetchPosts(Some(ListingType::Subscribed), true), #[watch] set_visible: model.logged_in, }, pack_start = >k::Button { set_label: "Joined", - connect_clicked => AppMsg::ViewCommunities(None, Some(ListingType::Subscribed)), + connect_clicked => AppMsg::FetchCommunities(Some(ListingType::Subscribed), true), #[watch] set_visible: model.logged_in, }, @@ -113,13 +116,22 @@ impl SimpleComponent for App { match model.state { AppState::Posts => gtk::ScrolledWindow { - set_vexpand: true, set_hexpand: true, - #[local_ref] - posts_box -> gtk::Box { + gtk::Box { set_orientation: gtk::Orientation::Vertical, - set_spacing: 5, + + #[local_ref] + posts_box -> gtk::Box { + set_orientation: gtk::Orientation::Vertical, + set_spacing: 5, + }, + + gtk::Button { + set_label: "More", + connect_clicked => AppMsg::StartFetchPosts(model.current_posts_type, false), + set_margin_all: 10, + } } }, AppState::Loading => gtk::Box { @@ -186,7 +198,7 @@ impl SimpleComponent for App { gtk::Button { set_label: "Cancel", - connect_clicked => AppMsg::StartFetchPosts(None), + connect_clicked => AppMsg::StartFetchPosts(None, true), set_margin_end: 10, }, gtk::Button { @@ -213,7 +225,6 @@ impl SimpleComponent for App { gtk::Box { set_margin_all: 10, - #[name(community_search_query)] gtk::Entry { set_hexpand: true, set_tooltip_text: Some("Search"), @@ -221,10 +232,7 @@ impl SimpleComponent for App { }, gtk::Button { set_label: "Search", - connect_clicked[sender, community_search_query] => move |_| { - let text = community_search_query.text().as_str().to_string(); - sender.input(AppMsg::ViewCommunities(Some(text), model.current_communities_type)); - }, + connect_clicked => AppMsg::FetchCommunities(model.current_communities_type, true), } }, @@ -232,6 +240,12 @@ impl SimpleComponent for App { communities_box -> gtk::Box { set_orientation: gtk::Orientation::Vertical, set_spacing: 5, + }, + + gtk::Button { + set_label: "More", + connect_clicked => AppMsg::FetchCommunities(model.current_communities_type, false), + set_margin_all: 10, } } } @@ -305,11 +319,12 @@ impl SimpleComponent for App { 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 inbox_page = InboxPage::builder().launch(()).forward(sender.input_sender(), |msg| msg); - - let model = App { state, logged_in, posts, communities, profile_page, community_page, post_page, inbox_page, message: None, latest_action: None, current_communities_type: None, current_posts_type: None }; + let community_search_buffer = gtk::EntryBuffer::builder().build(); + + let model = App { state, logged_in, posts, communities, profile_page, community_page, post_page, inbox_page, message: None, latest_action: None, current_communities_type: None, current_posts_type: None, current_communities_page: 1, current_posts_page: 1, community_search_buffer }; // fetch posts if that's the initial page - if !current_account.instance_url.is_empty() { sender.input(AppMsg::StartFetchPosts(None)) }; + if !current_account.instance_url.is_empty() { sender.input(AppMsg::StartFetchPosts(None, true)) }; // setup all widgets and different stack pages let posts_box = model.posts.widget(); @@ -357,15 +372,17 @@ impl SimpleComponent for App { current_account.instance_url = instance_url; settings::update_current_account(current_account); self.state = AppState::Loading; - sender.input(AppMsg::StartFetchPosts(None)); + sender.input(AppMsg::StartFetchPosts(None, true)); } AppMsg::ChooseInstance => { self.state = AppState::ChooseInstance; } - AppMsg::StartFetchPosts(type_) => { + AppMsg::StartFetchPosts(type_, remove_previous) => { self.current_posts_type = type_; + let page = if remove_previous { 1 } else { self.current_posts_page + 1 }; + self.current_posts_page = page; std::thread::spawn(move || { - let message = match api::posts::list_posts(1, None, type_) { + let message = match api::posts::list_posts(page, None, type_) { Ok(posts) => AppMsg::DoneFetchPosts(posts), Err(err) => AppMsg::ShowMessage(err.to_string()) }; @@ -374,16 +391,20 @@ impl SimpleComponent for App { } AppMsg::DoneFetchPosts(posts) => { self.state = AppState::Posts; - self.posts.guard().clear(); + if self.current_posts_page == 1 { self.posts.guard().clear(); } for post in posts { self.posts.guard().push_back(post); } } - AppMsg::ViewCommunities(query, listing_type) => { + AppMsg::FetchCommunities(listing_type, remove_previous) => { + let query_text = self.community_search_buffer.text().as_str().to_owned(); + let query = if query_text.is_empty() { None } else { Some(query_text) }; self.state = AppState::Communities; + let page = if remove_previous { 1 } else { self.current_communities_page + 1 }; + self.current_communities_page = page; self.current_communities_type = listing_type; std::thread::spawn(move || { - let message = match api::communities::fetch_communities(1, query, listing_type) { + let message = match api::communities::fetch_communities(page, query, listing_type) { Ok(communities) => AppMsg::DoneFetchCommunities(communities), Err(err) => AppMsg::ShowMessage(err.to_string()) }; @@ -392,7 +413,7 @@ impl SimpleComponent for App { } AppMsg::DoneFetchCommunities(communities) => { self.state = AppState::Communities; - self.communities.guard().clear(); + if self.current_communities_page == 1 { self.communities.guard().clear(); } for community in communities { self.communities.guard().push_back(community); } @@ -479,14 +500,14 @@ impl SimpleComponent for App { self.state = AppState::Message; } AppMsg::Retry => { - sender.input(self.latest_action.clone().unwrap_or(AppMsg::StartFetchPosts(None))); + sender.input(self.latest_action.clone().unwrap_or(AppMsg::StartFetchPosts(None, true))); } AppMsg::OpenInbox => { self.state = AppState::Inbox; } AppMsg::LoggedIn => { self.logged_in = true; - sender.input(AppMsg::StartFetchPosts(None)); + sender.input(AppMsg::StartFetchPosts(None, true)); } } }