refactor posts/home page
This commit is contained in:
parent
b38d225540
commit
6266004dcb
|
@ -164,9 +164,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);
|
||||||
sender
|
sender.output_sender().emit(crate::AppMsg::OpenPosts);
|
||||||
.output_sender()
|
|
||||||
.emit(crate::AppMsg::StartFetchPosts(None, true));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
CommentRowMsg::OpenEditor(is_new) => {
|
CommentRowMsg::OpenEditor(is_new) => {
|
||||||
|
|
|
@ -128,7 +128,7 @@ impl SimpleComponent for InstancesPage {
|
||||||
current_account.instance_url = url[0..url.len() - 1].to_string();
|
current_account.instance_url = url[0..url.len() - 1].to_string();
|
||||||
current_account.jwt = None;
|
current_account.jwt = None;
|
||||||
settings::update_current_account(current_account);
|
settings::update_current_account(current_account);
|
||||||
crate::AppMsg::StartFetchPosts(None, true)
|
crate::AppMsg::OpenPosts
|
||||||
}
|
}
|
||||||
Err(err) => crate::AppMsg::ShowMessage(err.to_string()),
|
Err(err) => crate::AppMsg::ShowMessage(err.to_string()),
|
||||||
};
|
};
|
||||||
|
|
|
@ -119,9 +119,7 @@ impl SimpleComponent for LoginPage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
LoginPageInput::Cancel => {
|
LoginPageInput::Cancel => {
|
||||||
sender
|
sender.output_sender().emit(crate::AppMsg::OpenPosts);
|
||||||
.output_sender()
|
|
||||||
.emit(crate::AppMsg::StartFetchPosts(None, true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub mod mention_row;
|
||||||
pub mod moderates_row;
|
pub mod moderates_row;
|
||||||
pub mod post_page;
|
pub mod post_page;
|
||||||
pub mod post_row;
|
pub mod post_row;
|
||||||
|
pub mod posts_page;
|
||||||
pub mod private_message_row;
|
pub mod private_message_row;
|
||||||
pub mod profile_page;
|
pub mod profile_page;
|
||||||
pub mod voting_row;
|
pub mod voting_row;
|
||||||
|
|
|
@ -316,9 +316,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);
|
||||||
sender
|
sender.output_sender().emit(crate::AppMsg::OpenPosts);
|
||||||
.output_sender()
|
|
||||||
.emit(crate::AppMsg::StartFetchPosts(None, true));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
PostPageInput::OpenEditPostDialog => {
|
PostPageInput::OpenEditPostDialog => {
|
||||||
|
|
|
@ -165,9 +165,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);
|
||||||
sender
|
sender.output_sender().emit(crate::AppMsg::OpenPosts);
|
||||||
.output_sender()
|
|
||||||
.emit(crate::AppMsg::StartFetchPosts(None, true));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use lemmy_api_common::{lemmy_db_schema::ListingType, lemmy_db_views::structs::PostView};
|
||||||
|
use relm4::{factory::FactoryVecDeque, prelude::*};
|
||||||
|
|
||||||
|
use crate::api;
|
||||||
|
|
||||||
|
use super::post_row::PostRow;
|
||||||
|
|
||||||
|
pub struct PostsPage {
|
||||||
|
posts: FactoryVecDeque<PostRow>,
|
||||||
|
posts_type: ListingType,
|
||||||
|
posts_page: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PostsPageInput {
|
||||||
|
FetchPosts(ListingType, bool),
|
||||||
|
DoneFetchPosts(Vec<PostView>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::component(pub)]
|
||||||
|
impl SimpleComponent for PostsPage {
|
||||||
|
type Init = ();
|
||||||
|
type Input = PostsPageInput;
|
||||||
|
type Output = crate::AppMsg;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
gtk::ScrolledWindow {
|
||||||
|
set_hexpand: true,
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_margin_all: 10,
|
||||||
|
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
|
set_spacing: 10,
|
||||||
|
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "All",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.posts_type == ListingType::All,
|
||||||
|
connect_clicked => PostsPageInput::FetchPosts(ListingType::All, true),
|
||||||
|
},
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "Local",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.posts_type ==ListingType::Local,
|
||||||
|
connect_clicked => PostsPageInput::FetchPosts(ListingType::Local, true),
|
||||||
|
},
|
||||||
|
gtk::ToggleButton {
|
||||||
|
set_label: "Subscribed",
|
||||||
|
#[watch]
|
||||||
|
set_active: model.posts_type == ListingType::Subscribed,
|
||||||
|
connect_clicked => PostsPageInput::FetchPosts(ListingType::Subscribed, true),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
#[local_ref]
|
||||||
|
posts_box -> gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 5,
|
||||||
|
},
|
||||||
|
gtk::Button {
|
||||||
|
set_label: "More",
|
||||||
|
connect_clicked => PostsPageInput::FetchPosts(model.posts_type, false),
|
||||||
|
set_margin_all: 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(
|
||||||
|
_init: Self::Init,
|
||||||
|
root: &Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
|
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.output_sender());
|
||||||
|
let model = Self {
|
||||||
|
posts,
|
||||||
|
posts_type: ListingType::Subscribed,
|
||||||
|
posts_page: 1,
|
||||||
|
};
|
||||||
|
let posts_box = model.posts.widget();
|
||||||
|
let widgets = view_output!();
|
||||||
|
ComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
|
||||||
|
match message {
|
||||||
|
PostsPageInput::FetchPosts(type_, remove_previous) => {
|
||||||
|
self.posts_type = type_;
|
||||||
|
let page = if remove_previous {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
self.posts_page + 1
|
||||||
|
};
|
||||||
|
// show the loading indicator if it's the first page
|
||||||
|
if page == 1 {
|
||||||
|
sender
|
||||||
|
.output_sender()
|
||||||
|
.emit(crate::AppMsg::UpdateState(crate::AppState::Loading));
|
||||||
|
}
|
||||||
|
self.posts_page = page;
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
match api::posts::list_posts(page, None, Some(type_)) {
|
||||||
|
Ok(posts) => {
|
||||||
|
sender.input(PostsPageInput::DoneFetchPosts(posts));
|
||||||
|
}
|
||||||
|
Err(err) => sender
|
||||||
|
.output_sender()
|
||||||
|
.emit(crate::AppMsg::ShowMessage(err.to_string())),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
PostsPageInput::DoneFetchPosts(posts) => {
|
||||||
|
sender
|
||||||
|
.output_sender()
|
||||||
|
.emit(crate::AppMsg::UpdateState(crate::AppState::Posts));
|
||||||
|
if self.posts_page == 1 {
|
||||||
|
self.posts.guard().clear();
|
||||||
|
}
|
||||||
|
for post in posts {
|
||||||
|
self.posts.guard().push_back(post);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
91
src/main.rs
91
src/main.rs
|
@ -12,7 +12,7 @@ use components::{
|
||||||
inbox_page::{InboxInput, InboxPage},
|
inbox_page::{InboxInput, InboxPage},
|
||||||
instances_page::{InstancesPage, InstancesPageInput},
|
instances_page::{InstancesPage, InstancesPageInput},
|
||||||
post_page::{self, PostPage},
|
post_page::{self, PostPage},
|
||||||
post_row::PostRow,
|
posts_page::{PostsPage, PostsPageInput},
|
||||||
profile_page::{ProfileInput, ProfilePage},
|
profile_page::{ProfileInput, ProfilePage},
|
||||||
};
|
};
|
||||||
use dialogs::about::AboutDialog;
|
use dialogs::about::AboutDialog;
|
||||||
|
@ -23,12 +23,10 @@ use lemmy_api_common::{
|
||||||
newtypes::{CommunityId, PersonId, PostId},
|
newtypes::{CommunityId, PersonId, PostId},
|
||||||
ListingType,
|
ListingType,
|
||||||
},
|
},
|
||||||
lemmy_db_views::structs::PostView,
|
|
||||||
post::GetPostResponse,
|
post::GetPostResponse,
|
||||||
};
|
};
|
||||||
use relm4::{
|
use relm4::{
|
||||||
actions::{RelmAction, RelmActionGroup},
|
actions::{RelmAction, RelmActionGroup},
|
||||||
factory::FactoryVecDeque,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
set_global_css,
|
set_global_css,
|
||||||
};
|
};
|
||||||
|
@ -53,8 +51,8 @@ struct App {
|
||||||
state: AppState,
|
state: AppState,
|
||||||
message: Option<String>,
|
message: Option<String>,
|
||||||
back_queue: Vec<AppMsg>,
|
back_queue: Vec<AppMsg>,
|
||||||
posts: FactoryVecDeque<PostRow>,
|
|
||||||
instances_page: Controller<InstancesPage>,
|
instances_page: Controller<InstancesPage>,
|
||||||
|
posts_page: Controller<PostsPage>,
|
||||||
profile_page: Controller<ProfilePage>,
|
profile_page: Controller<ProfilePage>,
|
||||||
community_page: Controller<CommunityPage>,
|
community_page: Controller<CommunityPage>,
|
||||||
communities_page: Controller<CommunitiesPage>,
|
communities_page: Controller<CommunitiesPage>,
|
||||||
|
@ -62,8 +60,6 @@ struct App {
|
||||||
inbox_page: Controller<InboxPage>,
|
inbox_page: Controller<InboxPage>,
|
||||||
login_page: Controller<LoginPage>,
|
login_page: Controller<LoginPage>,
|
||||||
logged_in: bool,
|
logged_in: bool,
|
||||||
current_posts_type: Option<ListingType>,
|
|
||||||
current_posts_page: i64,
|
|
||||||
about_dialog: Controller<AboutDialog>,
|
about_dialog: Controller<AboutDialog>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,8 +70,7 @@ pub enum AppMsg {
|
||||||
LoggedIn,
|
LoggedIn,
|
||||||
Logout,
|
Logout,
|
||||||
ShowMessage(String),
|
ShowMessage(String),
|
||||||
StartFetchPosts(Option<ListingType>, bool),
|
OpenPosts,
|
||||||
DoneFetchPosts(Vec<PostView>),
|
|
||||||
OpenCommunity(CommunityId),
|
OpenCommunity(CommunityId),
|
||||||
DoneFetchCommunity(GetCommunityResponse),
|
DoneFetchCommunity(GetCommunityResponse),
|
||||||
OpenPerson(PersonId),
|
OpenPerson(PersonId),
|
||||||
|
@ -112,19 +107,13 @@ impl SimpleComponent for App {
|
||||||
set_visible: model.back_queue.len() > 1,
|
set_visible: model.back_queue.len() > 1,
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
pack_start = >k::Button {
|
||||||
set_label: "Home",
|
set_label: "Posts",
|
||||||
connect_clicked => AppMsg::StartFetchPosts(None, true),
|
connect_clicked => AppMsg::OpenPosts,
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
pack_start = >k::Button {
|
||||||
set_label: "Communities",
|
set_label: "Communities",
|
||||||
connect_clicked => AppMsg::OpenCommunities,
|
connect_clicked => AppMsg::OpenCommunities,
|
||||||
},
|
},
|
||||||
pack_start = >k::Button {
|
|
||||||
set_label: "Recommended",
|
|
||||||
connect_clicked => AppMsg::StartFetchPosts(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,
|
||||||
|
@ -134,24 +123,9 @@ impl SimpleComponent for App {
|
||||||
},
|
},
|
||||||
|
|
||||||
match model.state {
|
match model.state {
|
||||||
AppState::Posts => gtk::ScrolledWindow {
|
AppState::Posts => gtk::Box {
|
||||||
set_hexpand: true,
|
|
||||||
|
|
||||||
gtk::Box {
|
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
|
||||||
|
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
posts_box -> gtk::Box {
|
posts_page -> gtk::ScrolledWindow {}
|
||||||
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 {
|
AppState::Loading => gtk::Box {
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
|
@ -248,8 +222,10 @@ impl SimpleComponent for App {
|
||||||
};
|
};
|
||||||
let logged_in = current_account.jwt.is_some();
|
let logged_in = current_account.jwt.is_some();
|
||||||
|
|
||||||
// initialize all controllers and factories
|
// initialize all controllers for the various components
|
||||||
let posts = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
|
let posts_page = PostsPage::builder()
|
||||||
|
.launch(())
|
||||||
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
let instances_page = InstancesPage::builder()
|
let instances_page = InstancesPage::builder()
|
||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), |msg| msg);
|
.forward(sender.input_sender(), |msg| msg);
|
||||||
|
@ -279,7 +255,7 @@ impl SimpleComponent for App {
|
||||||
state,
|
state,
|
||||||
back_queue: vec![],
|
back_queue: vec![],
|
||||||
logged_in,
|
logged_in,
|
||||||
posts,
|
posts_page,
|
||||||
instances_page,
|
instances_page,
|
||||||
profile_page,
|
profile_page,
|
||||||
community_page,
|
community_page,
|
||||||
|
@ -288,18 +264,16 @@ impl SimpleComponent for App {
|
||||||
communities_page,
|
communities_page,
|
||||||
login_page,
|
login_page,
|
||||||
message: None,
|
message: None,
|
||||||
current_posts_type: None,
|
|
||||||
current_posts_page: 1,
|
|
||||||
about_dialog,
|
about_dialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
// fetch posts if that's the initial page
|
// fetch posts if that's the initial page
|
||||||
if !current_account.instance_url.is_empty() {
|
if !current_account.instance_url.is_empty() {
|
||||||
sender.input(AppMsg::StartFetchPosts(None, true))
|
sender.input(AppMsg::OpenPosts)
|
||||||
};
|
};
|
||||||
|
|
||||||
// setup all widgets and different stack pages
|
// setup all widgets and different stack pages
|
||||||
let posts_box = model.posts.widget();
|
let posts_page = model.posts_page.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();
|
||||||
|
@ -355,7 +329,7 @@ impl SimpleComponent for App {
|
||||||
| AppMsg::DoneFetchCommunity(_)
|
| AppMsg::DoneFetchCommunity(_)
|
||||||
| AppMsg::OpenPerson(_)
|
| AppMsg::OpenPerson(_)
|
||||||
| AppMsg::DoneFetchPost(_)
|
| AppMsg::DoneFetchPost(_)
|
||||||
| AppMsg::DoneFetchPosts(_)
|
| AppMsg::OpenPosts
|
||||||
| AppMsg::ShowMessage(_) => self.back_queue.push(msg.clone()),
|
| AppMsg::ShowMessage(_) => self.back_queue.push(msg.clone()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -367,35 +341,6 @@ impl SimpleComponent for App {
|
||||||
.sender()
|
.sender()
|
||||||
.emit(InstancesPageInput::FetchInstances);
|
.emit(InstancesPageInput::FetchInstances);
|
||||||
}
|
}
|
||||||
AppMsg::StartFetchPosts(type_, remove_previous) => {
|
|
||||||
self.current_posts_type = type_;
|
|
||||||
let page = if remove_previous {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
self.current_posts_page + 1
|
|
||||||
};
|
|
||||||
// show the loading indicator if it's the first page
|
|
||||||
if page == 1 {
|
|
||||||
self.state = AppState::Loading;
|
|
||||||
}
|
|
||||||
self.current_posts_page = page;
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
let message = match api::posts::list_posts(page, None, type_) {
|
|
||||||
Ok(posts) => AppMsg::DoneFetchPosts(posts),
|
|
||||||
Err(err) => AppMsg::ShowMessage(err.to_string()),
|
|
||||||
};
|
|
||||||
sender.input(message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
AppMsg::DoneFetchPosts(posts) => {
|
|
||||||
self.state = AppState::Posts;
|
|
||||||
if self.current_posts_page == 1 {
|
|
||||||
self.posts.guard().clear();
|
|
||||||
}
|
|
||||||
for post in posts {
|
|
||||||
self.posts.guard().push_back(post);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AppMsg::OpenCommunities => {
|
AppMsg::OpenCommunities => {
|
||||||
self.state = AppState::Communities;
|
self.state = AppState::Communities;
|
||||||
self.communities_page
|
self.communities_page
|
||||||
|
@ -465,7 +410,7 @@ impl SimpleComponent for App {
|
||||||
AppMsg::LoggedIn => {
|
AppMsg::LoggedIn => {
|
||||||
self.logged_in = true;
|
self.logged_in = true;
|
||||||
self.back_queue.clear();
|
self.back_queue.clear();
|
||||||
sender.input(AppMsg::StartFetchPosts(None, true));
|
sender.input(AppMsg::OpenPosts);
|
||||||
}
|
}
|
||||||
AppMsg::PopBackStack => {
|
AppMsg::PopBackStack => {
|
||||||
let action = self.back_queue.get(self.back_queue.len() - 2);
|
let action = self.back_queue.get(self.back_queue.len() - 2);
|
||||||
|
@ -479,6 +424,10 @@ impl SimpleComponent for App {
|
||||||
AppMsg::UpdateState(state) => {
|
AppMsg::UpdateState(state) => {
|
||||||
self.state = state;
|
self.state = state;
|
||||||
}
|
}
|
||||||
|
AppMsg::OpenPosts => self
|
||||||
|
.posts_page
|
||||||
|
.sender()
|
||||||
|
.emit(PostsPageInput::FetchPosts(ListingType::Subscribed, true)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue