eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
//! Event dispatching module splitting event_handlers.rs

use super::ComponentManager;
use crate::app::{AppState, Action};
use crate::input::InputEvent;
use crate::errors::ComponentError;

mod commit;
mod branches;
mod rebase;
mod conflicts;
mod popups;
mod navigation;

pub use commit::handle_commit_mode_with_amend;
pub use branches::{handle_branch_create_mode, handle_stash_create_mode};
pub use rebase::{
    handle_rebase_todo, handle_rebase_builder, handle_rebase_recovery, handle_reword_input, handle_edit_input
};
pub use conflicts::{handle_conflicts_popup, handle_conflicts_guided};
pub use popups::{
    handle_op_log, handle_merge_log, handle_pr_helper, handle_theme_picker,
    handle_merge_base_picker, handle_help
};
pub use navigation::{
    handle_diff_focus, handle_command_palette, handle_log_action_menu, handle_active_component,
    handle_global_keys, get_available_log_actions
};

pub fn handle_event(
    manager: &mut ComponentManager,
    event: InputEvent,
    state: &AppState,
) -> Result<Option<Action>, ComponentError> {
    // Commit mode priority
    if state.commit_mode {
        return handle_commit_mode_with_amend(event, state);
    }

    // Branch create mode
    if state.branch_create_mode {
        return handle_branch_create_mode(event, state);
    }

    // Stash create mode
    if state.stash_create_mode {
        return handle_stash_create_mode(event, state);
    }

    // Rebase builder
    if state.rebase_editor_open {
        return handle_rebase_builder(event, state);
    }

    // Rebase recovery
    if state.rebase_recovery_open {
        return handle_rebase_recovery(event, state);
    }

    // Confirm modal
    if state.confirm_action.is_some() {
        if let InputEvent::Key(key) = &event {
            if key.kind == crossterm::event::KeyEventKind::Press {
                use crossterm::event::KeyCode::*;
                return Ok(match key.code {
                    Enter => Some(Action::ConfirmExecute),
                    Esc => Some(Action::ConfirmCancel),
                    _ => None,
                });
            }
        }
        return Ok(None);
    }

    // Log action menu
    if state.log_action_menu {
        tracing::debug!("handle_event: Routing to log_action_menu handler, selected={}", state.log_action_selected);
        return handle_log_action_menu(event, state);
    }

    // Popups
    if state.show_op_log { return handle_op_log(event); }
    if state.show_merge_log { return handle_merge_log(event); }
    if state.show_rebase_todo { return handle_rebase_todo(event, state); }
    if state.conflicts_popup { return handle_conflicts_popup(event, state); }
    if state.conflicts_guided { return handle_conflicts_guided(event, state); }
    if state.pr_helper { return handle_pr_helper(event, state); }
    if state.theme_picker { return handle_theme_picker(event, state); }

    // Diff focus
    if state.diff_focus { return handle_diff_focus(event); }

    // Reset pending
    if let InputEvent::Key(key) = &event {
        if key.kind == crossterm::event::KeyEventKind::Press {
            if let crossterm::event::KeyCode::Esc = key.code {
                if state.reset_pending.is_some() {
                    return Ok(Some(Action::CancelReset));
                }
            }
        }
    }

    // Global keys (before command palette)
    if !state.command_palette {
        if let Some(action) = manager.shortcut_handler.handle_keypress(event.clone(), state)? {
            return Ok(Some(action));
        }
        if let Some(action) = handle_global_keys(event.clone(), state)? {
            return Ok(Some(action));
        }
    }

    // Merge base picker
    if state.merge_base_picker {
        return handle_merge_base_picker(event, state);
    }

    // Help
    if state.show_help {
        return handle_help(event, state);
    }

    // Active component (last resort)
    if let Some(action) = handle_active_component(event, state, manager)? {
        return Ok(Some(action));
    }
    
    Ok(None)
}