diff --git a/Cargo.lock b/Cargo.lock index 848c6289..22b26894 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4696,9 +4696,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "veloren-serverbrowser-api" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3974631142a04d38d765a52cd625d01b2b5632a8e50e9b22509f1c6f14ab01f8" +checksum = "b25e966b27a95a55d4903c4646dc55ffdf59f23bef7e27978b97fa92fd64ca27" dependencies = [ "country-parser", "serde", diff --git a/client/Cargo.toml b/client/Cargo.toml index b885465b..2f78337d 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -28,7 +28,7 @@ maintenance = { status = "actively-developed" } bundled = ["openssl-sys"] [dependencies] -veloren-serverbrowser-api = "0.2.0" +veloren-serverbrowser-api = "0.3.1" # Cli clap = { version = "3.1.18", features = ["cargo", "derive"] } diff --git a/client/src/gui/components/server_browser_panel.rs b/client/src/gui/components/server_browser_panel.rs index f04f1ca9..9c76cf2b 100644 --- a/client/src/gui/components/server_browser_panel.rs +++ b/client/src/gui/components/server_browser_panel.rs @@ -10,9 +10,10 @@ use crate::{ components::GamePanelMessage, style::{ ChangelogHeaderStyle, ColumnHeadingButtonStyle, ColumnHeadingContainerStyle, - DarkContainerStyle, GitlabServerBrowserButtonStyle, RuleStyle, + DarkContainerStyle, DiscordBrowserButtonStyle, ExtraBrowserStyle, + GitlabServerBrowserButtonStyle, RedditBrowserButtonStyle, RuleStyle, ServerListEntryButtonStyle, TooltipStyle, WarningContainerStyle, - BRIGHT_ORANGE, DARK_WHITE, TOMATO_RED, + YoutubeBrowserButtonStyle, BRIGHT_ORANGE, DARK_WHITE, TOMATO_RED, }, views::default::{DefaultViewMessage, Interaction}, }, @@ -33,7 +34,8 @@ use iced::{ use iced_native::{image::Handle, widget::tooltip::Position, Command}; use std::{cmp::min, sync::Arc}; use tracing::debug; -use veloren_serverbrowser_api::GameServer; +use url::Url; +use veloren_serverbrowser_api::{FieldContent, GameServer}; #[derive(Debug, Clone)] pub struct ServerBrowserEntry { @@ -363,6 +365,22 @@ impl ServerBrowserPanelComponent { .selected_index .and_then(|x| self.servers.get(x).map(|y| &y.server)); + let discord_origin = url::Origin::Tuple( + "https".to_string(), + url::Host::Domain(String::from("discord.gg")), + 443, + ); + let reddit_origin = url::Origin::Tuple( + "https".to_string(), + url::Host::Domain(String::from("reddit.com")), + 443, + ); + let youtube_origin = url::Origin::Tuple( + "https".to_string(), + url::Host::Domain(String::from("youtube.com")), + 443, + ); + if let Some(server) = selected_server { col = col .push( @@ -371,35 +389,100 @@ impl ServerBrowserPanelComponent { .padding(Padding::from([5, 0])), ) .push( - container(scrollable( - column().push( - row().push( - column() - .spacing(5) - .push( + container(scrollable(column().push(row().push({ + let mut fields = + server.extra.clone().into_iter().collect::>(); + fields.sort_by(|a, b| a.0.cmp(&b.0)); + let mut extras = row().spacing(10); + for (id, field) in fields { + // TODO: Recognise common IDs, give them a custom icon + match field.content { + FieldContent::Text(c) => { + let container = match id.as_str() { + "email" => container( + text(format!("Email: {}", c)).size(14), + ) + .padding(Padding::from([2, 10, 2, 10])) + .style(ExtraBrowserStyle), + _ => container( + text(format!("{}: {}", field.name, c)) + .size(14), + ) + .padding(Padding::from([2, 10, 2, 10])) + .style(ExtraBrowserStyle), + }; + extras = extras.push(container); + }, + FieldContent::Url(c) => { + let mut button = button( row() - .spacing(10) .push( - text(&server.name) - .font(NOTO_SANS_UNIFIED_FONT), + text(field.name) + .color(Color::WHITE) + .size(14), ) - .push( - text(&server.address) - .font(NOTO_SANS_UNIFIED_FONT) - .color(BRIGHT_ORANGE), - ), + .push(image(Handle::from_memory( + UP_RIGHT_ARROW_ICON.to_vec(), + ))) + .spacing(5) + .align_items(Alignment::Center), ) + .on_press(DefaultViewMessage::Interaction( + Interaction::OpenURL(c.clone()), + )) + .padding(Padding::from([2, 10, 2, 10])) + .height(Length::Units(20)); + button = match id.as_str() { + "discord" + if Url::parse(&c) + .map(|u| u.origin() == discord_origin) + .unwrap_or(false) => + { + button.style(DiscordBrowserButtonStyle) + }, + "reddit" + if Url::parse(&c) + .map(|u| u.origin() == reddit_origin) + .unwrap_or(false) => + { + button.style(RedditBrowserButtonStyle) + }, + "youtube" + if Url::parse(&c) + .map(|u| u.origin() == youtube_origin) + .unwrap_or(false) => + { + button.style(YoutubeBrowserButtonStyle) + }, + _ => button.style(ExtraBrowserStyle), + }; + extras = extras.push(button); + }, + _ => {}, + }; + } + column() + .spacing(5) + .push( + row() + .spacing(10) .push( - text("Description: ") + text(&server.name) .font(NOTO_SANS_UNIFIED_FONT), ) .push( - text(&server.description) - .font(NOTO_SANS_UNIFIED_FONT), + text(&display_gameserver_address(server)) + .font(NOTO_SANS_UNIFIED_FONT) + .color(BRIGHT_ORANGE), ), - ), - ), - )) + ) + .push(text("Description: ").font(NOTO_SANS_UNIFIED_FONT)) + .push( + text(&server.description) + .font(NOTO_SANS_UNIFIED_FONT), + ) + .push(extras) + })))) .height(Length::Units(128)), ); } @@ -503,13 +586,9 @@ impl ServerBrowserPanelComponent { ServerBrowserPanelMessage::SelectServerEntry(index) => { self.selected_index = index; let selected_server = index.and_then(|index| { - self.servers.get(index).map(|x| { - if x.server.port == net::DEFAULT_GAME_PORT { - x.server.address.clone() - } else { - format!("{}:{}", x.server.address, x.server.port) - } - }) + self.servers + .get(index) + .map(|x| display_gameserver_address(&x.server)) }); Some(Command::perform(async {}, move |()| { @@ -552,6 +631,14 @@ impl ServerBrowserPanelComponent { } } +fn display_gameserver_address(gameserver: &GameServer) -> String { + if gameserver.port == net::DEFAULT_GAME_PORT { + gameserver.address.clone() + } else { + format!("{}:{}", gameserver.address, gameserver.port) + } +} + #[derive(Clone, Debug)] pub enum ServerSortOrder { Default, diff --git a/client/src/gui/style.rs b/client/src/gui/style.rs index 55eb6555..5c1fa5a8 100644 --- a/client/src/gui/style.rs +++ b/client/src/gui/style.rs @@ -6,6 +6,14 @@ use iced::{ Background, Color, Vector, }; +const fn rgb8(red: u8, green: u8, blue: u8) -> Color { + Color::from_rgb( + red as f32 / 255.0, + green as f32 / 255.0, + blue as f32 / 255.0, + ) +} + // Colors pub const LIGHT_GREY: Color = Color::from_rgb(0.93, 0.93, 0.93); pub const MEDIUM_GREY: Color = Color::from_rgb(0.7, 0.7, 0.7); @@ -17,6 +25,9 @@ const TRANSPARENT_WHITE: Color = Color::from_rgba(1.0, 1.0, 1.0, 0.1); pub const DARK_WHITE: Color = Color::from_rgb(0.9, 0.9, 0.9); const BACKGROUND_BLUE: Color = Color::from_rgb(0.14, 0.21, 0.41); const LIME_GREEN: Color = Color::from_rgb(0.41, 0.64, 0.26); +const DISCORD_BLURPLE: Color = rgb8(88, 101, 242); +const REDDIT_ORANGE: Color = rgb8(255, 69, 0); +const YOUTUBE_RED: Color = rgb8(255, 0, 0); const CORNFLOWER_BLUE: Color = Color::from_rgb(0.19, 0.4, 0.85); const BLOG_POST_BACKGROUND_BLUE: Color = Color::from_rgb(0.24, 0.33, 0.58); pub const LILAC: Color = Color::from_rgb(0.62, 0.66, 0.79); @@ -246,6 +257,59 @@ impl button::StyleSheet for GitlabChangelogButtonStyle { } } +pub struct DiscordBrowserButtonStyle; +impl button::StyleSheet for DiscordBrowserButtonStyle { + fn active(&self) -> Style { + Style { + background: Some(Background::Color(DISCORD_BLURPLE)), + border_radius: 25.0, + ..button::Style::default() + } + } +} + +pub struct RedditBrowserButtonStyle; +impl button::StyleSheet for RedditBrowserButtonStyle { + fn active(&self) -> Style { + Style { + background: Some(Background::Color(REDDIT_ORANGE)), + border_radius: 25.0, + ..button::Style::default() + } + } +} + +pub struct YoutubeBrowserButtonStyle; +impl button::StyleSheet for YoutubeBrowserButtonStyle { + fn active(&self) -> Style { + Style { + background: Some(Background::Color(YOUTUBE_RED)), + border_radius: 25.0, + ..button::Style::default() + } + } +} + +pub struct ExtraBrowserStyle; +impl button::StyleSheet for ExtraBrowserStyle { + fn active(&self) -> Style { + Style { + background: Some(Background::Color(LIME_GREEN)), + border_radius: 25.0, + ..button::Style::default() + } + } +} +impl container::StyleSheet for ExtraBrowserStyle { + fn style(&self) -> container::Style { + container::Style { + background: Some(Background::Color(LIME_GREEN)), + border_radius: 25.0, + ..container::Style::default() + } + } +} + pub struct GitlabServerBrowserButtonStyle; impl button::StyleSheet for GitlabServerBrowserButtonStyle { fn active(&self) -> Style { diff --git a/client/src/main.rs b/client/src/main.rs index 93170656..6aee22d8 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,5 +1,6 @@ #![feature(async_closure)] #![feature(let_chains)] +#![feature(const_fn_floating_point_arithmetic)] mod assets; mod channels; mod cli;