diff --git a/src/api/posts.rs b/src/api/posts.rs index 51710c4..d2f6533 100644 --- a/src/api/posts.rs +++ b/src/api/posts.rs @@ -1,5 +1,5 @@ use lemmy_api_common::{ - lemmy_db_schema::ListingType, + lemmy_db_schema::{ListingType, SortType}, lemmy_db_views::structs::PostView, post::{GetPosts, GetPostsResponse}, }; @@ -10,10 +10,12 @@ pub fn list_posts( page: i64, community_name: Option, listing_type: Option, + sort_type: Option, ) -> std::result::Result, reqwest::Error> { let params = GetPosts { page: Some(page), type_: listing_type, + sort: sort_type, community_name, auth: settings::get_current_account().jwt, ..Default::default() diff --git a/src/components/community_page.rs b/src/components/community_page.rs index 3f8a2fb..8cc0786 100644 --- a/src/components/community_page.rs +++ b/src/components/community_page.rs @@ -184,7 +184,7 @@ impl SimpleComponent for CommunityPage { 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); + let community_posts = api::posts::list_posts(page, Some(name), None, None); if let Ok(community_posts) = community_posts { sender.input(CommunityInput::DoneFetchPosts(community_posts)); } diff --git a/src/components/mod.rs b/src/components/mod.rs index 55f024b..2442c9b 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -15,4 +15,5 @@ pub mod post_row; pub mod posts_page; pub mod private_message_row; pub mod profile_page; +pub mod sort_dropown; pub mod voting_row; diff --git a/src/components/posts_page.rs b/src/components/posts_page.rs index 704bd79..414ce86 100644 --- a/src/components/posts_page.rs +++ b/src/components/posts_page.rs @@ -1,21 +1,24 @@ 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 crate::api; -use super::post_row::PostRow; +use super::{post_row::PostRow, sort_dropown::{SortDropdown, SortDropdownOutput}}; pub struct PostsPage { + sort_dropdown: Controller, posts: FactoryVecDeque, + posts_order: SortType, posts_type: ListingType, posts_page: i64, } #[derive(Debug)] pub enum PostsPageInput { - FetchPosts(ListingType, bool), + FetchPosts(ListingType, SortType, bool), DoneFetchPosts(Vec), + UpdateOrder(SortType), } #[relm4::component(pub)] @@ -40,20 +43,27 @@ impl SimpleComponent for PostsPage { set_label: "All", #[watch] 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 { set_label: "Local", #[watch] 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 { set_label: "Subscribed", #[watch] 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] posts_box -> gtk::Box { @@ -62,7 +72,7 @@ impl SimpleComponent for PostsPage { }, gtk::Button { 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, } } @@ -74,12 +84,20 @@ impl SimpleComponent for PostsPage { root: &Self::Root, sender: ComponentSender, ) -> ComponentParts { + 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 model = Self { + sort_dropdown, posts, posts_type: ListingType::Local, + posts_order: SortType::Hot, posts_page: 1, }; + let sort_dropdown = model.sort_dropdown.widget(); let posts_box = model.posts.widget(); let widgets = view_output!(); ComponentParts { model, widgets } @@ -87,8 +105,9 @@ impl SimpleComponent for PostsPage { fn update(&mut self, message: Self::Input, sender: ComponentSender) { match message { - PostsPageInput::FetchPosts(type_, remove_previous) => { + PostsPageInput::FetchPosts(type_, order, remove_previous) => { self.posts_type = type_; + self.posts_order = order; let page = if remove_previous { 1 } else { @@ -102,7 +121,7 @@ impl SimpleComponent for PostsPage { } self.posts_page = page; 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) => { sender.input(PostsPageInput::DoneFetchPosts(posts)); } @@ -123,6 +142,10 @@ impl SimpleComponent for PostsPage { self.posts.guard().push_back(post); } } + PostsPageInput::UpdateOrder(order) => { + self.posts_order = order; + sender.input_sender().emit(PostsPageInput::FetchPosts(self.posts_type, order, true)); + } } } } diff --git a/src/components/sort_dropown.rs b/src/components/sort_dropown.rs new file mode 100644 index 0000000..8880716 --- /dev/null +++ b/src/components/sort_dropown.rs @@ -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, + ) -> ComponentParts { + 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 } + } +} diff --git a/src/main.rs b/src/main.rs index c1239da..3ff2352 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ use lemmy_api_common::{ community::GetCommunityResponse, lemmy_db_schema::{ newtypes::{CommunityId, PersonId, PostId}, - ListingType, + ListingType, SortType, }, post::GetPostResponse, }; @@ -465,7 +465,7 @@ impl SimpleComponent for App { AppMsg::OpenPosts => self .posts_page .sender() - .emit(PostsPageInput::FetchPosts(ListingType::Local, true)), + .emit(PostsPageInput::FetchPosts(ListingType::Local, SortType::Hot, true)), } } }