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::{
13 Align, Button, Column, Container, Length, Row, Space, Text, TextInput, button, text_input,
14};
15
16const INPUT_WIDTH: u16 = 230;
17const INPUT_TEXT_SIZE: u16 = 20;
18
19#[derive(Default)]
21pub struct Prompt {
22 pub(super) error: Option<String>,
23 secure_service_button: button::State,
24 submit_button: button::State,
25 username: text_input::State,
26 password: text_input::State,
27}
28
29impl Prompt {
30 pub(super) fn view(
31 &mut self,
32 fonts: &Fonts,
33 imgs: &Imgs,
34 login_info: &LoginInfo,
35 auth_server: &Option<String>,
36 i18n: &Localization,
37 button_style: style::button::Style,
38 ) -> Element<'_, Message> {
39 let title_text = Text::new("Login").size(fonts.cyri.scale(25));
40 let password_required = auth_server.is_some();
41 let msg = if let Some(auth_server) = auth_server {
42 i18n.get_msg_ctx("main-login-enter-credentials", &i18n::fluent_args! {
43 "server" => auth_server
44 })
45 } else {
46 i18n.get_msg("main-login-enter-username")
47 };
48 let msg_text = Text::new(msg).size(fonts.cyri.scale(15));
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 checkbox = Button::new(
104 &mut self.secure_service_button,
105 Row::with_children(vec![
106 Text::new(checkmark)
107 .size(input_text_size)
108 .color(text_color)
109 .into(),
110 Text::new(i18n.get_msg("main-remember-password"))
111 .size(input_text_size)
112 .color(text_color)
113 .into(),
114 ])
115 .spacing(6),
116 );
117 let checkbox = if login_info.secure_service_status == CredentialStatus::Ready {
118 checkbox.on_press(Message::UseSecureService(!login_info.use_secure_service))
119 } else {
120 checkbox
121 };
122
123 inputs.push(checkbox.into());
124 };
125 }
126
127 let inputs = Column::with_children(inputs)
128 .spacing(5)
129 .align_items(Align::Center)
130 .width(Length::Fill);
131
132 let submit = Button::new(
133 &mut self.submit_button,
134 Text::new(i18n.get_msg("common-okay"))
135 .size(input_text_size)
136 .width(Length::Fill)
137 .height(Length::Fill)
138 .horizontal_alignment(iced::HorizontalAlignment::Center)
139 .vertical_alignment(iced::VerticalAlignment::Center),
140 )
141 .width(Length::Units(INPUT_WIDTH))
142 .height(Length::Units(35))
143 .style(button_style)
144 .on_press(Message::CredentialsSubmit);
145
146 let submit = Container::new(submit).width(Length::Fill).center_x();
147
148 let mut children = vec![title_text.into(), msg_text.into()];
149 if let Some(error) = self.error.as_deref() {
150 children.push(
151 Text::new(error)
152 .color(iced::Color::from_rgb(1.0, 0.7, 0.3))
153 .size(fonts.cyri.scale(15))
154 .into(),
155 );
156 }
157 children.extend([
158 Space::new(Length::Shrink, Length::Units(16)).into(),
159 inputs.into(),
160 submit.into(),
161 ]);
162
163 let content = Column::with_children(children)
164 .spacing(4)
165 .max_width(320)
166 .width(Length::Fill)
167 .height(Length::Shrink);
168
169 let prompt_window = Container::new(content)
170 .style(
171 style::container::Style::color_with_double_cornerless_border(
172 (22, 18, 16, 255).into(),
173 (11, 11, 11, 255).into(),
174 (54, 46, 38, 255).into(),
175 ),
176 )
177 .padding(20);
178
179 Container::new(prompt_window)
180 .width(Length::Fill)
181 .height(Length::Fill)
182 .center_x()
183 .center_y()
184 .into()
185 }
186
187 pub(super) fn focus_username(&mut self) {
188 self.password = text_input::State::new();
189 self.username = text_input::State::focused();
190 self.username.move_cursor_to_end();
191 }
192
193 pub(super) fn focus_password(&mut self) {
194 self.username = text_input::State::new();
195 self.password = text_input::State::focused();
196 self.password.move_cursor_to_end();
197 }
198
199 pub(super) fn tab(&mut self, password_required: bool) {
200 if self.username.is_focused() && password_required {
201 self.focus_password();
202 } else {
203 self.focus_username();
204 }
205 }
206}