extends Control ## Login Screen Script ## ## Handles user authentication via the backend API. ## Validates input, displays errors, and navigates to character list on success. # Node references @onready var email_input: LineEdit = $CenterContainer/LoginCard/MainContainer/ContentVBox/EmailInput @onready var password_input: LineEdit = $CenterContainer/LoginCard/MainContainer/ContentVBox/PasswordInput @onready var login_button: Button = $CenterContainer/LoginCard/MainContainer/ContentVBox/LoginButton @onready var error_label: Label = $CenterContainer/LoginCard/MainContainer/ContentVBox/ErrorLabel @onready var remember_checkbox: CheckBox = $CenterContainer/LoginCard/MainContainer/ContentVBox/RememberCheckBox @onready var register_link: Button = $CenterContainer/LoginCard/MainContainer/ContentVBox/BottomLinksVBox/RegisterLink @onready var forgot_password_link: Button = $CenterContainer/LoginCard/MainContainer/ContentVBox/BottomLinksVBox/ForgotPasswordLink # Service references @onready var http_client: Node = get_node("/root/HTTPClient") @onready var state_manager: Node = get_node("/root/StateManager") # Internal state var _is_loading: bool = false func _ready() -> void: print("[LoginScreen] Initialized") # Connect button signals login_button.pressed.connect(_on_login_button_pressed) register_link.pressed.connect(_on_register_link_pressed) forgot_password_link.pressed.connect(_on_forgot_password_link_pressed) # Connect Enter key to submit email_input.text_submitted.connect(_on_input_submitted) password_input.text_submitted.connect(_on_input_submitted) # Hide error label by default error_label.visible = false # Load saved remember setting remember_checkbox.button_pressed = state_manager.get_setting("remember_login", true) ## Handle login button press func _on_login_button_pressed() -> void: # Prevent double-click if _is_loading: return # Get input values var email := email_input.text.strip_edges() var password := password_input.text # Validate inputs var validation_error := _validate_inputs(email, password) if not validation_error.is_empty(): _show_error(validation_error) return # Start login process _start_login(email, password) ## Handle Enter key press in input fields func _on_input_submitted(_text: String = "") -> void: _on_login_button_pressed() ## Validate email and password func _validate_inputs(email: String, password: String) -> String: # Check if email is empty if email.is_empty(): return "Please enter your email address" # Check if password is empty if password.is_empty(): return "Please enter your password" # Basic email format validation (contains @ and .) if not email.contains("@") or not email.contains("."): return "Please enter a valid email address" # Check minimum password length if password.length() < 6: return "Password must be at least 6 characters" return "" ## Start login process func _start_login(email: String, password: String) -> void: _is_loading = true _hide_error() # Disable button and show loading state login_button.disabled = true login_button.text = "LOGGING IN..." # Build request payload var payload := { "email": email, "password": password, "remember_me": remember_checkbox.button_pressed } print("[LoginScreen] Attempting login for: %s (remember_me=%s)" % [email, remember_checkbox.button_pressed]) # Make API request http_client.http_post( "/api/v1/auth/login", payload, _on_login_success, _on_login_error ) ## Handle successful login response func _on_login_success(response: APIResponse) -> void: _is_loading = false # Re-enable button login_button.disabled = false login_button.text = "LOGIN" # Check if response is actually successful if not response.is_success(): _on_login_error(response) return print("[LoginScreen] Login successful") # Extract user data from response # Note: Authentication is cookie-based, so no token in response var result: Dictionary = response.result if response.result is Dictionary else {} var user_data: Dictionary = result.get("user", {}) if user_data.is_empty(): _show_error("Invalid response from server") return # Update remember setting state_manager.set_setting("remember_login", remember_checkbox.button_pressed) # Save session to StateManager (cookie is already set in HTTPClient) state_manager.set_user_session(user_data) print("[LoginScreen] User authenticated: %s" % user_data.get("email", "unknown")) print("[LoginScreen] Session cookie stored, ready for authenticated requests") # Navigate back to main screen (which will show authenticated UI) print("[LoginScreen] Navigating to main screen...") get_tree().change_scene_to_file("res://scenes/main.tscn") ## Handle login error func _on_login_error(response: APIResponse) -> void: _is_loading = false # Re-enable button login_button.disabled = false login_button.text = "LOGIN" # Get error message var error_message := response.get_error_message() # Show user-friendly error if error_message.is_empty(): error_message = "Login failed. Please try again." # Handle specific error cases if response.status == 401: error_message = "Invalid email or password" elif response.status == 0 or response.status >= 500: error_message = "Cannot connect to server. Please check your connection." print("[LoginScreen] Login error: %s (status=%d)" % [error_message, response.status]) _show_error(error_message) ## Show error message func _show_error(message: String) -> void: error_label.text = message error_label.visible = true ## Hide error message func _hide_error() -> void: error_label.visible = false ## Handle register link press func _on_register_link_pressed() -> void: print("[LoginScreen] Opening registration page in browser") var register_url := Settings.get_web_url() + "/auth/register" var error := OS.shell_open(register_url) if error != OK: push_error("[LoginScreen] Failed to open browser: %s" % error) _show_error("Could not open registration page") ## Handle forgot password link press func _on_forgot_password_link_pressed() -> void: print("[LoginScreen] Opening forgot password page in browser") var forgot_url := Settings.get_web_url() + "/auth/forgot-password" var error := OS.shell_open(forgot_url) if error != OK: push_error("[LoginScreen] Failed to open browser: %s" % error) _show_error("Could not open password reset page")