Move communities page into a separate component
This commit is contained in:
parent
ae6bf45879
commit
0755f2a0de
|
@ -0,0 +1,152 @@
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use lemmy_api_common::{
|
||||||
|
lemmy_db_schema::ListingType, lemmy_db_views_actor::structs::CommunityView,
|
||||||
|
};
|
||||||
|
use relm4::{factory::FactoryVecDeque, prelude::*};
|
||||||
|
|
||||||
|
use crate::api;
|
||||||
|
|
||||||
|
use super::community_row::CommunityRow;
|
||||||
|
|
||||||
|
pub struct CommunitiesPage {
|
||||||
|
communities: FactoryVecDeque<CommunityRow>,
|
||||||
|
communities_page: i64,
|
||||||
|
communities_type: ListingType,
|
||||||
|
community_search_buffer: gtk::EntryBuffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum CommunitiesPageInput {
|
||||||
|
DoneFetchCommunities(Vec<CommunityView>),
|
||||||
|
FetchCommunities(ListingType, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::component(pub)]
|
||||||
|
impl SimpleComponent for CommunitiesPage {
|
||||||
|
type Init = ();
|
||||||
|
type Input = CommunitiesPageInput;
|
||||||
|
type Output = crate::AppMsg;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
gtk::Box {
|
||||||
|
gtk::ScrolledWindow {
|
||||||
|
set_vexpand: true,
|
||||||
|
set_hexpand: true,
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 10,
|
||||||
|
set_margin_all: 10,
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
|
set_spacing: 10,
|
||||||
|
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "All",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.communities_type == ListingType::All,
|
||||||
|
connect_clicked => CommunitiesPageInput::FetchCommunities(ListingType::All, true),
|
||||||
|
},
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "Local",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.communities_type == ListingType::Local,
|
||||||
|
connect_clicked => CommunitiesPageInput::FetchCommunities(ListingType::Local, true),
|
||||||
|
},
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "Subscribed",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.communities_type == ListingType::Subscribed,
|
||||||
|
connect_clicked => CommunitiesPageInput::FetchCommunities(ListingType::Subscribed, true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_spacing: 10,
|
||||||
|
|
||||||
|
gtk::Entry {
|
||||||
|
set_hexpand: true,
|
||||||
|
set_tooltip_text: Some("Search"),
|
||||||
|
set_buffer: &model.community_search_buffer,
|
||||||
|
},
|
||||||
|
gtk::Button {
|
||||||
|
set_label: "Search",
|
||||||
|
connect_clicked => CommunitiesPageInput::FetchCommunities(model.communities_type, true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
#[local_ref]
|
||||||
|
communities_box -> gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 5,
|
||||||
|
},
|
||||||
|
|
||||||
|
gtk::Button {
|
||||||
|
set_label: "More",
|
||||||
|
connect_clicked => CommunitiesPageInput::FetchCommunities(model.communities_type, false),
|
||||||
|
set_margin_top: 10,
|
||||||
|
set_margin_bottom: 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(
|
||||||
|
_init: Self::Init,
|
||||||
|
root: &Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
|
let communities = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
|
||||||
|
let community_search_buffer = gtk::EntryBuffer::builder().build();
|
||||||
|
let model = CommunitiesPage {
|
||||||
|
communities,
|
||||||
|
community_search_buffer,
|
||||||
|
communities_page: 1,
|
||||||
|
communities_type: ListingType::Local,
|
||||||
|
};
|
||||||
|
let communities_box = model.communities.widget();
|
||||||
|
let widgets = view_output!();
|
||||||
|
ComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
|
||||||
|
match message {
|
||||||
|
CommunitiesPageInput::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)
|
||||||
|
};
|
||||||
|
let page = if remove_previous {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
self.communities_page + 1
|
||||||
|
};
|
||||||
|
self.communities_page = page;
|
||||||
|
self.communities_type = listing_type;
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
match api::communities::fetch_communities(page, query, Some(listing_type)) {
|
||||||
|
Ok(communities) => {
|
||||||
|
sender.input(CommunitiesPageInput::DoneFetchCommunities(communities));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let _ = sender.output(crate::AppMsg::ShowMessage(err.to_string()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CommunitiesPageInput::DoneFetchCommunities(communities) => {
|
||||||
|
if self.communities_page == 1 {
|
||||||
|
self.communities.guard().clear();
|
||||||
|
}
|
||||||
|
for community in communities {
|
||||||
|
self.communities.guard().push_back(community);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod comment_row;
|
pub mod comment_row;
|
||||||
|
pub mod communities_page;
|
||||||
pub mod community_page;
|
pub mod community_page;
|
||||||
pub mod community_row;
|
pub mod community_row;
|
||||||
pub mod inbox_page;
|
pub mod inbox_page;
|
||||||
|
|
110
src/main.rs
110
src/main.rs
|
@ -7,8 +7,8 @@ pub mod util;
|
||||||
|
|
||||||
use api::{community::default_community, post::default_post, user::default_person};
|
use api::{community::default_community, post::default_post, user::default_person};
|
||||||
use components::{
|
use components::{
|
||||||
|
communities_page::{CommunitiesPage, CommunitiesPageInput},
|
||||||
community_page::{self, CommunityPage},
|
community_page::{self, CommunityPage},
|
||||||
community_row::CommunityRow,
|
|
||||||
inbox_page::{InboxInput, InboxPage},
|
inbox_page::{InboxInput, InboxPage},
|
||||||
instances_page::{InstancePageInput, InstancesPage},
|
instances_page::{InstancePageInput, InstancesPage},
|
||||||
post_page::{self, PostPage},
|
post_page::{self, PostPage},
|
||||||
|
@ -24,7 +24,6 @@ use lemmy_api_common::{
|
||||||
ListingType,
|
ListingType,
|
||||||
},
|
},
|
||||||
lemmy_db_views::structs::PostView,
|
lemmy_db_views::structs::PostView,
|
||||||
lemmy_db_views_actor::structs::CommunityView,
|
|
||||||
person::GetPersonDetailsResponse,
|
person::GetPersonDetailsResponse,
|
||||||
post::GetPostResponse,
|
post::GetPostResponse,
|
||||||
};
|
};
|
||||||
|
@ -55,18 +54,15 @@ struct App {
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
back_queue: Vec<AppMsg>,
|
back_queue: Vec<AppMsg>,
|
||||||
posts: FactoryVecDeque<PostRow>,
|
posts: FactoryVecDeque<PostRow>,
|
||||||
communities: FactoryVecDeque<CommunityRow>,
|
|
||||||
instances_page: Controller<InstancesPage>,
|
instances_page: Controller<InstancesPage>,
|
||||||
profile_page: Controller<ProfilePage>,
|
profile_page: Controller<ProfilePage>,
|
||||||
community_page: Controller<CommunityPage>,
|
community_page: Controller<CommunityPage>,
|
||||||
|
communities_page: Controller<CommunitiesPage>,
|
||||||
post_page: Controller<PostPage>,
|
post_page: Controller<PostPage>,
|
||||||
inbox_page: Controller<InboxPage>,
|
inbox_page: Controller<InboxPage>,
|
||||||
logged_in: bool,
|
logged_in: bool,
|
||||||
current_communities_type: Option<ListingType>,
|
|
||||||
current_posts_type: Option<ListingType>,
|
current_posts_type: Option<ListingType>,
|
||||||
current_communities_page: i64,
|
|
||||||
current_posts_page: i64,
|
current_posts_page: i64,
|
||||||
community_search_buffer: gtk::EntryBuffer,
|
|
||||||
about_dialog: Controller<AboutDialog>,
|
about_dialog: Controller<AboutDialog>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +77,6 @@ pub enum AppMsg {
|
||||||
DoneChoosingInstance(String),
|
DoneChoosingInstance(String),
|
||||||
StartFetchPosts(Option<ListingType>, bool),
|
StartFetchPosts(Option<ListingType>, bool),
|
||||||
DoneFetchPosts(Vec<PostView>),
|
DoneFetchPosts(Vec<PostView>),
|
||||||
DoneFetchCommunities(Vec<CommunityView>),
|
|
||||||
FetchCommunities(Option<ListingType>, bool),
|
|
||||||
OpenCommunity(CommunityId),
|
OpenCommunity(CommunityId),
|
||||||
DoneFetchCommunity(GetCommunityResponse),
|
DoneFetchCommunity(GetCommunityResponse),
|
||||||
OpenPerson(PersonId),
|
OpenPerson(PersonId),
|
||||||
|
@ -90,6 +84,7 @@ pub enum AppMsg {
|
||||||
OpenPost(PostId),
|
OpenPost(PostId),
|
||||||
DoneFetchPost(GetPostResponse),
|
DoneFetchPost(GetPostResponse),
|
||||||
OpenInbox,
|
OpenInbox,
|
||||||
|
OpenCommunities,
|
||||||
PopBackStack,
|
PopBackStack,
|
||||||
ShowAbout,
|
ShowAbout,
|
||||||
}
|
}
|
||||||
|
@ -124,7 +119,7 @@ impl SimpleComponent for App {
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
pack_start = >k::Button {
|
||||||
set_label: "Communities",
|
set_label: "Communities",
|
||||||
connect_clicked => AppMsg::FetchCommunities(None, true),
|
connect_clicked => AppMsg::OpenCommunities,
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
pack_start = >k::Button {
|
||||||
set_label: "Recommended",
|
set_label: "Recommended",
|
||||||
|
@ -132,12 +127,6 @@ impl SimpleComponent for App {
|
||||||
#[watch]
|
#[watch]
|
||||||
set_visible: model.logged_in,
|
set_visible: model.logged_in,
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
|
||||||
set_label: "Joined",
|
|
||||||
connect_clicked => AppMsg::FetchCommunities(Some(ListingType::Subscribed), true),
|
|
||||||
#[watch]
|
|
||||||
set_visible: model.logged_in,
|
|
||||||
},
|
|
||||||
pack_start = >k::Button {
|
pack_start = >k::Button {
|
||||||
set_label: "Inbox",
|
set_label: "Inbox",
|
||||||
connect_clicked => AppMsg::OpenInbox,
|
connect_clicked => AppMsg::OpenInbox,
|
||||||
|
@ -233,42 +222,8 @@ impl SimpleComponent for App {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AppState::Communities => gtk::Box {
|
AppState::Communities => gtk::Box {
|
||||||
gtk::ScrolledWindow {
|
#[local_ref]
|
||||||
set_vexpand: true,
|
communities_page -> gtk::Box {}
|
||||||
set_hexpand: true,
|
|
||||||
|
|
||||||
gtk::Box {
|
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
|
||||||
set_spacing: 10,
|
|
||||||
|
|
||||||
gtk::Box {
|
|
||||||
set_margin_all: 10,
|
|
||||||
|
|
||||||
gtk::Entry {
|
|
||||||
set_hexpand: true,
|
|
||||||
set_tooltip_text: Some("Search"),
|
|
||||||
set_margin_end: 10,
|
|
||||||
set_buffer: &model.community_search_buffer,
|
|
||||||
},
|
|
||||||
gtk::Button {
|
|
||||||
set_label: "Search",
|
|
||||||
connect_clicked => AppMsg::FetchCommunities(model.current_communities_type, true),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
#[local_ref]
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AppState::Person => {
|
AppState::Person => {
|
||||||
|
@ -340,7 +295,6 @@ impl SimpleComponent for App {
|
||||||
|
|
||||||
// initialize all controllers and factories
|
// initialize all controllers and factories
|
||||||
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
|
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
|
||||||
let communities = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
|
|
||||||
let instances_page = InstancesPage::builder()
|
let instances_page = InstancesPage::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), |msg| msg);
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
|
@ -356,7 +310,9 @@ impl SimpleComponent for App {
|
||||||
let inbox_page = InboxPage::builder()
|
let inbox_page = InboxPage::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), |msg| msg);
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
let community_search_buffer = gtk::EntryBuffer::builder().build();
|
let communities_page = CommunitiesPage::builder()
|
||||||
|
.launch(())
|
||||||
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
let about_dialog = AboutDialog::builder()
|
let about_dialog = AboutDialog::builder()
|
||||||
.launch(root.toplevel_window().unwrap())
|
.launch(root.toplevel_window().unwrap())
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -366,18 +322,15 @@ impl SimpleComponent for App {
|
||||||
back_queue: vec![],
|
back_queue: vec![],
|
||||||
logged_in,
|
logged_in,
|
||||||
posts,
|
posts,
|
||||||
communities,
|
|
||||||
instances_page,
|
instances_page,
|
||||||
profile_page,
|
profile_page,
|
||||||
community_page,
|
community_page,
|
||||||
post_page,
|
post_page,
|
||||||
inbox_page,
|
inbox_page,
|
||||||
|
communities_page,
|
||||||
message: None,
|
message: None,
|
||||||
current_communities_type: None,
|
|
||||||
current_posts_type: None,
|
current_posts_type: None,
|
||||||
current_communities_page: 1,
|
|
||||||
current_posts_page: 1,
|
current_posts_page: 1,
|
||||||
community_search_buffer,
|
|
||||||
about_dialog,
|
about_dialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -388,12 +341,12 @@ impl SimpleComponent for App {
|
||||||
|
|
||||||
// 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();
|
||||||
let communities_box = model.communities.widget();
|
|
||||||
let instances_page = model.instances_page.widget();
|
let instances_page = model.instances_page.widget();
|
||||||
let profile_page = model.profile_page.widget();
|
let profile_page = model.profile_page.widget();
|
||||||
let community_page = model.community_page.widget();
|
let community_page = model.community_page.widget();
|
||||||
let post_page = model.post_page.widget();
|
let post_page = model.post_page.widget();
|
||||||
let inbox_page = model.inbox_page.widget();
|
let inbox_page = model.inbox_page.widget();
|
||||||
|
let communities_page = model.communities_page.widget();
|
||||||
|
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
|
|
||||||
|
@ -438,7 +391,7 @@ impl SimpleComponent for App {
|
||||||
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||||
// save the back queue
|
// save the back queue
|
||||||
match msg {
|
match msg {
|
||||||
AppMsg::DoneFetchCommunities(_)
|
AppMsg::OpenCommunities
|
||||||
| AppMsg::DoneFetchCommunity(_)
|
| AppMsg::DoneFetchCommunity(_)
|
||||||
| AppMsg::DoneFetchPerson(_)
|
| AppMsg::DoneFetchPerson(_)
|
||||||
| AppMsg::DoneFetchPost(_)
|
| AppMsg::DoneFetchPost(_)
|
||||||
|
@ -506,39 +459,14 @@ impl SimpleComponent for App {
|
||||||
self.posts.guard().push_back(post);
|
self.posts.guard().push_back(post);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppMsg::FetchCommunities(listing_type, remove_previous) => {
|
AppMsg::OpenCommunities => {
|
||||||
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 {
|
self.communities_page
|
||||||
1
|
.sender()
|
||||||
} else {
|
.emit(CommunitiesPageInput::FetchCommunities(
|
||||||
self.current_communities_page + 1
|
ListingType::Local,
|
||||||
};
|
true,
|
||||||
self.current_communities_page = page;
|
));
|
||||||
self.current_communities_type = listing_type;
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
let message =
|
|
||||||
match api::communities::fetch_communities(page, query, listing_type) {
|
|
||||||
Ok(communities) => AppMsg::DoneFetchCommunities(communities),
|
|
||||||
Err(err) => AppMsg::ShowMessage(err.to_string()),
|
|
||||||
};
|
|
||||||
sender.input(message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
AppMsg::DoneFetchCommunities(communities) => {
|
|
||||||
self.state = AppState::Communities;
|
|
||||||
if self.current_communities_page == 1 {
|
|
||||||
self.communities.guard().clear();
|
|
||||||
}
|
|
||||||
for community in communities {
|
|
||||||
self.communities.guard().push_back(community);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
AppMsg::OpenPerson(person_id) => {
|
AppMsg::OpenPerson(person_id) => {
|
||||||
self.state = AppState::Loading;
|
self.state = AppState::Loading;
|
||||||
|
|
Loading…
Reference in New Issue