login and register are now havving own handlers and loaders, moving logic out of event.rs and ui.rs
This commit is contained in:
@@ -305,94 +305,33 @@ impl EventHandler {
|
|||||||
|
|
||||||
if !overlay_active {
|
if !overlay_active {
|
||||||
if let Page::Login(login_page) = &mut router.current {
|
if let Page::Login(login_page) = &mut router.current {
|
||||||
use crossterm::event::{KeyCode, KeyModifiers};
|
let outcome =
|
||||||
|
login::event::handle_login_event(event, app_state, login_page)?;
|
||||||
// Inside canvas: at the last field, 'j' or Down moves focus to buttons
|
// Only return if the login page actually consumed the key
|
||||||
if !app_state.ui.focus_outside_canvas {
|
if !outcome.get_message_if_ok().is_empty() {
|
||||||
let last_idx = login_page
|
return Ok(outcome);
|
||||||
.editor
|
|
||||||
.data_provider()
|
|
||||||
.field_count()
|
|
||||||
.saturating_sub(1);
|
|
||||||
let at_last = login_page.editor.current_field() >= last_idx;
|
|
||||||
if at_last
|
|
||||||
&& matches!(
|
|
||||||
(key_code, modifiers),
|
|
||||||
(KeyCode::Char('j'), KeyModifiers::NONE) | (KeyCode::Down, _)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
app_state.ui.focus_outside_canvas = true;
|
|
||||||
app_state.focused_button_index = 0; // focus "Login" button
|
|
||||||
// Ensure canvas mode is ReadOnly when leaving
|
|
||||||
login_page.editor.set_mode(CanvasMode::ReadOnly);
|
|
||||||
return Ok(EventOutcome::Ok("Focus moved to buttons".to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only forward to the canvas while focus is inside it
|
|
||||||
if !app_state.ui.focus_outside_canvas {
|
|
||||||
match login_page.handle_key_event(key_event) {
|
|
||||||
KeyEventOutcome::Consumed(Some(msg)) => {
|
|
||||||
self.command_message = msg;
|
|
||||||
return Ok(EventOutcome::Ok("Login input updated".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::Consumed(None) => {
|
|
||||||
return Ok(EventOutcome::Ok("Login input updated".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::Pending => {
|
|
||||||
return Ok(EventOutcome::Ok("Waiting for next key...".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::NotMatched => {
|
|
||||||
// fall through to other handlers (buttons, etc.)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if let Page::Register(register_page) = &mut router.current {
|
} else if let Page::Register(register_page) = &mut router.current {
|
||||||
use crossterm::event::{KeyCode, KeyModifiers};
|
let outcome = crate::pages::register::event::handle_register_event(
|
||||||
|
event,
|
||||||
// Inside canvas: at the last field, 'j' or Down moves focus to buttons
|
app_state,
|
||||||
if !app_state.ui.focus_outside_canvas {
|
register_page,
|
||||||
let last_idx = register_page.editor.data_provider().field_count().saturating_sub(1);
|
)?;
|
||||||
let at_last = register_page.editor.current_field() >= last_idx;
|
// Only stop if page actually consumed the key; else fall through to global handling
|
||||||
if at_last
|
if !outcome.get_message_if_ok().is_empty() {
|
||||||
&& matches!(
|
return Ok(outcome);
|
||||||
(key_code, modifiers),
|
|
||||||
(KeyCode::Char('j'), KeyModifiers::NONE) | (KeyCode::Down, _)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
app_state.ui.focus_outside_canvas = true;
|
|
||||||
app_state.focused_button_index = 0; // focus "Register" button
|
|
||||||
register_page.editor.set_mode(CanvasMode::ReadOnly);
|
|
||||||
return Ok(EventOutcome::Ok("Focus moved to buttons".to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only forward to the canvas while focus is inside it
|
|
||||||
if !app_state.ui.focus_outside_canvas {
|
|
||||||
match register_page.handle_key_event(key_event) {
|
|
||||||
KeyEventOutcome::Consumed(Some(msg)) => {
|
|
||||||
self.command_message = msg;
|
|
||||||
return Ok(EventOutcome::Ok("Register input updated".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::Consumed(None) => {
|
|
||||||
return Ok(EventOutcome::Ok("Register input updated".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::Pending => {
|
|
||||||
return Ok(EventOutcome::Ok("Waiting for next key...".to_string()));
|
|
||||||
}
|
|
||||||
KeyEventOutcome::NotMatched => {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if let Page::Form(path) = &router.current {
|
} else if let Page::Form(path) = &router.current {
|
||||||
// NEW: Delegate Form event handling
|
let outcome = forms::event::handle_form_event(
|
||||||
return forms::event::handle_form_event(
|
event,
|
||||||
event,
|
app_state,
|
||||||
app_state,
|
path,
|
||||||
path,
|
&mut self.ideal_cursor_column,
|
||||||
&mut self.ideal_cursor_column
|
)?;
|
||||||
);
|
// Only return if the form page actually consumed the key
|
||||||
|
if !outcome.get_message_if_ok().is_empty() {
|
||||||
|
return Ok(outcome);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if toggle_sidebar(
|
if toggle_sidebar(
|
||||||
@@ -508,19 +447,6 @@ impl EventHandler {
|
|||||||
match &mut router.current {
|
match &mut router.current {
|
||||||
// LOGIN: From buttons (general) back into the canvas with 'k' (Up),
|
// LOGIN: From buttons (general) back into the canvas with 'k' (Up),
|
||||||
// but ONLY from the left-most "Login" button.
|
// but ONLY from the left-most "Login" button.
|
||||||
Page::Login(page) => {
|
|
||||||
if app_state.ui.focus_outside_canvas {
|
|
||||||
if app_state.focused_button_index == 0
|
|
||||||
&& matches!(ma, crate::movement::MovementAction::Up)
|
|
||||||
{
|
|
||||||
app_state.ui.focus_outside_canvas = false;
|
|
||||||
// Enter canvas in ReadOnly mode (never jump straight to Edit)
|
|
||||||
page.editor.set_mode(CanvasMode::ReadOnly);
|
|
||||||
// Optional: keep current field (usually 0 initially)
|
|
||||||
return Ok(EventOutcome::Ok(String::new()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Page::AddTable(state) => {
|
Page::AddTable(state) => {
|
||||||
if state.handle_movement(ma) {
|
if state.handle_movement(ma) {
|
||||||
// Keep UI focus consistent with inputs vs. outer elements
|
// Keep UI focus consistent with inputs vs. outer elements
|
||||||
|
|||||||
60
client/src/pages/admin/admin/event.rs
Normal file
60
client/src/pages/admin/admin/event.rs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
// src/pages/admin/admin/event.rs
|
||||||
|
use anyhow::Result;
|
||||||
|
use crossterm::event::KeyEvent;
|
||||||
|
|
||||||
|
use crate::buffer::state::BufferState;
|
||||||
|
use crate::config::binds::config::Config;
|
||||||
|
use crate::pages::admin::AdminState;
|
||||||
|
use crate::pages::admin::main::logic::handle_admin_navigation;
|
||||||
|
use crate::state::app::state::AppState;
|
||||||
|
|
||||||
|
/// Handle all Admin page-specific key events (movement + actions).
|
||||||
|
/// Returns true if the key was handled (so the caller should stop propagation).
|
||||||
|
pub fn handle_admin_event(
|
||||||
|
key_event: KeyEvent,
|
||||||
|
config: &Config,
|
||||||
|
app_state: &mut AppState,
|
||||||
|
admin_state: &mut AdminState,
|
||||||
|
buffer_state: &mut BufferState,
|
||||||
|
command_message: &mut String,
|
||||||
|
) -> Result<bool> {
|
||||||
|
// 1) Map general action to MovementAction (same mapping used in event.rs)
|
||||||
|
let movement_action = if let Some(act) =
|
||||||
|
config.get_general_action(key_event.code, key_event.modifiers)
|
||||||
|
{
|
||||||
|
use crate::movement::MovementAction;
|
||||||
|
match act {
|
||||||
|
"up" => Some(MovementAction::Up),
|
||||||
|
"down" => Some(MovementAction::Down),
|
||||||
|
"left" => Some(MovementAction::Left),
|
||||||
|
"right" => Some(MovementAction::Right),
|
||||||
|
"next" => Some(MovementAction::Next),
|
||||||
|
"previous" => Some(MovementAction::Previous),
|
||||||
|
"select" => Some(MovementAction::Select),
|
||||||
|
"esc" => Some(MovementAction::Esc),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ma) = movement_action {
|
||||||
|
if admin_state.handle_movement(app_state, ma) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Rich Admin navigation (buttons, selections, etc.)
|
||||||
|
if handle_admin_navigation(
|
||||||
|
key_event,
|
||||||
|
config,
|
||||||
|
app_state,
|
||||||
|
admin_state,
|
||||||
|
buffer_state,
|
||||||
|
command_message,
|
||||||
|
) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
54
client/src/pages/admin/admin/loader.rs
Normal file
54
client/src/pages/admin/admin/loader.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// src/pages/admin/admin/loader.rs
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
|
use crate::pages::admin::{AdminFocus, AdminState};
|
||||||
|
use crate::services::grpc_client::GrpcClient;
|
||||||
|
use crate::state::app::state::AppState;
|
||||||
|
|
||||||
|
/// Refresh admin data and ensure focus and selections are valid.
|
||||||
|
pub async fn refresh_admin_state(
|
||||||
|
grpc_client: &mut GrpcClient,
|
||||||
|
app_state: &mut AppState,
|
||||||
|
admin_state: &mut AdminState,
|
||||||
|
) -> Result<()> {
|
||||||
|
// Fetch latest profile tree
|
||||||
|
let refreshed_tree = grpc_client
|
||||||
|
.get_profile_tree()
|
||||||
|
.await
|
||||||
|
.context("Failed to refresh profile tree for Admin panel")?;
|
||||||
|
app_state.profile_tree = refreshed_tree;
|
||||||
|
|
||||||
|
// Populate profile names for AdminState's list
|
||||||
|
let profile_names = app_state
|
||||||
|
.profile_tree
|
||||||
|
.profiles
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.name.clone())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
admin_state.set_profiles(profile_names);
|
||||||
|
|
||||||
|
// Ensure a sane focus
|
||||||
|
if admin_state.current_focus == AdminFocus::default()
|
||||||
|
|| !matches!(
|
||||||
|
admin_state.current_focus,
|
||||||
|
AdminFocus::InsideProfilesList
|
||||||
|
| AdminFocus::Tables
|
||||||
|
| AdminFocus::InsideTablesList
|
||||||
|
| AdminFocus::Button1
|
||||||
|
| AdminFocus::Button2
|
||||||
|
| AdminFocus::Button3
|
||||||
|
| AdminFocus::ProfilesPane
|
||||||
|
)
|
||||||
|
{
|
||||||
|
admin_state.current_focus = AdminFocus::ProfilesPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure a selection exists when profiles are present
|
||||||
|
if admin_state.profile_list_state.selected().is_none()
|
||||||
|
&& !app_state.profile_tree.profiles.is_empty()
|
||||||
|
{
|
||||||
|
admin_state.profile_list_state.select(Some(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -3,5 +3,7 @@
|
|||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod tui;
|
pub mod tui;
|
||||||
|
pub mod event;
|
||||||
|
pub mod loader;
|
||||||
|
|
||||||
pub use state::{AdminState, AdminFocus};
|
pub use state::{AdminState, AdminFocus};
|
||||||
|
|||||||
73
client/src/pages/login/event.rs
Normal file
73
client/src/pages/login/event.rs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// src/pages/login/event.rs
|
||||||
|
use anyhow::Result;
|
||||||
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||||
|
use canvas::{keymap::KeyEventOutcome, AppMode as CanvasMode};
|
||||||
|
use crate::{
|
||||||
|
state::app::state::AppState,
|
||||||
|
pages::login::LoginFormState,
|
||||||
|
modes::handlers::event::EventOutcome,
|
||||||
|
};
|
||||||
|
use canvas::DataProvider;
|
||||||
|
|
||||||
|
/// Handles all Login page-specific events
|
||||||
|
pub fn handle_login_event(
|
||||||
|
event: Event,
|
||||||
|
app_state: &mut AppState,
|
||||||
|
login_page: &mut LoginFormState,
|
||||||
|
) -> Result<EventOutcome> {
|
||||||
|
if let Event::Key(key_event) = event {
|
||||||
|
let key_code = key_event.code;
|
||||||
|
let modifiers = key_event.modifiers;
|
||||||
|
|
||||||
|
// From buttons (outside) back into the canvas (ReadOnly) with Up/k from the left-most button
|
||||||
|
if login_page.focus_outside_canvas
|
||||||
|
&& login_page.focused_button_index == 0
|
||||||
|
&& matches!(key_code, KeyCode::Up | KeyCode::Char('k'))
|
||||||
|
&& modifiers.is_empty()
|
||||||
|
{
|
||||||
|
login_page.focus_outside_canvas = false;
|
||||||
|
app_state.ui.focus_outside_canvas = false; // 🔑 keep global in sync
|
||||||
|
login_page.editor.set_mode(CanvasMode::ReadOnly);
|
||||||
|
return Ok(EventOutcome::Ok(String::new()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus handoff: inside canvas → buttons
|
||||||
|
if !login_page.focus_outside_canvas {
|
||||||
|
let last_idx = login_page.editor.data_provider().field_count().saturating_sub(1);
|
||||||
|
let at_last = login_page.editor.current_field() >= last_idx;
|
||||||
|
if at_last
|
||||||
|
&& matches!(
|
||||||
|
(key_code, modifiers),
|
||||||
|
(KeyCode::Char('j'), KeyModifiers::NONE) | (KeyCode::Down, _)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
login_page.focus_outside_canvas = true;
|
||||||
|
login_page.focused_button_index = 0; // focus "Login" button
|
||||||
|
app_state.ui.focus_outside_canvas = true;
|
||||||
|
app_state.focused_button_index = 0;
|
||||||
|
login_page.editor.set_mode(CanvasMode::ReadOnly);
|
||||||
|
return Ok(EventOutcome::Ok("Focus moved to buttons".into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward to canvas if focus is inside
|
||||||
|
if !login_page.focus_outside_canvas {
|
||||||
|
match login_page.handle_key_event(key_event) {
|
||||||
|
KeyEventOutcome::Consumed(Some(msg)) => {
|
||||||
|
return Ok(EventOutcome::Ok(msg));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::Consumed(None) => {
|
||||||
|
return Ok(EventOutcome::Ok("Login input updated".into()));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::Pending => {
|
||||||
|
return Ok(EventOutcome::Ok("Waiting for next key...".into()));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::NotMatched => {
|
||||||
|
// fall through to button handling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EventOutcome::Ok(String::new()))
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod logic;
|
pub mod logic;
|
||||||
|
pub mod event;
|
||||||
|
|
||||||
pub use state::*;
|
pub use state::*;
|
||||||
pub use ui::render_login;
|
pub use ui::render_login;
|
||||||
pub use logic::*;
|
pub use logic::*;
|
||||||
|
pub use event::*;
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ impl DataProvider for LoginState {
|
|||||||
pub struct LoginFormState {
|
pub struct LoginFormState {
|
||||||
pub state: LoginState,
|
pub state: LoginState,
|
||||||
pub editor: FormEditor<LoginState>,
|
pub editor: FormEditor<LoginState>,
|
||||||
|
pub focus_outside_canvas: bool,
|
||||||
|
pub focused_button_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
// manual debug because FormEditor doesnt implement debug
|
// manual debug because FormEditor doesnt implement debug
|
||||||
@@ -150,7 +152,12 @@ impl LoginFormState {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let state = LoginState::default();
|
let state = LoginState::default();
|
||||||
let editor = FormEditor::new(state.clone());
|
let editor = FormEditor::new(state.clone());
|
||||||
Self { state, editor }
|
Self {
|
||||||
|
state,
|
||||||
|
editor,
|
||||||
|
focus_outside_canvas: false,
|
||||||
|
focused_button_index: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Delegates to LoginState fields ===
|
// === Delegates to LoginState fields ===
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ pub fn render_login(
|
|||||||
|
|
||||||
// Login Button
|
// Login Button
|
||||||
let login_button_index = 0;
|
let login_button_index = 0;
|
||||||
let login_active = if app_state.ui.focus_outside_canvas {
|
let login_active = if login_page.focus_outside_canvas {
|
||||||
app_state.focused_button_index == login_button_index
|
app_state.focused_button_index == login_button_index
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
|||||||
76
client/src/pages/register/event.rs
Normal file
76
client/src/pages/register/event.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// src/pages/register/event.rs
|
||||||
|
use anyhow::Result;
|
||||||
|
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||||
|
use canvas::{keymap::KeyEventOutcome, AppMode as CanvasMode};
|
||||||
|
use canvas::DataProvider;
|
||||||
|
use crate::{
|
||||||
|
state::app::state::AppState,
|
||||||
|
pages::register::RegisterFormState,
|
||||||
|
modes::handlers::event::EventOutcome,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Handles all Register page-specific events.
|
||||||
|
/// Return a non-empty Ok(message) only when the page actually consumed the key,
|
||||||
|
/// otherwise return Ok("") to let global handling proceed.
|
||||||
|
pub fn handle_register_event(
|
||||||
|
event: Event,
|
||||||
|
app_state: &mut AppState,
|
||||||
|
register_page: &mut RegisterFormState,
|
||||||
|
)-> Result<EventOutcome> {
|
||||||
|
if let Event::Key(key_event) = event {
|
||||||
|
let key_code = key_event.code;
|
||||||
|
let modifiers = key_event.modifiers;
|
||||||
|
|
||||||
|
// From buttons (outside) back into the canvas (ReadOnly) with Up/k from the left-most button
|
||||||
|
if register_page.focus_outside_canvas
|
||||||
|
&& register_page.focused_button_index == 0
|
||||||
|
&& matches!(key_code, KeyCode::Up | KeyCode::Char('k'))
|
||||||
|
&& modifiers.is_empty()
|
||||||
|
{
|
||||||
|
register_page.focus_outside_canvas = false;
|
||||||
|
// Keep global in sync for now (cursor styling elsewhere still reads it)
|
||||||
|
app_state.ui.focus_outside_canvas = false;
|
||||||
|
register_page.editor.set_mode(CanvasMode::ReadOnly);
|
||||||
|
return Ok(EventOutcome::Ok(String::new()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus handoff: inside canvas → buttons
|
||||||
|
if !register_page.focus_outside_canvas {
|
||||||
|
let last_idx = register_page.editor.data_provider().field_count().saturating_sub(1);
|
||||||
|
let at_last = register_page.editor.current_field() >= last_idx;
|
||||||
|
if at_last
|
||||||
|
&& matches!(
|
||||||
|
(key_code, modifiers),
|
||||||
|
(KeyCode::Char('j'), KeyModifiers::NONE) | (KeyCode::Down, _)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
register_page.focus_outside_canvas = true;
|
||||||
|
register_page.focused_button_index = 0; // focus "Register" button
|
||||||
|
// Keep global in sync for now
|
||||||
|
app_state.ui.focus_outside_canvas = true;
|
||||||
|
app_state.focused_button_index = 0;
|
||||||
|
register_page.editor.set_mode(CanvasMode::ReadOnly);
|
||||||
|
return Ok(EventOutcome::Ok("Focus moved to buttons".into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward to canvas if focus is inside
|
||||||
|
if !register_page.focus_outside_canvas {
|
||||||
|
match register_page.handle_key_event(key_event) {
|
||||||
|
KeyEventOutcome::Consumed(Some(msg)) => {
|
||||||
|
return Ok(EventOutcome::Ok(msg));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::Consumed(None) => {
|
||||||
|
return Ok(EventOutcome::Ok("Register input updated".into()));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::Pending => {
|
||||||
|
return Ok(EventOutcome::Ok("Waiting for next key...".into()));
|
||||||
|
}
|
||||||
|
KeyEventOutcome::NotMatched => {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(EventOutcome::Ok(String::new()))
|
||||||
|
}
|
||||||
@@ -54,6 +54,8 @@ pub async fn back_to_login(
|
|||||||
buffer_state.update_history(AppView::Login);
|
buffer_state.update_history(AppView::Login);
|
||||||
|
|
||||||
// Reset focus state
|
// Reset focus state
|
||||||
|
register_state.focus_outside_canvas = false;
|
||||||
|
register_state.focused_button_index = 0;
|
||||||
app_state.ui.focus_outside_canvas = false;
|
app_state.ui.focus_outside_canvas = false;
|
||||||
app_state.focused_button_index = 0;
|
app_state.focused_button_index = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ pub mod ui;
|
|||||||
pub mod state;
|
pub mod state;
|
||||||
pub mod logic;
|
pub mod logic;
|
||||||
pub mod suggestions;
|
pub mod suggestions;
|
||||||
|
pub mod event;
|
||||||
|
|
||||||
// pub use state::*;
|
// pub use state::*;
|
||||||
pub use ui::render_register;
|
pub use ui::render_register;
|
||||||
pub use logic::*;
|
pub use logic::*;
|
||||||
pub use state::*;
|
pub use state::*;
|
||||||
|
pub use event::*;
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ impl DataProvider for RegisterState {
|
|||||||
pub struct RegisterFormState {
|
pub struct RegisterFormState {
|
||||||
pub state: RegisterState,
|
pub state: RegisterState,
|
||||||
pub editor: FormEditor<RegisterState>,
|
pub editor: FormEditor<RegisterState>,
|
||||||
|
pub focus_outside_canvas: bool,
|
||||||
|
pub focused_button_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RegisterFormState {
|
impl Default for RegisterFormState {
|
||||||
@@ -174,7 +176,12 @@ impl RegisterFormState {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let state = RegisterState::default();
|
let state = RegisterState::default();
|
||||||
let editor = FormEditor::new(state.clone());
|
let editor = FormEditor::new(state.clone());
|
||||||
Self { state, editor }
|
Self {
|
||||||
|
state,
|
||||||
|
editor,
|
||||||
|
focus_outside_canvas: false,
|
||||||
|
focused_button_index: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Delegates to RegisterState ===
|
// === Delegates to RegisterState ===
|
||||||
|
|||||||
@@ -80,8 +80,9 @@ pub fn render_register(
|
|||||||
|
|
||||||
// Register Button
|
// Register Button
|
||||||
let register_button_index = 0;
|
let register_button_index = 0;
|
||||||
let register_active = app_state.ui.focus_outside_canvas
|
let register_active =
|
||||||
&& app_state.focused_button_index == register_button_index;
|
register_page.focus_outside_canvas
|
||||||
|
&& register_page.focused_button_index == register_button_index;
|
||||||
let mut register_style = Style::default().fg(theme.fg);
|
let mut register_style = Style::default().fg(theme.fg);
|
||||||
let mut register_border = Style::default().fg(theme.border);
|
let mut register_border = Style::default().fg(theme.border);
|
||||||
if register_active {
|
if register_active {
|
||||||
@@ -104,8 +105,9 @@ pub fn render_register(
|
|||||||
|
|
||||||
// Return Button
|
// Return Button
|
||||||
let return_button_index = 1;
|
let return_button_index = 1;
|
||||||
let return_active = app_state.ui.focus_outside_canvas
|
let return_active =
|
||||||
&& app_state.focused_button_index == return_button_index;
|
register_page.focus_outside_canvas
|
||||||
|
&& register_page.focused_button_index == return_button_index;
|
||||||
let mut return_style = Style::default().fg(theme.fg);
|
let mut return_style = Style::default().fg(theme.fg);
|
||||||
let mut return_border = Style::default().fg(theme.border);
|
let mut return_border = Style::default().fg(theme.border);
|
||||||
if return_active {
|
if return_active {
|
||||||
|
|||||||
Reference in New Issue
Block a user