Files
komp_ac/client/src/pages/login/state.rs

249 lines
6.1 KiB
Rust

// src/pages/login/state.rs
use canvas::{AppMode, DataProvider};
use canvas::FormEditor;
use std::fmt;
#[derive(Debug, Clone)]
pub struct LoginState {
pub username: String,
pub password: String,
pub error_message: Option<String>,
pub current_field: usize,
pub current_cursor_pos: usize,
pub has_unsaved_changes: bool,
pub login_request_pending: bool,
pub app_mode: AppMode,
}
impl Default for LoginState {
fn default() -> Self {
Self {
username: String::new(),
password: String::new(),
error_message: None,
current_field: 0,
current_cursor_pos: 0,
has_unsaved_changes: false,
login_request_pending: false,
app_mode: canvas::AppMode::Edit,
}
}
}
impl LoginState {
pub fn new() -> Self {
Self {
app_mode: canvas::AppMode::Edit,
..Default::default()
}
}
pub fn current_field(&self) -> usize {
self.current_field
}
pub fn current_cursor_pos(&self) -> usize {
self.current_cursor_pos
}
pub fn set_current_field(&mut self, index: usize) {
if index < 2 {
self.current_field = index;
}
}
pub fn set_current_cursor_pos(&mut self, pos: usize) {
self.current_cursor_pos = pos;
}
pub fn get_current_input(&self) -> &str {
match self.current_field {
0 => &self.username,
1 => &self.password,
_ => "",
}
}
pub fn get_current_input_mut(&mut self) -> &mut String {
match self.current_field {
0 => &mut self.username,
1 => &mut self.password,
_ => panic!("Invalid current_field index in LoginState"),
}
}
pub fn current_mode(&self) -> AppMode {
self.app_mode
}
pub fn has_unsaved_changes(&self) -> bool {
self.has_unsaved_changes
}
pub fn set_has_unsaved_changes(&mut self, changed: bool) {
self.has_unsaved_changes = changed;
}
}
// Implement DataProvider for LoginState
impl DataProvider for LoginState {
fn field_count(&self) -> usize {
2
}
fn field_name(&self, index: usize) -> &str {
match index {
0 => "Username/Email",
1 => "Password",
_ => "",
}
}
fn field_value(&self, index: usize) -> &str {
match index {
0 => &self.username,
1 => &self.password,
_ => "",
}
}
fn set_field_value(&mut self, index: usize, value: String) {
match index {
0 => self.username = value,
1 => self.password = value,
_ => {}
}
self.has_unsaved_changes = true;
}
fn supports_suggestions(&self, _field_index: usize) -> bool {
false // Login form doesn't support suggestions
}
}
/// Wrapper that owns both the raw login state and its editor
pub struct LoginFormState {
pub state: LoginState,
pub editor: FormEditor<LoginState>,
pub focus_outside_canvas: bool,
pub focused_button_index: usize,
}
// manual debug because FormEditor doesnt implement debug
impl fmt::Debug for LoginFormState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LoginFormState")
.field("state", &self.state) // ✅ only print the data
.finish()
}
}
impl LoginFormState {
/// Sync the editor's data provider back into our state
pub fn sync_from_editor(&mut self) {
// FormEditor holds the authoritative data
let dp = self.editor.data_provider();
self.state = dp.clone(); // LoginState implements Clone
}
/// Create a new LoginFormState with default LoginState and FormEditor
pub fn new() -> Self {
let state = LoginState::default();
let editor = FormEditor::new(state.clone());
Self {
state,
editor,
focus_outside_canvas: false,
focused_button_index: 0,
}
}
// === Delegates to LoginState fields ===
pub fn username(&self) -> &str {
&self.state.username
}
pub fn username_mut(&mut self) -> &mut String {
&mut self.state.username
}
pub fn password(&self) -> &str {
&self.state.password
}
pub fn password_mut(&mut self) -> &mut String {
&mut self.state.password
}
pub fn error_message(&self) -> Option<&String> {
self.state.error_message.as_ref()
}
pub fn set_error_message(&mut self, msg: Option<String>) {
self.state.error_message = msg;
}
pub fn has_unsaved_changes(&self) -> bool {
self.state.has_unsaved_changes
}
pub fn set_has_unsaved_changes(&mut self, changed: bool) {
self.state.has_unsaved_changes = changed;
}
pub fn clear(&mut self) {
self.state.username.clear();
self.state.password.clear();
self.state.error_message = None;
self.state.has_unsaved_changes = false;
self.state.login_request_pending = false;
self.state.current_cursor_pos = 0;
}
// === Delegates to LoginState cursor/input ===
pub fn current_field(&self) -> usize {
self.state.current_field()
}
pub fn set_current_field(&mut self, index: usize) {
self.state.set_current_field(index);
}
pub fn current_cursor_pos(&self) -> usize {
self.state.current_cursor_pos()
}
pub fn set_current_cursor_pos(&mut self, pos: usize) {
self.state.set_current_cursor_pos(pos);
}
pub fn get_current_input(&self) -> &str {
self.state.get_current_input()
}
pub fn get_current_input_mut(&mut self) -> &mut String {
self.state.get_current_input_mut()
}
// === Delegates to FormEditor ===
pub fn mode(&self) -> AppMode {
self.editor.mode()
}
pub fn cursor_position(&self) -> usize {
self.editor.cursor_position()
}
pub fn handle_key_event(
&mut self,
key_event: crossterm::event::KeyEvent,
) -> canvas::keymap::KeyEventOutcome {
self.editor.handle_key_event(key_event)
}
}