mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add styling for Container, implement auth trust prompt, misc additions
This commit is contained in:
parent
20a46eb526
commit
73982637b2
@ -65,6 +65,7 @@
|
||||
"common.back": "Back",
|
||||
"common.create": "Create",
|
||||
"common.okay": "Okay",
|
||||
"common.add": "Add",
|
||||
"common.accept": "Accept",
|
||||
"common.decline": "Decline",
|
||||
"common.disclaimer": "Disclaimer",
|
||||
|
@ -1,20 +1,19 @@
|
||||
use super::{IcedImgs as Imgs, Message};
|
||||
use super::{ConnectionState, IcedImgs as Imgs, Message};
|
||||
use crate::{
|
||||
i18n::Localization,
|
||||
ui::{
|
||||
fonts::IcedFonts as Fonts,
|
||||
ice::{
|
||||
component::neat_button,
|
||||
widget::{image, BackgroundContainer, Image},
|
||||
ButtonStyle, Element,
|
||||
},
|
||||
ice::{component::neat_button, style, widget::image, Element},
|
||||
},
|
||||
};
|
||||
use iced::{button, Color, Column, Container, HorizontalAlignment, Length, Row, Space, Text};
|
||||
use iced::{
|
||||
button, Align, Color, Column, Container, HorizontalAlignment, Length, Row, Space, Text,
|
||||
};
|
||||
|
||||
/// Connecting screen for the main menu
|
||||
pub struct Screen {
|
||||
cancel_button: button::State,
|
||||
add_button: button::State,
|
||||
}
|
||||
|
||||
// TODO: move to super and unify with identical login consts
|
||||
@ -25,6 +24,7 @@ impl Screen {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
cancel_button: Default::default(),
|
||||
add_button: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,13 +34,13 @@ impl Screen {
|
||||
imgs: &Imgs,
|
||||
bg_img: image::Handle,
|
||||
start: &std::time::Instant,
|
||||
status_text: &str,
|
||||
connection_state: &ConnectionState,
|
||||
version: &str,
|
||||
time: f32,
|
||||
i18n: &Localization,
|
||||
) -> Element<Message> {
|
||||
let fade_msg = (time * 2.0).sin() * 0.5 + 0.51;
|
||||
let button_style = ButtonStyle::new(imgs.button)
|
||||
let button_style = style::button::Style::new(imgs.button)
|
||||
.hover_image(imgs.button_hover)
|
||||
.press_image(imgs.button_press)
|
||||
.text_color(TEXT_COLOR)
|
||||
@ -49,10 +49,12 @@ impl Screen {
|
||||
let version = Text::new(version)
|
||||
.size(fonts.cyri.scale(15)) // move version text size to const
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.height(if matches!(connection_state, ConnectionState::InProgress {..}){Length::Fill}else{Length::Shrink})
|
||||
.horizontal_alignment(HorizontalAlignment::Right);
|
||||
|
||||
let status = Text::new(status_text)
|
||||
let (middle, bottom) = match connection_state {
|
||||
ConnectionState::InProgress { status } => {
|
||||
let status = Text::new(status)
|
||||
.size(fonts.alkhemi.scale(80))
|
||||
.font(fonts.alkhemi.id)
|
||||
.color(Color::from_rgba(1.0, 1.0, 1.0, fade_msg))
|
||||
@ -77,13 +79,69 @@ impl Screen {
|
||||
.center_x()
|
||||
.padding(3);
|
||||
|
||||
let content = Column::with_children(vec![version.into(), status.into(), cancel.into()])
|
||||
(status.into(), cancel.into())
|
||||
},
|
||||
ConnectionState::AuthTrustPrompt { msg, .. } => {
|
||||
let text = Text::new(msg).size(fonts.cyri.scale(25));
|
||||
|
||||
let cancel = neat_button(
|
||||
&mut self.cancel_button,
|
||||
i18n.get("common.cancel"),
|
||||
0.7,
|
||||
button_style,
|
||||
Some(Message::TrustPromptCancel),
|
||||
);
|
||||
let add = neat_button(
|
||||
&mut self.add_button,
|
||||
i18n.get("common.add"),
|
||||
0.7,
|
||||
button_style,
|
||||
Some(Message::TrustPromptAdd),
|
||||
);
|
||||
|
||||
let content = Column::with_children(vec![
|
||||
text.into(),
|
||||
Container::new(
|
||||
Row::with_children(vec![cancel.into(), add.into()])
|
||||
.spacing(20)
|
||||
.height(Length::Units(25)),
|
||||
)
|
||||
.align_x(Align::End)
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
])
|
||||
.spacing(4)
|
||||
.max_width(500)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill);
|
||||
|
||||
let prompt_window = Container::new(content)
|
||||
// TODO: add borders
|
||||
.style(style::container::Style::Color((10, 10, 0, 255).into()))
|
||||
.padding(10);
|
||||
|
||||
let container = Container::new(prompt_window)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.center_x()
|
||||
.center_y();
|
||||
|
||||
(
|
||||
container.into(),
|
||||
Space::new(Length::Fill, Length::Units(fonts.cyri.scale(15))).into(),
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
let content = Column::with_children(vec![version.into(), middle, bottom])
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(3);
|
||||
|
||||
// Note: could replace this with styling on iced's container since we aren't
|
||||
// using fixed aspect ratio
|
||||
BackgroundContainer::new(Image::new(bg_img), content).into()
|
||||
Container::new(content)
|
||||
.style(style::container::Style::image(bg_img))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ use crate::{
|
||||
fonts::IcedFonts as Fonts,
|
||||
ice::{
|
||||
component::neat_button,
|
||||
style,
|
||||
widget::{
|
||||
compound_graphic::{CompoundGraphic, Graphic},
|
||||
BackgroundContainer, Image, Padding,
|
||||
},
|
||||
ButtonStyle, Element,
|
||||
Element,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -52,11 +53,12 @@ impl Screen {
|
||||
imgs: &Imgs,
|
||||
login_info: &LoginInfo,
|
||||
info: &Info,
|
||||
error: Option<&str>,
|
||||
version: &str,
|
||||
show_servers: bool,
|
||||
i18n: &Localization,
|
||||
) -> Element<Message> {
|
||||
let button_style = ButtonStyle::new(imgs.button)
|
||||
let button_style = style::button::Style::new(imgs.button)
|
||||
.hover_image(imgs.button_hover)
|
||||
.press_image(imgs.button_press)
|
||||
.text_color(TEXT_COLOR)
|
||||
@ -146,7 +148,9 @@ impl Screen {
|
||||
.spacing(10)
|
||||
.padding(3);
|
||||
|
||||
BackgroundContainer::new(Image::new(imgs.bg), content).into()
|
||||
Container::new(content)
|
||||
.style(style::container::Style::image(imgs.bg))
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +183,7 @@ impl Banner {
|
||||
imgs: &Imgs,
|
||||
login_info: &LoginInfo,
|
||||
i18n: &Localization,
|
||||
button_style: ButtonStyle,
|
||||
button_style: style::button::Style,
|
||||
) -> Element<Message> {
|
||||
let input_text_size = fonts.cyri.scale(INPUT_TEXT_SIZE);
|
||||
|
||||
|
@ -119,15 +119,35 @@ enum Info {
|
||||
Intro,
|
||||
}
|
||||
|
||||
enum ConnectionState {
|
||||
InProgress {
|
||||
status: String,
|
||||
},
|
||||
AuthTrustPrompt {
|
||||
auth_server: String,
|
||||
msg: String,
|
||||
// To remember when we switch back
|
||||
status: String,
|
||||
},
|
||||
}
|
||||
impl ConnectionState {
|
||||
fn take_status_string(&mut self) -> String {
|
||||
std::mem::take(match self {
|
||||
Self::InProgress { status } => status,
|
||||
Self::AuthTrustPrompt { status, .. } => status,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enum Screen {
|
||||
Login {
|
||||
screen: login::Screen,
|
||||
// Error to display in a box
|
||||
error: Option<String>,
|
||||
},
|
||||
Connecting {
|
||||
screen: connecting::Screen,
|
||||
// TODO: why instant?
|
||||
start: std::time::Instant,
|
||||
status_text: String,
|
||||
connection_state: ConnectionState,
|
||||
},
|
||||
}
|
||||
|
||||
@ -142,8 +162,6 @@ struct IcedState {
|
||||
|
||||
login_info: LoginInfo,
|
||||
|
||||
// TODO: not sure if this should be used for connecting
|
||||
popup: Option<PopupData>,
|
||||
show_servers: bool,
|
||||
info: Info,
|
||||
time: f32,
|
||||
@ -163,6 +181,10 @@ enum Message {
|
||||
Server(String),
|
||||
FocusPassword,
|
||||
CancelConnect,
|
||||
TrustPromptAdd,
|
||||
TrustPromptCancel,
|
||||
CloseError,
|
||||
CloseDisclaimer,
|
||||
}
|
||||
|
||||
impl IcedState {
|
||||
@ -198,13 +220,13 @@ impl IcedState {
|
||||
server: String::new(),
|
||||
},
|
||||
|
||||
popup: None,
|
||||
show_servers: false,
|
||||
info,
|
||||
time: 0.0,
|
||||
|
||||
screen: Screen::Login {
|
||||
screen: login::Screen::new(),
|
||||
error: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -212,12 +234,14 @@ impl IcedState {
|
||||
fn view(&mut self, dt: f32) -> Element<Message> {
|
||||
self.time = self.time + dt;
|
||||
|
||||
// TODO: make disclaimer it's own screen?
|
||||
match &mut self.screen {
|
||||
Screen::Login { screen } => screen.view(
|
||||
Screen::Login { screen, error } => screen.view(
|
||||
&self.fonts,
|
||||
&self.imgs,
|
||||
&self.login_info,
|
||||
&self.info,
|
||||
error.as_deref(),
|
||||
&self.version,
|
||||
self.show_servers,
|
||||
&self.i18n,
|
||||
@ -225,13 +249,13 @@ impl IcedState {
|
||||
Screen::Connecting {
|
||||
screen,
|
||||
start,
|
||||
status_text,
|
||||
connection_state,
|
||||
} => screen.view(
|
||||
&self.fonts,
|
||||
&self.imgs,
|
||||
self.bg_img,
|
||||
&start,
|
||||
&status_text,
|
||||
&connection_state,
|
||||
&self.version,
|
||||
self.time,
|
||||
&self.i18n,
|
||||
@ -248,7 +272,9 @@ impl IcedState {
|
||||
self.screen = Screen::Connecting {
|
||||
screen: connecting::Screen::new(),
|
||||
start: std::time::Instant::now(),
|
||||
status_text: [self.i18n.get("main.creating_world"), "..."].concat(),
|
||||
connection_state: ConnectionState::InProgress {
|
||||
status: [self.i18n.get("main.creating_world"), "..."].concat(),
|
||||
},
|
||||
};
|
||||
|
||||
events.push(Event::StartSingleplayer);
|
||||
@ -257,7 +283,9 @@ impl IcedState {
|
||||
self.screen = Screen::Connecting {
|
||||
screen: connecting::Screen::new(),
|
||||
start: std::time::Instant::now(),
|
||||
status_text: [self.i18n.get("main.connecting"), "..."].concat(),
|
||||
connection_state: ConnectionState::InProgress {
|
||||
status: [self.i18n.get("main.connecting"), "..."].concat(),
|
||||
},
|
||||
};
|
||||
|
||||
events.push(Event::LoginAttempt {
|
||||
@ -279,6 +307,34 @@ impl IcedState {
|
||||
self.cancel_connection();
|
||||
events.push(Event::CancelLoginAttempt);
|
||||
},
|
||||
msg @ Message::TrustPromptAdd | msg @ Message::TrustPromptCancel => {
|
||||
if let Screen::Connecting {
|
||||
connection_state, ..
|
||||
} = &mut self.screen
|
||||
{
|
||||
if let ConnectionState::AuthTrustPrompt {
|
||||
auth_server,
|
||||
status,
|
||||
..
|
||||
} = connection_state
|
||||
{
|
||||
let auth_server = std::mem::take(auth_server);
|
||||
let status = std::mem::take(status);
|
||||
let added = matches!(msg, Message::TrustPromptAdd);
|
||||
|
||||
*connection_state = ConnectionState::InProgress { status };
|
||||
events.push(Event::AuthServerTrust(auth_server, added));
|
||||
}
|
||||
}
|
||||
},
|
||||
Message::CloseError => {
|
||||
if let Screen::Login { error, .. } = &mut self.screen {
|
||||
*error = None;
|
||||
}
|
||||
},
|
||||
Message::CloseDisclaimer => {
|
||||
events.push(Event::DisclaimerClosed);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,6 +342,37 @@ impl IcedState {
|
||||
if matches!(&self.screen, Screen::Connecting {..}) {
|
||||
self.screen = Screen::Login {
|
||||
screen: login::Screen::new(),
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn auth_trust_prompt(&mut self, auth_server: String) {
|
||||
if let Screen::Connecting {
|
||||
connection_state, ..
|
||||
} = &mut self.screen
|
||||
{
|
||||
let msg = format!(
|
||||
"Warning: The server you are trying to connect to has provided this \
|
||||
authentication server address:\n\n{}\n\nbut it is not in your list of trusted \
|
||||
authentication servers.\n\nMake sure that you trust this site and owner to not \
|
||||
try and bruteforce your password!",
|
||||
&auth_server
|
||||
);
|
||||
|
||||
*connection_state = ConnectionState::AuthTrustPrompt {
|
||||
auth_server,
|
||||
msg,
|
||||
status: connection_state.take_status_string(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn connection_error(&mut self, error: String) {
|
||||
if matches!(&self.screen, Screen::Connecting {..}) {
|
||||
self.screen = Screen::Login {
|
||||
screen: login::Screen::new(),
|
||||
error: Some(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1061,6 +1148,7 @@ impl<'a> MainMenuUi {
|
||||
}
|
||||
|
||||
pub fn auth_trust_prompt(&mut self, auth_server: String) {
|
||||
self.ice_state.auth_trust_prompt(auth_server.clone());
|
||||
self.popup = Some(PopupData {
|
||||
msg: format!(
|
||||
"Warning: The server you are trying to connect to has provided this \
|
||||
@ -1074,6 +1162,8 @@ impl<'a> MainMenuUi {
|
||||
}
|
||||
|
||||
pub fn show_info(&mut self, msg: String) {
|
||||
self.ice_state.connection_error(msg.clone());
|
||||
|
||||
self.popup = Some(PopupData {
|
||||
msg,
|
||||
popup_type: PopupType::Error,
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::ui::ice as ui;
|
||||
use iced::{button::State, Button, Element, Length};
|
||||
use ui::{
|
||||
style::button::Style,
|
||||
widget::{AspectRatioContainer, FillText},
|
||||
ButtonStyle,
|
||||
};
|
||||
|
||||
pub fn neat_button<M: Clone + 'static>(
|
||||
state: &mut State,
|
||||
label: impl Into<String>,
|
||||
fill_fraction: f32,
|
||||
button_style: ButtonStyle,
|
||||
button_style: Style,
|
||||
message: Option<M>,
|
||||
) -> Element<M, ui::IcedRenderer> {
|
||||
let button = Button::new(state, FillText::new(label).fill_fraction(fill_fraction))
|
||||
|
@ -9,7 +9,7 @@ mod winit_conversion;
|
||||
pub use cache::{Font, FontId, RawFont};
|
||||
pub use graphic::{Id, Rotation};
|
||||
pub use iced::Event;
|
||||
pub use renderer::{ButtonStyle, IcedRenderer};
|
||||
pub use renderer::{style, IcedRenderer};
|
||||
pub use winit_conversion::window_event;
|
||||
|
||||
use super::{
|
||||
|
@ -1,10 +1,9 @@
|
||||
mod defaults;
|
||||
mod primitive;
|
||||
mod style;
|
||||
pub mod style;
|
||||
mod widget;
|
||||
|
||||
pub use defaults::Defaults;
|
||||
pub use style::ButtonStyle;
|
||||
|
||||
pub(self) use primitive::Primitive;
|
||||
|
||||
|
18
voxygen/src/ui/ice/renderer/style/container.rs
Normal file
18
voxygen/src/ui/ice/renderer/style/container.rs
Normal file
@ -0,0 +1,18 @@
|
||||
use super::super::super::widget::image;
|
||||
use vek::Rgba;
|
||||
|
||||
/// Background of the container
|
||||
pub enum Style {
|
||||
Image(image::Handle, Rgba<u8>),
|
||||
Color(Rgba<u8>),
|
||||
None,
|
||||
}
|
||||
|
||||
impl Style {
|
||||
/// Shorthand for common case where the color of the image is not modified
|
||||
pub fn image(image: image::Handle) -> Self { Self::Image(image, Rgba::broadcast(255)) }
|
||||
}
|
||||
|
||||
impl Default for Style {
|
||||
fn default() -> Self { Self::None }
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
mod button;
|
||||
|
||||
pub use button::Style as ButtonStyle;
|
||||
pub mod button;
|
||||
pub mod container;
|
||||
|
@ -1,10 +1,10 @@
|
||||
use super::super::{super::Rotation, Defaults, IcedRenderer, Primitive};
|
||||
use super::super::{super::Rotation, style, Defaults, IcedRenderer, Primitive};
|
||||
use iced::{button, mouse, Element, Layout, Point, Rectangle};
|
||||
use vek::Rgba;
|
||||
|
||||
impl button::Renderer for IcedRenderer {
|
||||
// TODO: what if this gets large enough to not be copied around?
|
||||
type Style = super::super::style::ButtonStyle;
|
||||
type Style = style::button::Style;
|
||||
|
||||
const DEFAULT_PADDING: u16 = 0;
|
||||
|
||||
|
@ -1,23 +1,47 @@
|
||||
use super::super::IcedRenderer;
|
||||
use super::super::{super::Rotation, style, IcedRenderer, Primitive};
|
||||
use common::util::srgba_to_linear;
|
||||
use iced::{container, Element, Layout, Point, Rectangle};
|
||||
|
||||
impl container::Renderer for IcedRenderer {
|
||||
type Style = ();
|
||||
type Style = style::container::Style;
|
||||
|
||||
fn draw<M>(
|
||||
&mut self,
|
||||
defaults: &Self::Defaults,
|
||||
_bounds: Rectangle,
|
||||
bounds: Rectangle,
|
||||
cursor_position: Point,
|
||||
_style_sheet: &Self::Style,
|
||||
style_sheet: &Self::Style,
|
||||
content: &Element<'_, M, Self>,
|
||||
content_layout: Layout<'_>,
|
||||
) -> Self::Output {
|
||||
let (content, mouse_interaction) =
|
||||
content.draw(self, defaults, content_layout, cursor_position);
|
||||
|
||||
// We may have more stuff here if styles are used
|
||||
let prim = match style_sheet {
|
||||
Self::Style::Image(handle, color) => {
|
||||
let background = Primitive::Image {
|
||||
handle: (*handle, Rotation::None),
|
||||
bounds,
|
||||
color: *color,
|
||||
};
|
||||
|
||||
(content, mouse_interaction)
|
||||
Primitive::Group {
|
||||
primitives: vec![background, content],
|
||||
}
|
||||
},
|
||||
Self::Style::Color(color) => {
|
||||
let background = Primitive::Rectangle {
|
||||
bounds,
|
||||
linear_color: srgba_to_linear(color.map(|e| e as f32 / 255.0)),
|
||||
};
|
||||
|
||||
Primitive::Group {
|
||||
primitives: vec![background, content],
|
||||
}
|
||||
},
|
||||
Self::Style::None => content,
|
||||
};
|
||||
|
||||
(prim, mouse_interaction)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user