feat(posts): option to set the sort order

This commit is contained in:
Bnyro 2023-08-06 13:41:38 +02:00
parent 2cd1c678bd
commit b96ad40fb4
6 changed files with 109 additions and 14 deletions

View File

@ -1,5 +1,5 @@
use lemmy_api_common::{ use lemmy_api_common::{
lemmy_db_schema::ListingType, lemmy_db_schema::{ListingType, SortType},
lemmy_db_views::structs::PostView, lemmy_db_views::structs::PostView,
post::{GetPosts, GetPostsResponse}, post::{GetPosts, GetPostsResponse},
}; };
@ -10,10 +10,12 @@ pub fn list_posts(
page: i64, page: i64,
community_name: Option<String>, community_name: Option<String>,
listing_type: Option<ListingType>, listing_type: Option<ListingType>,
sort_type: Option<SortType>,
) -> std::result::Result<Vec<PostView>, reqwest::Error> { ) -> std::result::Result<Vec<PostView>, reqwest::Error> {
let params = GetPosts { let params = GetPosts {
page: Some(page), page: Some(page),
type_: listing_type, type_: listing_type,
sort: sort_type,
community_name, community_name,
auth: settings::get_current_account().jwt, auth: settings::get_current_account().jwt,
..Default::default() ..Default::default()

View File

@ -184,7 +184,7 @@ impl SimpleComponent for CommunityPage {
self.current_posts_page += 1; self.current_posts_page += 1;
let page = self.current_posts_page; let page = self.current_posts_page;
std::thread::spawn(move || { std::thread::spawn(move || {
let community_posts = api::posts::list_posts(page, Some(name), None); let community_posts = api::posts::list_posts(page, Some(name), None, 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

@ -15,4 +15,5 @@ pub mod post_row;
pub mod posts_page; pub mod posts_page;
pub mod private_message_row; pub mod private_message_row;
pub mod profile_page; pub mod profile_page;
pub mod sort_dropown;
pub mod voting_row; pub mod voting_row;

View File

@ -1,21 +1,24 @@
use gtk::prelude::*; use gtk::prelude::*;
use lemmy_api_common::{lemmy_db_schema::ListingType, lemmy_db_views::structs::PostView}; use lemmy_api_common::{lemmy_db_schema::{ListingType, SortType}, lemmy_db_views::structs::PostView};
use relm4::{factory::FactoryVecDeque, prelude::*}; use relm4::{factory::FactoryVecDeque, prelude::*};
use crate::api; use crate::api;
use super::post_row::PostRow; use super::{post_row::PostRow, sort_dropown::{SortDropdown, SortDropdownOutput}};
pub struct PostsPage { pub struct PostsPage {
sort_dropdown: Controller<SortDropdown>,
posts: FactoryVecDeque<PostRow>, posts: FactoryVecDeque<PostRow>,
posts_order: SortType,
posts_type: ListingType, posts_type: ListingType,
posts_page: i64, posts_page: i64,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum PostsPageInput { pub enum PostsPageInput {
FetchPosts(ListingType, bool), FetchPosts(ListingType, SortType, bool),
DoneFetchPosts(Vec<PostView>), DoneFetchPosts(Vec<PostView>),
UpdateOrder(SortType),
} }
#[relm4::component(pub)] #[relm4::component(pub)]
@ -40,20 +43,27 @@ impl SimpleComponent for PostsPage {
set_label: "All", set_label: "All",
#[watch] #[watch]
set_active: model.posts_type == ListingType::All, set_active: model.posts_type == ListingType::All,
connect_clicked => PostsPageInput::FetchPosts(ListingType::All, true), connect_clicked => PostsPageInput::FetchPosts(ListingType::All, model.posts_order, true),
}, },
gtk::ToggleButton { gtk::ToggleButton {
set_label: "Local", set_label: "Local",
#[watch] #[watch]
set_active: model.posts_type ==ListingType::Local, set_active: model.posts_type ==ListingType::Local,
connect_clicked => PostsPageInput::FetchPosts(ListingType::Local, true), connect_clicked => PostsPageInput::FetchPosts(ListingType::Local, model.posts_order, true),
}, },
gtk::ToggleButton { gtk::ToggleButton {
set_label: "Subscribed", set_label: "Subscribed",
#[watch] #[watch]
set_active: model.posts_type == ListingType::Subscribed, set_active: model.posts_type == ListingType::Subscribed,
connect_clicked => PostsPageInput::FetchPosts(ListingType::Subscribed, true), connect_clicked => PostsPageInput::FetchPosts(ListingType::Subscribed, model.posts_order, true),
} },
gtk::Box {
set_hexpand: true,
},
#[local_ref]
sort_dropdown -> gtk::DropDown {},
}, },
#[local_ref] #[local_ref]
posts_box -> gtk::Box { posts_box -> gtk::Box {
@ -62,7 +72,7 @@ impl SimpleComponent for PostsPage {
}, },
gtk::Button { gtk::Button {
set_label: "More", set_label: "More",
connect_clicked => PostsPageInput::FetchPosts(model.posts_type, false), connect_clicked => PostsPageInput::FetchPosts(model.posts_type, model.posts_order, false),
set_margin_all: 10, set_margin_all: 10,
} }
} }
@ -74,12 +84,20 @@ impl SimpleComponent for PostsPage {
root: &Self::Root, root: &Self::Root,
sender: ComponentSender<Self>, sender: ComponentSender<Self>,
) -> ComponentParts<Self> { ) -> ComponentParts<Self> {
let sort_dropdown = SortDropdown::builder().launch(()).forward(sender.input_sender(), |msg| {
match msg {
SortDropdownOutput::New(sort_order) => PostsPageInput::UpdateOrder(sort_order),
}
});
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender()); let posts = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
let model = Self { let model = Self {
sort_dropdown,
posts, posts,
posts_type: ListingType::Local, posts_type: ListingType::Local,
posts_order: SortType::Hot,
posts_page: 1, posts_page: 1,
}; };
let sort_dropdown = model.sort_dropdown.widget();
let posts_box = model.posts.widget(); let posts_box = model.posts.widget();
let widgets = view_output!(); let widgets = view_output!();
ComponentParts { model, widgets } ComponentParts { model, widgets }
@ -87,8 +105,9 @@ impl SimpleComponent for PostsPage {
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) { fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
match message { match message {
PostsPageInput::FetchPosts(type_, remove_previous) => { PostsPageInput::FetchPosts(type_, order, remove_previous) => {
self.posts_type = type_; self.posts_type = type_;
self.posts_order = order;
let page = if remove_previous { let page = if remove_previous {
1 1
} else { } else {
@ -102,7 +121,7 @@ impl SimpleComponent for PostsPage {
} }
self.posts_page = page; self.posts_page = page;
std::thread::spawn(move || { std::thread::spawn(move || {
match api::posts::list_posts(page, None, Some(type_)) { match api::posts::list_posts(page, None, Some(type_), Some(order)) {
Ok(posts) => { Ok(posts) => {
sender.input(PostsPageInput::DoneFetchPosts(posts)); sender.input(PostsPageInput::DoneFetchPosts(posts));
} }
@ -123,6 +142,10 @@ impl SimpleComponent for PostsPage {
self.posts.guard().push_back(post); self.posts.guard().push_back(post);
} }
} }
PostsPageInput::UpdateOrder(order) => {
self.posts_order = order;
sender.input_sender().emit(PostsPageInput::FetchPosts(self.posts_type, order, true));
}
} }
} }
} }

View File

@ -0,0 +1,69 @@
use lemmy_api_common::lemmy_db_schema::SortType;
use relm4::prelude::*;
pub struct SortDropdown {}
#[derive(Debug)]
pub enum SortDropdownOutput {
New(SortType),
}
pub struct Widgets {}
impl SimpleComponent for SortDropdown {
type Init = ();
type Input = ();
type Output = SortDropdownOutput;
type Root = gtk::DropDown;
type Widgets = Widgets;
fn init_root() -> Self::Root {
gtk::DropDown::from_strings(&[
"Hot",
"New",
"Active",
"Old",
"Top All",
"Top Today",
"Top Week",
"Top Month",
"Top Year",
"Most comments",
"New comments",
"Top current hour",
"Top 6 hours",
])
}
fn init(
_init: Self::Init,
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = Self {};
let dropdown = root.clone();
dropdown.connect_selected_item_notify(move |dropdown| {
let sort_type = match dropdown.selected() {
0 => SortType::Hot,
1 => SortType::New,
2 => SortType::Active,
3 => SortType::Old,
4 => SortType::TopAll,
5 => SortType::TopDay,
6 => SortType::TopWeek,
7 => SortType::TopMonth,
8 => SortType::TopYear,
9 => SortType::MostComments,
10 => SortType::NewComments,
11 => SortType::TopHour,
12 => SortType::TopSixHour,
_ => SortType::Active,
};
sender
.output_sender()
.emit(SortDropdownOutput::New(sort_type));
});
let widgets = Widgets {};
ComponentParts { model, widgets }
}
}

View File

@ -22,7 +22,7 @@ use lemmy_api_common::{
community::GetCommunityResponse, community::GetCommunityResponse,
lemmy_db_schema::{ lemmy_db_schema::{
newtypes::{CommunityId, PersonId, PostId}, newtypes::{CommunityId, PersonId, PostId},
ListingType, ListingType, SortType,
}, },
post::GetPostResponse, post::GetPostResponse,
}; };
@ -465,7 +465,7 @@ impl SimpleComponent for App {
AppMsg::OpenPosts => self AppMsg::OpenPosts => self
.posts_page .posts_page
.sender() .sender()
.emit(PostsPageInput::FetchPosts(ListingType::Local, true)), .emit(PostsPageInput::FetchPosts(ListingType::Local, SortType::Hot, true)),
} }
} }
} }