diff --git a/voxygen/src/menu/main/ui/login.rs b/voxygen/src/menu/main/ui/login.rs index dc43361f0a..9a58989621 100644 --- a/voxygen/src/menu/main/ui/login.rs +++ b/voxygen/src/menu/main/ui/login.rs @@ -50,7 +50,6 @@ impl Screen { imgs: &Imgs, login_info: &LoginInfo, error: Option<&str>, - show_servers: bool, i18n: &Localization, button_style: style::button::Style, ) -> Element { diff --git a/voxygen/src/menu/main/ui/mod.rs b/voxygen/src/menu/main/ui/mod.rs index 7811f7f5d3..b218f0a89b 100644 --- a/voxygen/src/menu/main/ui/mod.rs +++ b/voxygen/src/menu/main/ui/mod.rs @@ -1,6 +1,7 @@ mod connecting; //mod disclaimer; mod login; +mod servers; use crate::{ i18n::{i18n_asset_key, Localization}, @@ -146,6 +147,9 @@ enum Screen { // Error to display in a box error: Option, }, + Servers { + screen: servers::Screen, + }, Connecting { screen: connecting::Screen, connection_state: ConnectionState, @@ -160,9 +164,10 @@ struct IcedState { // Voxygen version version: String, + servers: Vec, + selected_server_index: Option, login_info: LoginInfo, - show_servers: bool, time: f32, screen: Screen, @@ -171,6 +176,7 @@ struct IcedState { #[derive(Clone)] enum Message { Quit, + Back, ShowServers, #[cfg(feature = "singleplayer")] Singleplayer, @@ -178,6 +184,7 @@ enum Message { Username(String), Password(String), Server(String), + ServerChanged(usize), FocusPassword, CancelConnect, TrustPromptAdd, @@ -212,6 +219,14 @@ impl IcedState { }; //}; + let servers = settings.networking.servers.clone(); + let login_info = LoginInfo { + username: settings.networking.username.clone(), + password: String::new(), + server: settings.networking.default_server.clone(), + }; + let selected_server_index = servers.iter().position(|f| f == &login_info.server); + Self { fonts, imgs, @@ -219,13 +234,10 @@ impl IcedState { i18n, version, - login_info: LoginInfo { - username: settings.networking.username.clone(), - password: String::new(), - server: settings.networking.default_server.clone(), - }, + servers, + selected_server_index, + login_info, - show_servers: false, time: 0.0, screen, @@ -264,7 +276,14 @@ impl IcedState { &self.imgs, &self.login_info, error.as_deref(), - self.show_servers, + &self.i18n, + button_style, + ), + Screen::Servers { screen } => screen.view( + &self.fonts, + &self.imgs, + &self.servers, + self.selected_server_index, &self.i18n, button_style, ), @@ -295,7 +314,17 @@ impl IcedState { fn update(&mut self, message: Message, events: &mut Vec) { match message { Message::Quit => events.push(Event::Quit), - Message::ShowServers => self.show_servers = true, + Message::Back => { + self.screen = Screen::Login { + screen: login::Screen::new(), + error: None, + }; + }, + Message::ShowServers => { + self.screen = Screen::Servers { + screen: servers::Screen::new(), + }; + }, #[cfg(feature = "singleplayer")] Message::Singleplayer => { self.screen = Screen::Connecting { @@ -323,7 +352,14 @@ impl IcedState { }, Message::Username(new_value) => self.login_info.username = new_value, Message::Password(new_value) => self.login_info.password = new_value, - Message::Server(new_value) => self.login_info.server = new_value, + Message::Server(new_value) => { + self.selected_server_index = self.servers.iter().position(|f| f == &new_value); + self.login_info.server = new_value; + }, + Message::ServerChanged(new_value) => { + self.login_info.server = self.servers[new_value].clone(); + self.selected_server_index = Some(new_value); + }, Message::FocusPassword => { if let Screen::Login { screen, .. } = &mut self.screen { screen.banner.password = text_input::State::focused(); diff --git a/voxygen/src/menu/main/ui/servers.rs b/voxygen/src/menu/main/ui/servers.rs new file mode 100644 index 0000000000..817596a003 --- /dev/null +++ b/voxygen/src/menu/main/ui/servers.rs @@ -0,0 +1,98 @@ +use super::{IcedImgs as Imgs, Message}; +use crate::{ + i18n::Localization, + ui::{ + fonts::IcedFonts as Fonts, + ice::{ + component::neat_button, + style, + widget::{ + background_container::Padding, + compound_graphic::{CompoundGraphic, Graphic}, + BackgroundContainer, + }, + Element, + }, + }, +}; +use iced::{button, scrollable, Align, Button, Column, Container, Length, Scrollable, Text}; + +pub struct Screen { + back_button: button::State, + server_buttons: Vec, + servers_list: scrollable::State, +} + +impl Screen { + pub fn new() -> Self { + Self { + back_button: Default::default(), + server_buttons: vec![], + servers_list: Default::default(), + } + } + + pub(super) fn view( + &mut self, + fonts: &Fonts, + imgs: &Imgs, + servers: &Vec, + selected_server_index: Option, + i18n: &Localization, + button_style: style::button::Style, + ) -> Element { + let button = neat_button( + &mut self.back_button, + i18n.get("common.back"), + 0.77_f32, + button_style, + Some(Message::Back), + ); + + let button = Container::new(Container::new(button).max_width(200)) + .width(Length::Fill) + .align_x(Align::Center); + + let mut list = Scrollable::new(&mut self.servers_list) + .align_items(Align::Start) + .width(Length::Fill) + .height(Length::Fill) + .spacing(10); + + if self.server_buttons.len() != servers.len() { + self.server_buttons = vec![Default::default(); servers.len()]; + } + + for (i, state) in self.server_buttons.iter_mut().enumerate() { + let server = servers.get(i).unwrap(); + let text = format!( + "{}{}", + if i == selected_server_index.unwrap_or(std::usize::MAX) { + "-> " + } else { + " " + }, + server + ); + let button = Button::new(state, Text::new(text).size(fonts.cyri.scale(25))) + .on_press(Message::ServerChanged(i)); + list = list.push(button); + } + + Container::new( + BackgroundContainer::new( + CompoundGraphic::padded_image(imgs.info_frame, [500, 300], [0; 4]), + Column::with_children(vec![list.into(), button.into()]) + .width(Length::Fill) + .height(Length::Fill) + .spacing(10) + .padding(20), + ) + .max_width(500), + ) + .width(Length::Fill) + .align_x(Align::Center) + .padding(80) + .into() + } +}