List federated instances in instance selector (#8)

Co-authored-by: Bnyro <bnyro@tutanota.com>
This commit is contained in:
Lorenzo B Gomez 2023-06-30 09:57:18 -05:00 committed by GitHub
parent 38c0c4fd27
commit daa539031f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 134 additions and 22 deletions

29
src/api/instances.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::settings;
use lemmy_api_common::{
lemmy_db_schema::source::instance::Instance,
site::{GetFederatedInstances, GetFederatedInstancesResponse},
};
pub fn fetch_instances() -> std::result::Result<Vec<Instance>, reqwest::Error> {
// TODO: Update code to use the Instance views from lemmy 0.18.0
let params = GetFederatedInstances {
auth: settings::get_current_account().jwt,
};
// we fetch the instances from the official instance because the instance is likely unset on first startup
let instances = super::CLIENT
.get("https://lemmy.ml/api/v3/federated_instances".to_owned())
.query(&params)
.send()?
.json::<GetFederatedInstancesResponse>()?;
match instances.federated_instances {
Some(instances) => Ok(instances
.linked
.iter()
.filter(|instance| instance.software == Some("lemmy".to_owned()))
.map(|instance| instance.clone())
.collect::<Vec<Instance>>()),
None => Ok(vec![]),
}
}

View File

@ -6,13 +6,14 @@ pub mod auth;
pub mod comment; pub mod comment;
pub mod communities; pub mod communities;
pub mod community; pub mod community;
pub mod image;
pub mod moderation; pub mod moderation;
pub mod post; pub mod post;
pub mod posts; pub mod posts;
pub mod private_message; pub mod private_message;
pub mod search; pub mod search;
pub mod site; pub mod site;
pub mod image;
pub mod instances;
pub mod user; pub mod user;
static API_VERSION: &str = "v3"; static API_VERSION: &str = "v3";

View File

@ -0,0 +1,87 @@
use gtk::prelude::*;
use lemmy_api_common::lemmy_db_schema::source::instance::Instance;
use relm4::prelude::*;
#[derive(Debug)]
pub struct InstanceRow {
instance: Instance,
}
#[derive(Debug)]
pub enum InstanceRowMsg {
OpenInstance,
}
#[relm4::factory(pub)]
impl FactoryComponent for InstanceRow {
type Init = Instance;
type Input = InstanceRowMsg;
type Output = crate::AppMsg;
type CommandOutput = ();
type Widgets = PostViewWidgets;
type ParentInput = crate::AppMsg;
type ParentWidget = gtk::Box;
view! {
root = gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,
set_margin_end: 10,
set_margin_start: 10,
set_vexpand: false,
add_controller = gtk::GestureClick {
connect_pressed[sender] => move |_, _, _, _| {
sender.input(InstanceRowMsg::OpenInstance);
}
},
gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
set_spacing: 10,
gtk::Label {
set_label: &self.instance.domain
},
gtk::Box {
set_hexpand: true,
},
},
gtk::Separator {}
}
}
fn forward_to_parent(output: Self::Output) -> Option<Self::ParentInput> {
Some(output)
}
fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender<Self>) -> Self {
Self { instance: value }
}
fn init_widgets(
&mut self,
_index: &Self::Index,
root: &Self::Root,
_returned_widget: &<Self::ParentWidget as relm4::factory::FactoryView>::ReturnedWidget,
sender: FactorySender<Self>,
) -> Self::Widgets {
let widgets = view_output!();
widgets
}
fn update(&mut self, message: Self::Input, sender: FactorySender<Self>) {
match message {
InstanceRowMsg::OpenInstance => {
let instance_address = format!("https://{}", self.instance.domain);
sender.output(crate::AppMsg::DoneChoosingInstance(
instance_address.clone(),
))
}
}
}
}

View File

@ -2,6 +2,8 @@ pub mod comment_row;
pub mod community_page; pub mod community_page;
pub mod community_row; pub mod community_row;
pub mod inbox_page; pub mod inbox_page;
pub mod instance_row;
pub mod instances_page;
pub mod mention_row; pub mod mention_row;
pub mod post_page; pub mod post_page;
pub mod post_row; pub mod post_row;

View File

@ -10,6 +10,7 @@ use components::{
community_page::{self, CommunityPage}, community_page::{self, CommunityPage},
community_row::CommunityRow, community_row::CommunityRow,
inbox_page::{InboxInput, InboxPage}, inbox_page::{InboxInput, InboxPage},
instances_page::{InstancePageInput, InstancesPage},
post_page::{self, PostPage}, post_page::{self, PostPage},
post_row::PostRow, post_row::PostRow,
profile_page::{self, ProfilePage}, profile_page::{self, ProfilePage},
@ -55,6 +56,7 @@ struct App {
back_queue: Vec<AppMsg>, back_queue: Vec<AppMsg>,
posts: FactoryVecDeque<PostRow>, posts: FactoryVecDeque<PostRow>,
communities: FactoryVecDeque<CommunityRow>, communities: FactoryVecDeque<CommunityRow>,
instances_page: Controller<InstancesPage>,
profile_page: Controller<ProfilePage>, profile_page: Controller<ProfilePage>,
community_page: Controller<CommunityPage>, community_page: Controller<CommunityPage>,
post_page: Controller<PostPage>, post_page: Controller<PostPage>,
@ -179,27 +181,8 @@ impl SimpleComponent for App {
}, },
}, },
AppState::ChooseInstance => gtk::Box { AppState::ChooseInstance => gtk::Box {
set_hexpand: true, #[local_ref]
set_orientation: gtk::Orientation::Vertical, instances_page -> gtk::Box {}
set_spacing: 12,
set_margin_all: 20,
set_valign: gtk::Align::Center,
set_halign: gtk::Align::Center,
gtk::Label {
set_text: "Please enter the URL of a valid lemmy instance",
},
#[name(instance_url)]
gtk::Entry {
set_tooltip_text: Some("Instance"),
},
gtk::Button {
set_label: "Done",
connect_clicked[sender, instance_url] => move |_| {
let text = instance_url.text().as_str().to_string();
instance_url.set_text("");
sender.input(AppMsg::DoneChoosingInstance(text));
},
}
}, },
AppState::Login => gtk::Box { AppState::Login => gtk::Box {
set_hexpand: true, set_hexpand: true,
@ -287,6 +270,7 @@ impl SimpleComponent for App {
} }
} }
} }
AppState::Person => { AppState::Person => {
gtk::Box { gtk::Box {
#[local_ref] #[local_ref]
@ -357,6 +341,9 @@ 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 communities = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender());
let instances_page = InstancesPage::builder()
.launch(())
.forward(sender.input_sender(), |msg| msg);
let profile_page = ProfilePage::builder() let profile_page = ProfilePage::builder()
.launch(default_person()) .launch(default_person())
.forward(sender.input_sender(), |msg| msg); .forward(sender.input_sender(), |msg| msg);
@ -380,6 +367,7 @@ impl SimpleComponent for App {
logged_in, logged_in,
posts, posts,
communities, communities,
instances_page,
profile_page, profile_page,
community_page, community_page,
post_page, post_page,
@ -401,6 +389,7 @@ 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 communities_box = model.communities.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();
@ -486,6 +475,9 @@ impl SimpleComponent for App {
} }
AppMsg::ChooseInstance => { AppMsg::ChooseInstance => {
self.state = AppState::ChooseInstance; self.state = AppState::ChooseInstance;
self.instances_page
.sender()
.emit(InstancePageInput::FetchInstances);
} }
AppMsg::StartFetchPosts(type_, remove_previous) => { AppMsg::StartFetchPosts(type_, remove_previous) => {
self.current_posts_type = type_; self.current_posts_type = type_;
@ -536,6 +528,7 @@ impl SimpleComponent for App {
sender.input(message); sender.input(message);
}); });
} }
AppMsg::DoneFetchCommunities(communities) => { AppMsg::DoneFetchCommunities(communities) => {
self.state = AppState::Communities; self.state = AppState::Communities;
if self.current_communities_page == 1 { if self.current_communities_page == 1 {