aboutsummaryrefslogtreecommitdiff
path: root/src/ui/login.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/login.rs')
-rw-r--r--src/ui/login.rs272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/ui/login.rs b/src/ui/login.rs
new file mode 100644
index 0000000..8a85418
--- /dev/null
+++ b/src/ui/login.rs
@@ -0,0 +1,272 @@
+use eframe::egui;
+use std::sync::mpsc::Receiver;
+
+use crate::api::ApiClient;
+use crate::models::LoginResponse;
+use crate::session::SessionManager;
+
+pub struct LoginScreen {
+ server_url: String,
+ username: String,
+ password: String,
+
+ remember_server: bool,
+ remember_username: bool,
+
+ error_message: Option<String>,
+ is_logging_in: bool,
+
+ // For async operations
+ login_receiver: Option<Receiver<Result<(String, LoginResponse), String>>>,
+}
+
+impl LoginScreen {
+ pub fn new(session_manager: &SessionManager) -> Self {
+ let server_url = session_manager
+ .get_saved_server_url()
+ .unwrap_or_else(|| "http://localhost:5777".to_string()); // Reminder to myself : Fucking remove this before release
+
+ let username = session_manager.get_saved_username().unwrap_or_default();
+
+ let remember_username = !username.is_empty();
+
+ Self {
+ server_url,
+ username,
+ password: String::new(),
+ remember_server: true,
+ remember_username,
+ error_message: None,
+ is_logging_in: false,
+ login_receiver: None,
+ }
+ }
+
+ pub fn show(&mut self, ctx: &egui::Context, on_success: &mut Option<(String, LoginResponse)>) {
+ // Check if we have a login result from async operation
+ if let Some(receiver) = &self.login_receiver {
+ match receiver.try_recv() {
+ Ok(result) => {
+ log::info!("UI thread: Received login result!");
+ self.is_logging_in = false;
+ self.login_receiver = None;
+
+ match result {
+ Ok((server_url, login_response)) => {
+ log::info!("UI thread: Login successful, setting on_success");
+ *on_success = Some((server_url, login_response));
+ }
+ Err(err) => {
+ log::error!("UI thread: Login failed: {} tried suicide yet maybe that actually works?", err);
+ self.error_message = Some(err);
+ }
+ }
+ }
+ Err(std::sync::mpsc::TryRecvError::Empty) => {
+ // Still waiting, request repaint to check again
+ ctx.request_repaint();
+ }
+ Err(std::sync::mpsc::TryRecvError::Disconnected) => {
+ log::error!("UI thread: Channel disconnected!");
+ self.is_logging_in = false;
+ self.login_receiver = None;
+ self.error_message = Some("Connection error".to_string());
+ }
+ }
+ }
+
+ egui::CentralPanel::default().show(ctx, |ui| {
+ // Center the login form both horizontally and vertically bruh
+ let available_size = ui.available_size();
+ let panel_width = available_size.x.min(500.0);
+
+ ui.allocate_ui_with_layout(
+ available_size,
+ egui::Layout::top_down(egui::Align::Center),
+ |ui| {
+ // Add vertical spacing to center
+ ui.add_space(available_size.y * 0.15);
+
+ // Logo/Title
+ ui.heading(egui::RichText::new("BeepZone Login").size(48.0).strong());
+ ui.label(
+ egui::RichText::new(format!(
+ "BeepZone Desktop Client eGUI EMO Edition - v{}",
+ env!("CARGO_PKG_VERSION")
+ ))
+ .size(18.0),
+ );
+
+ ui.add_space(30.0);
+
+ // Login form
+ egui::Frame::new()
+ .fill(ctx.style().visuals.window_fill)
+ .stroke(ctx.style().visuals.window_stroke)
+ .corner_radius(12.0)
+ .inner_margin(32.0)
+ .show(ui, |ui| {
+ ui.set_width(panel_width * 0.8);
+
+ // Server URL
+ ui.horizontal(|ui: &mut egui::Ui| {
+ ui.label("BeepZone Sekel API URL:");
+ ui.add_space(10.0);
+ });
+ ui.text_edit_singleline(&mut self.server_url);
+ ui.add_space(8.0);
+
+ // Username field
+ ui.label("Username:");
+ ui.text_edit_singleline(&mut self.username);
+ ui.add_space(8.0);
+
+ // Password field
+ ui.label("Password:");
+ let password_response = ui
+ .add(egui::TextEdit::singleline(&mut self.password).password(true));
+
+ // Enter key to submit
+ if password_response.lost_focus()
+ && ui.input(|i| i.key_pressed(egui::Key::Enter))
+ {
+ self.do_login();
+ }
+
+ ui.add_space(12.0);
+
+ // Remember options
+ ui.checkbox(&mut self.remember_server, "Remember Sekel URL");
+ ui.checkbox(&mut self.remember_username, "Remember Username");
+
+ ui.add_space(16.0);
+
+ // Error message
+ if let Some(error) = &self.error_message {
+ ui.label(format!("Error: {}", error));
+ ui.add_space(12.0);
+ }
+
+ // Login button
+ ui.add_enabled_ui(!self.is_logging_in, |ui| {
+ let button_text = if self.is_logging_in {
+ "Logging in..."
+ } else {
+ "Login"
+ };
+
+ if ui
+ .add_sized(
+ [ui.available_width(), 40.0],
+ egui::Button::new(button_text),
+ )
+ .clicked()
+ {
+ self.do_login();
+ }
+ });
+
+ if self.is_logging_in {
+ ui.add_space(8.0);
+ ui.horizontal(|ui| {
+ ui.spinner();
+ ui.label("Connecting to server...");
+ });
+ }
+ });
+
+ ui.add_space(20.0);
+ ui.label(
+ egui::RichText::new("- The only based Sigma Inventory System -")
+ .size(12.0)
+ .color(egui::Color32::GRAY),
+ );
+
+ // Debug info
+ if self.is_logging_in {
+ ui.add_space(10.0);
+ ui.label(
+ egui::RichText::new(format!("Connecting to: {}", self.server_url))
+ .size(10.0)
+ .color(egui::Color32::GRAY),
+ );
+ }
+ },
+ );
+ });
+ }
+
+ fn do_login(&mut self) {
+ // Validate inputs
+ if self.server_url.trim().is_empty() {
+ self.error_message =
+ Some("Server URL is required!? Perhaps enter it you know?".to_string());
+ return;
+ }
+
+ if self.username.trim().is_empty() || self.password.trim().is_empty() {
+ self.error_message = Some(
+ "Username and password are required!? Please enter both you know?".to_string(),
+ );
+ return;
+ }
+
+ self.error_message = None;
+ self.is_logging_in = true;
+
+ // Clone data for background thread
+ let server_url = self.server_url.clone();
+ let username = self.username.clone();
+ let password = self.password.clone();
+
+ log::info!("Trying to sign in as : {}", username);
+
+ // Create channel for communication
+ let (tx, rx) = std::sync::mpsc::channel();
+ self.login_receiver = Some(rx);
+
+ // Spawn background thread to perform login
+ std::thread::spawn(move || {
+ log::info!("Background thread: Connecting to {}", server_url);
+ let result = match ApiClient::new(server_url.clone()) {
+ Ok(client) => {
+ log::info!("Background thread: API client created, attempting login...");
+ match client.login_password(&username, &password) {
+ Ok(response) => {
+ log::info!(
+ "Background thread: Got response, success={}",
+ response.success
+ );
+ if response.success {
+ log::info!(
+ "Login successfulf for user: {}",
+ response.user.username
+ );
+ Ok((server_url, response))
+ } else {
+ let error = "Login failed gay credentials".to_string();
+ log::error!("{}", error);
+ Err(error)
+ }
+ }
+ Err(e) => {
+ let error = format!("Notwork error: {}", e);
+ log::error!("{}", error);
+ Err(error)
+ }
+ }
+ }
+ Err(e) => {
+ let error = format!("Failed at connecting to server somehow: {}", e);
+ log::error!("{}", error);
+ Err(error)
+ }
+ };
+
+ log::info!("Background thread: Sending result back to UI");
+ if let Err(e) = tx.send(result) {
+ log::error!("Background thread: Failed to send result: {:?}", e);
+ }
+ });
+ }
+}