veloren_voxygen/menu/main/ui/
credentials.rs1use super::{Imgs, LoginInfo, Message, TEXT_COLOR};
2use crate::ui::{
3 fonts::IcedFonts as Fonts,
4 ice::{
5 Element, style,
6 widget::{BackgroundContainer, Image, Padding},
7 },
8};
9
10use credentialstore::CredentialStatus;
11use i18n::Localization;
12use iced::{Align, Button, Column, Container, Length, Space, Text, TextInput, button, text_input};
13
14const INPUT_WIDTH: u16 = 230;
15const INPUT_TEXT_SIZE: u16 = 20;
16
17#[derive(Default)]
19pub struct Prompt {
20 pub(super) error: Option<String>,
21 secure_service_button: button::State,
22 submit_button: button::State,
23 username: text_input::State,
24 password: text_input::State,
25}
26
27impl Prompt {
28 pub(super) fn view(
29 &mut self,
30 fonts: &Fonts,
31 imgs: &Imgs,
32 login_info: &LoginInfo,
33 auth_server: &Option<String>,
34 i18n: &Localization,
35 button_style: style::button::Style,
36 ) -> Element<'_, Message> {
37 let title_text = Text::new("Login").size(fonts.cyri.scale(25));
38 let password_required = auth_server.is_some();
39 let msg = if let Some(auth_server) = auth_server {
40 i18n.get_msg_ctx("main-login-enter-credentials", &i18n::fluent_args! {
41 "server" => auth_server
42 })
43 } else {
44 i18n.get_msg("main-login-enter-username")
45 };
46 let msg_text = Text::new(msg)
47 .size(fonts.cyri.scale(15))
48 .width(Length::Fill);
49 let input_text_size = fonts.cyri.scale(INPUT_TEXT_SIZE);
50
51 let username = BackgroundContainer::new(
52 Image::new(imgs.input_bg)
53 .width(Length::Units(INPUT_WIDTH))
54 .fix_aspect_ratio(),
55 TextInput::new(
56 &mut self.username,
57 &i18n.get_msg("main-username"),
58 &login_info.username,
59 Message::Username,
60 )
61 .size(input_text_size)
62 .on_submit(if password_required {
63 Message::FocusPassword
64 } else {
65 Message::CredentialsSubmit
66 }),
67 )
68 .padding(Padding::new().horizontal(7).top(5));
69
70 let mut inputs = vec![username.into()];
71 if password_required {
72 inputs.push(
73 BackgroundContainer::new(
74 Image::new(imgs.input_bg)
75 .width(Length::Units(INPUT_WIDTH))
76 .fix_aspect_ratio(),
77 TextInput::new(
78 &mut self.password,
79 &i18n.get_msg("main-password"),
80 &login_info.password,
81 Message::Password,
82 )
83 .size(input_text_size)
84 .password()
85 .on_submit(Message::CredentialsSubmit),
86 )
87 .padding(Padding::new().horizontal(7).top(5))
88 .into(),
89 );
90
91 if login_info.secure_service_status > CredentialStatus::Disabled {
92 let text_color = if login_info.secure_service_status == CredentialStatus::Ready {
93 TEXT_COLOR
94 } else {
95 iced::Color::from_rgba(1.0, 1.0, 1.0, 0.4)
97 };
98 let checkmark = if login_info.use_secure_service {
99 "[X]"
100 } else {
101 "[ ]"
102 };
103 let password_text =
104 format!("{checkmark} {}", i18n.get_msg("main-remember-password"));
105 let checkbox = Button::new(
106 &mut self.secure_service_button,
107 Text::new(password_text)
108 .size(input_text_size)
109 .color(text_color)
110 .width(Length::Fill)
111 .horizontal_alignment(iced::HorizontalAlignment::Center),
112 );
113 let checkbox = if login_info.secure_service_status == CredentialStatus::Ready {
114 checkbox.on_press(Message::UseSecureService(!login_info.use_secure_service))
115 } else {
116 checkbox
117 };
118
119 inputs.push(checkbox.into());
120 };
121 }
122
123 let inputs = Column::with_children(inputs)
124 .spacing(5)
125 .align_items(Align::Center)
126 .width(Length::Fill);
127
128 let submit = Button::new(
129 &mut self.submit_button,
130 Text::new(i18n.get_msg("common-okay"))
131 .size(input_text_size)
132 .width(Length::Fill)
133 .height(Length::Fill)
134 .horizontal_alignment(iced::HorizontalAlignment::Center)
135 .vertical_alignment(iced::VerticalAlignment::Center),
136 )
137 .width(Length::Units(INPUT_WIDTH))
138 .height(Length::Units(35))
139 .style(button_style)
140 .on_press(Message::CredentialsSubmit);
141
142 let submit = Container::new(submit).width(Length::Fill).center_x();
143
144 let mut children = vec![title_text.into(), msg_text.into()];
145 if let Some(error) = self.error.as_deref() {
146 children.push(
147 Text::new(error)
148 .color(iced::Color::from_rgb(1.0, 0.7, 0.3))
149 .size(fonts.cyri.scale(15))
150 .into(),
151 );
152 }
153 children.extend([
154 Space::new(Length::Shrink, Length::Units(16)).into(),
155 inputs.into(),
156 submit.into(),
157 ]);
158
159 let content = Column::with_children(children)
160 .spacing(4)
161 .max_width(320)
162 .width(Length::Fill)
163 .height(Length::Shrink);
164
165 let prompt_window = Container::new(content)
166 .style(
167 style::container::Style::color_with_double_cornerless_border(
168 (22, 18, 16, 255).into(),
169 (11, 11, 11, 255).into(),
170 (54, 46, 38, 255).into(),
171 ),
172 )
173 .padding(20);
174
175 Container::new(prompt_window)
176 .width(Length::Fill)
177 .height(Length::Fill)
178 .center_x()
179 .center_y()
180 .into()
181 }
182
183 pub(super) fn focus_username(&mut self) {
184 self.password = text_input::State::new();
185 self.username = text_input::State::focused();
186 self.username.move_cursor_to_end();
187 }
188
189 pub(super) fn focus_password(&mut self) {
190 self.username = text_input::State::new();
191 self.password = text_input::State::focused();
192 self.password.move_cursor_to_end();
193 }
194
195 pub(super) fn tab(&mut self, password_required: bool) {
196 if self.username.is_focused() && password_required {
197 self.focus_password();
198 } else {
199 self.focus_username();
200 }
201 }
202}