Support for viewing the next pages of communities and posts

This commit is contained in:
Bnyro 2023-06-23 16:26:59 +02:00
parent 598288434f
commit 07343a3021
6 changed files with 71 additions and 37 deletions

View File

@ -22,9 +22,8 @@ Working:
- Editing and deleting posts or comments - Editing and deleting posts or comments
- Viewing the personal inbox (mentions, replies) - 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 - Private messages
# Build dependencies # Build dependencies

View File

@ -137,7 +137,7 @@ impl FactoryComponent for CommentRow {
let comment_id = self.comment.comment.id; let comment_id = self.comment.comment.id;
std::thread::spawn(move || { std::thread::spawn(move || {
let _ = api::comment::delete_comment(comment_id); 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 => { CommentRowMsg::OpenEditCommentDialog => {

View File

@ -16,11 +16,13 @@ pub struct CommunityPage {
posts: FactoryVecDeque<PostRow>, posts: FactoryVecDeque<PostRow>,
#[allow(dead_code)] #[allow(dead_code)]
create_post_dialog: Controller<EditorDialog>, create_post_dialog: Controller<EditorDialog>,
current_posts_page: i64
} }
#[derive(Debug)] #[derive(Debug)]
pub enum CommunityInput { pub enum CommunityInput {
UpdateCommunity(CommunityView), UpdateCommunity(CommunityView),
FetchPosts,
DoneFetchPosts(Vec<PostView>), DoneFetchPosts(Vec<PostView>),
OpenCreatePostDialog, OpenCreatePostDialog,
CreatePostRequest(EditorData), CreatePostRequest(EditorData),
@ -112,6 +114,12 @@ impl SimpleComponent for CommunityPage {
#[local_ref] #[local_ref]
posts -> gtk::Box { posts -> gtk::Box {
set_orientation: gtk::Orientation::Vertical, 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 _ => 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 avatar = model.avatar.widget();
let posts = model.posts.widget(); let posts = model.posts.widget();
let widgets = view_output!(); let widgets = view_output!();
@ -148,10 +156,16 @@ impl SimpleComponent for CommunityPage {
self.info = community.clone(); self.info = community.clone();
self.avatar.emit(get_web_image_msg(community.community.icon)); self.avatar.emit(get_web_image_msg(community.community.icon));
self.posts.guard().clear(); self.posts.guard().clear();
self.current_posts_page = 0;
std::thread::spawn(move || {
if community.counts.posts == 0 { return; } if community.counts.posts == 0 { return; }
let community_posts = api::posts::list_posts(1, Some(community.community.name), None); 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 || {
let community_posts = api::posts::list_posts(page, Some(name), None);
if let Ok(community_posts) = community_posts { if let Ok(community_posts) = community_posts {
sender.input(CommunityInput::DoneFetchPosts(community_posts)); sender.input(CommunityInput::DoneFetchPosts(community_posts));
} }

View File

@ -280,7 +280,7 @@ impl SimpleComponent for PostPage {
let post_id = self.info.post_view.post.id; let post_id = self.info.post_view.post.id;
std::thread::spawn(move || { std::thread::spawn(move || {
let _ = api::post::delete_post(post_id); let _ = api::post::delete_post(post_id);
let _ = sender.output(crate::AppMsg::StartFetchPosts(None)); let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true));
}); });
} }
PostInput::OpenEditPostDialog => { PostInput::OpenEditPostDialog => {

View File

@ -162,7 +162,7 @@ impl FactoryComponent for PostRow {
let post_id = self.post.post.id; let post_id = self.post.post.id;
std::thread::spawn(move || { std::thread::spawn(move || {
let _ = api::post::delete_post(post_id); let _ = api::post::delete_post(post_id);
let _ = sender.output(crate::AppMsg::StartFetchPosts(None)); let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true));
}); });
} }
} }

View File

@ -40,6 +40,9 @@ struct App {
logged_in: bool, logged_in: bool,
current_communities_type: Option<ListingType>, current_communities_type: Option<ListingType>,
current_posts_type: Option<ListingType>, current_posts_type: Option<ListingType>,
current_communities_page: i64,
current_posts_page: i64,
community_search_buffer: gtk::EntryBuffer,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -52,10 +55,10 @@ pub enum AppMsg {
Retry, Retry,
ShowMessage(String), ShowMessage(String),
DoneChoosingInstance(String), DoneChoosingInstance(String),
StartFetchPosts(Option<ListingType>), StartFetchPosts(Option<ListingType>, bool),
DoneFetchPosts(Vec<PostView>), DoneFetchPosts(Vec<PostView>),
DoneFetchCommunities(Vec<CommunityView>), DoneFetchCommunities(Vec<CommunityView>),
ViewCommunities(Option<String>, Option<ListingType>), FetchCommunities(Option<ListingType>, bool),
OpenCommunity(String), OpenCommunity(String),
DoneFetchCommunity(GetCommunityResponse), DoneFetchCommunity(GetCommunityResponse),
OpenPerson(String), OpenPerson(String),
@ -85,21 +88,21 @@ impl SimpleComponent for App {
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
set_label: "Home", set_label: "Home",
connect_clicked => AppMsg::StartFetchPosts(None), connect_clicked => AppMsg::StartFetchPosts(None, true),
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
set_label: "Communities", set_label: "Communities",
connect_clicked => AppMsg::ViewCommunities(None, None), connect_clicked => AppMsg::FetchCommunities(None, true),
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
set_label: "Recommended", set_label: "Recommended",
connect_clicked => AppMsg::StartFetchPosts(Some(ListingType::Subscribed)), connect_clicked => AppMsg::StartFetchPosts(Some(ListingType::Subscribed), true),
#[watch] #[watch]
set_visible: model.logged_in, set_visible: model.logged_in,
}, },
pack_start = &gtk::Button { pack_start = &gtk::Button {
set_label: "Joined", set_label: "Joined",
connect_clicked => AppMsg::ViewCommunities(None, Some(ListingType::Subscribed)), connect_clicked => AppMsg::FetchCommunities(Some(ListingType::Subscribed), true),
#[watch] #[watch]
set_visible: model.logged_in, set_visible: model.logged_in,
}, },
@ -113,13 +116,22 @@ impl SimpleComponent for App {
match model.state { match model.state {
AppState::Posts => gtk::ScrolledWindow { AppState::Posts => gtk::ScrolledWindow {
set_vexpand: true,
set_hexpand: true, set_hexpand: true,
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
#[local_ref] #[local_ref]
posts_box -> gtk::Box { posts_box -> gtk::Box {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_spacing: 5, 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 { AppState::Loading => gtk::Box {
@ -186,7 +198,7 @@ impl SimpleComponent for App {
gtk::Button { gtk::Button {
set_label: "Cancel", set_label: "Cancel",
connect_clicked => AppMsg::StartFetchPosts(None), connect_clicked => AppMsg::StartFetchPosts(None, true),
set_margin_end: 10, set_margin_end: 10,
}, },
gtk::Button { gtk::Button {
@ -213,7 +225,6 @@ impl SimpleComponent for App {
gtk::Box { gtk::Box {
set_margin_all: 10, set_margin_all: 10,
#[name(community_search_query)]
gtk::Entry { gtk::Entry {
set_hexpand: true, set_hexpand: true,
set_tooltip_text: Some("Search"), set_tooltip_text: Some("Search"),
@ -221,10 +232,7 @@ impl SimpleComponent for App {
}, },
gtk::Button { gtk::Button {
set_label: "Search", set_label: "Search",
connect_clicked[sender, community_search_query] => move |_| { connect_clicked => AppMsg::FetchCommunities(model.current_communities_type, true),
let text = community_search_query.text().as_str().to_string();
sender.input(AppMsg::ViewCommunities(Some(text), model.current_communities_type));
},
} }
}, },
@ -232,6 +240,12 @@ impl SimpleComponent for App {
communities_box -> gtk::Box { communities_box -> gtk::Box {
set_orientation: gtk::Orientation::Vertical, set_orientation: gtk::Orientation::Vertical,
set_spacing: 5, 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 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 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 inbox_page = InboxPage::builder().launch(()).forward(sender.input_sender(), |msg| msg);
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 }; 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 // 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 // setup all widgets and different stack pages
let posts_box = model.posts.widget(); let posts_box = model.posts.widget();
@ -357,15 +372,17 @@ impl SimpleComponent for App {
current_account.instance_url = instance_url; current_account.instance_url = instance_url;
settings::update_current_account(current_account); settings::update_current_account(current_account);
self.state = AppState::Loading; self.state = AppState::Loading;
sender.input(AppMsg::StartFetchPosts(None)); sender.input(AppMsg::StartFetchPosts(None, true));
} }
AppMsg::ChooseInstance => { AppMsg::ChooseInstance => {
self.state = AppState::ChooseInstance; self.state = AppState::ChooseInstance;
} }
AppMsg::StartFetchPosts(type_) => { AppMsg::StartFetchPosts(type_, remove_previous) => {
self.current_posts_type = type_; 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 || { 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), Ok(posts) => AppMsg::DoneFetchPosts(posts),
Err(err) => AppMsg::ShowMessage(err.to_string()) Err(err) => AppMsg::ShowMessage(err.to_string())
}; };
@ -374,16 +391,20 @@ impl SimpleComponent for App {
} }
AppMsg::DoneFetchPosts(posts) => { AppMsg::DoneFetchPosts(posts) => {
self.state = AppState::Posts; self.state = AppState::Posts;
self.posts.guard().clear(); if self.current_posts_page == 1 { self.posts.guard().clear(); }
for post in posts { for post in posts {
self.posts.guard().push_back(post); 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; 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; self.current_communities_type = listing_type;
std::thread::spawn(move || { 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), Ok(communities) => AppMsg::DoneFetchCommunities(communities),
Err(err) => AppMsg::ShowMessage(err.to_string()) Err(err) => AppMsg::ShowMessage(err.to_string())
}; };
@ -392,7 +413,7 @@ impl SimpleComponent for App {
} }
AppMsg::DoneFetchCommunities(communities) => { AppMsg::DoneFetchCommunities(communities) => {
self.state = AppState::Communities; self.state = AppState::Communities;
self.communities.guard().clear(); if self.current_communities_page == 1 { self.communities.guard().clear(); }
for community in communities { for community in communities {
self.communities.guard().push_back(community); self.communities.guard().push_back(community);
} }
@ -479,14 +500,14 @@ impl SimpleComponent for App {
self.state = AppState::Message; self.state = AppState::Message;
} }
AppMsg::Retry => { 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 => { AppMsg::OpenInbox => {
self.state = AppState::Inbox; self.state = AppState::Inbox;
} }
AppMsg::LoggedIn => { AppMsg::LoggedIn => {
self.logged_in = true; self.logged_in = true;
sender.input(AppMsg::StartFetchPosts(None)); sender.input(AppMsg::StartFetchPosts(None, true));
} }
} }
} }