Skip to main content

veloren_voxygen/menu/main/ui/
credentials.rs

1use 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/// Credential prompt for the connecting screen
20#[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                    // XAG 102 (Inactive Elements)
96                    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}