M client/src/main.rs => client/src/main.rs +2 -0
@@ 10,6 10,8 @@ use bevy::prelude::*;
use bevy_editor_pls::EditorPlugin;
use bevy_egui::EguiPlugin;
+mod util;
+
mod plugins;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, States)]
M => +8 -2
@@ 31,9 31,11 @@ enum MenuState {
}
#[derive(Resource)]
struct MenuData {
pub struct MenuData {
ui_state: MenuUIState,
error: String,
login_email: String,
login_password: String,
@@ 48,6 50,8 @@ impl Default for MenuData {
Self {
ui_state: MenuUIState::Login,
error: String::from(""),
login_email: String::from(""),
login_password: String::from(""),
@@ 59,7 63,9 @@ impl Default for MenuData {
}
}
enum MenuUIState {
#[derive(Debug)]
pub enum MenuUIState {
Loading, // for waiting for requests to finish
Login,
Register,
A => +44 -0
@@ 0,0 1,44 @@
/*
* This file is part of laurelin_client
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* Licensed under GPL-3.0-only.
* See LICENSE for licensing information.
*/
use bevy_egui::egui;
use crate::util::egui::password;
use super::{MenuData, MenuUIState};
pub fn view(ui: &mut egui::Ui, data: &mut MenuData) {
ui.horizontal(|ui| {
ui.label("Email:");
ui.text_edit_singleline(&mut data.login_email)
});
ui.horizontal(|ui| {
ui.label("Password:");
ui.add(password(&mut data.login_password));
});
if !data.error.is_empty() {
ui.label(egui::RichText::new(&data.error).color(egui::Color32::RED));
}
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
if ui.button("Login").clicked() {
data.error.clear();
data.ui_state = MenuUIState::Loading;
// use dem fields to do stuff
}
});
ui.vertical_centered(|ui| {
ui.label("I don't have an account:");
if ui.link("Register").clicked() {
data.ui_state = MenuUIState::Register;
}
});
}
M => +24 -3
@@ 9,8 9,29 @@
use bevy::prelude::*;
use bevy_egui::{EguiContexts, egui};
pub fn ui(mut contexts: EguiContexts) {
egui::Window::new("Laurelin").show(contexts.ctx_mut(), |ui| {
ui.label("bonk");
pub use super::{MenuData, MenuUIState};
mod login;
mod register;
pub fn ui(mut contexts: EguiContexts, mut data: ResMut<MenuData>) {
egui::Window::new(format!("{:?}", data.ui_state))
.collapsible(false)
.resizable(false)
.anchor(egui::Align2::CENTER_CENTER, egui::Vec2::ZERO)
.show(contexts.ctx_mut(), |ui| {
match data.ui_state {
MenuUIState::Loading => {
ui.horizontal(|ui| {
ui.spinner();
ui.label("something may or may not be happening");
});
}
MenuUIState::Login => login::view(ui, &mut data),
MenuUIState::Register => register::view(ui, &mut data),
_ => {
ui.spinner();
}
}
});
}
A => +54 -0
@@ 0,0 1,54 @@
/*
* This file is part of laurelin_client
* Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
*
* Licensed under GPL-3.0-only.
* See LICENSE for licensing information.
*/
use bevy_egui::egui;
use crate::util::egui::password;
use super::{MenuData, MenuUIState};
pub fn view(ui: &mut egui::Ui, data: &mut MenuData) {
ui.horizontal(|ui| {
ui.label("Username:");
ui.text_edit_singleline(&mut data.register_username)
});
ui.horizontal(|ui| {
ui.label("Email:");
ui.text_edit_singleline(&mut data.register_email)
});
ui.horizontal(|ui| {
ui.label("Password:");
ui.add(password(&mut data.register_password));
});
ui.horizontal(|ui| {
ui.label("Confirm password:");
ui.add(password(&mut data.register_password_confirm));
});
if !data.error.is_empty() {
ui.label(egui::RichText::new(&data.error).color(egui::Color32::RED));
}
ui.add_enabled_ui(data.register_password == data.register_password_confirm, |ui| {
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
if ui.button("Register").clicked() {
data.error.clear();
data.ui_state = MenuUIState::Loading;
// do stuff with fields
}
});
});
ui.vertical_centered(|ui| {
ui.label("I have an account:");
if ui.link("Login").clicked() {
data.ui_state = MenuUIState::Login;
}
});
}
A client/src/util/egui/mod.rs => client/src/util/egui/mod.rs +37 -0
@@ 0,0 1,37 @@
+/*
+ * This file is part of laurelin_client
+ * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
+ *
+ * Licensed under GPL-3.0-only.
+ * See LICENSE for licensing information.
+ */
+
+use bevy_egui::egui;
+
+fn password_ui(ui: &mut egui::Ui, password: &mut String) -> egui::Response {
+ let state_id = ui.id().with("show_plaintext");
+
+ let mut show_plaintext = ui.data_mut(|d| d.get_temp::<bool>(state_id).unwrap_or(false));
+
+ let result = ui.with_layout(egui::Layout::left_to_right(egui::Align::Center), |ui| {
+ // TODO: this was previously add_sized() with a max of ui.available_size()
+ // just, a note if... some usecase breaks or something
+ ui.add(egui::TextEdit::singleline(password).password(!show_plaintext));
+
+ let response = ui
+ .add(egui::SelectableLabel::new(show_plaintext, "👁"))
+ .on_hover_text("Show/hide password");
+
+ if response.clicked() {
+ show_plaintext = !show_plaintext;
+ }
+ });
+
+ ui.data_mut(|d| d.insert_temp(state_id, show_plaintext));
+
+ result.response
+}
+
+pub fn password(password: &mut String) -> impl egui::Widget + '_ {
+ move |ui: &mut egui::Ui| password_ui(ui, password)
+}
A client/src/util/mod.rs => client/src/util/mod.rs +9 -0
@@ 0,0 1,9 @@
+/*
+ * This file is part of laurelin_client
+ * Copyright (C) 2023 Jonni Liljamo <jonni@liljamo.com>
+ *
+ * Licensed under GPL-3.0-only.
+ * See LICENSE for licensing information.
+ */
+
+pub mod egui;