eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
use super::ComponentManager;
use crate::app::{AppState, Action};
use crate::input::InputEvent;
use crate::errors::ComponentError;
use crossterm::event::KeyCode::*;

pub fn handle_diff_focus(event: InputEvent) -> Result<Option<Action>, ComponentError> {
    if let InputEvent::Key(key) = &event {
        if key.kind == crossterm::event::KeyEventKind::Press {
            return Ok(match key.code {
                Esc | Left => Some(Action::FocusStatus),
                Char('h') => Some(Action::FocusStatus),
                Up | Char('k') | Char('[') | PageUp => Some(Action::DetailScrollUp),
                Down | Char('j') | Char(']') | PageDown => Some(Action::DetailScrollDown),
                Char('<') => Some(Action::DetailScrollLeft),
                Char('>') => Some(Action::DetailScrollRight),
                Home => Some(Action::DetailScrollReset),
                _ => None,
            });
        }
    }
    Ok(None)
}

#[allow(dead_code)]
#[deprecated(note = "Command palette now handled by palette::PaletteHandler. This function kept for backward compatibility only.")]
pub fn handle_command_palette(_event: InputEvent, _state: &AppState, _manager: &ComponentManager) -> Result<Option<Action>, ComponentError> {
    // Old command palette handler - no longer used
    // New system handles commands via ComponentManager::handle_event -> palette::PaletteHandler
    Ok(None)
}

pub fn handle_log_action_menu(event: InputEvent, state: &AppState) -> Result<Option<Action>, ComponentError> {
    if let InputEvent::Key(key) = &event {
        if key.kind == crossterm::event::KeyEventKind::Press {
            match key.code {
                Esc => {
                    return Ok(Some(Action::HideLogActionMenu));
                }
                Up | Char('k') => {
                    return Ok(Some(Action::LogActionMenuUp));
                }
                Down | Char('j') => {
                    return Ok(Some(Action::LogActionMenuDown));
                }
                Enter => {
                    // Get available actions for this commit
                    let actions = get_available_log_actions(state);
                    if let Some(action) = actions.get(state.log_action_selected) {
                        return Ok(Some(Action::ExecuteLogAction(action.clone())));
                    }
                }
                _ => {}
            }
        }
    }
    Ok(None)
}

/// Get available log actions for the selected commit
pub fn get_available_log_actions(state: &AppState) -> Vec<crate::app::actions::LogAction> {
    use crate::app::actions::LogAction;
    let mut actions = vec![
        LogAction::ShowDetail,
        LogAction::CherryPick,
        LogAction::Revert,
        LogAction::ResetSoft,
        LogAction::ResetMixed,
        LogAction::ResetHard,
        LogAction::CreateBranch,
        LogAction::CreateTag,
    ];
    
    // Check if this is HEAD (first commit in list)
    if let Some(hash) = &state.log_action_commit_hash {
        if let Some(first_commit) = state.commits.first() {
            if first_commit.hash == *hash {
                // Insert Amend at position 3 (after ShowDetail, CherryPick, Revert)
                actions.insert(3, LogAction::Amend);
            }
        }
    }
    
    actions
}

pub fn handle_active_component(event: InputEvent, state: &AppState, manager: &mut ComponentManager) -> Result<Option<Action>, ComponentError> {
    if let Some(component) = manager.active_mut() {
        if let Some(action) = component.handle_event(event, state)? {
            return Ok(Some(action));
        }
    }
    Ok(None)
}

pub fn handle_global_keys(event: InputEvent, state: &AppState) -> Result<Option<Action>, ComponentError> {
    match event {
        InputEvent::Key(key) if key.kind == crossterm::event::KeyEventKind::Press => {
            match key.code {
                crossterm::event::KeyCode::Char('q') => {
                    Ok(Some(Action::Quit))
                }
                crossterm::event::KeyCode::Char('c')
                    if key.modifiers.contains(crossterm::event::KeyModifiers::CONTROL) =>
                {
                    Ok(Some(Action::Quit))
                }
                crossterm::event::KeyCode::Char('L') => {
                    Ok(Some(Action::LoadFullDiff))
                }
                crossterm::event::KeyCode::Char('l') => {
                    Ok(Some(Action::LoadFullDiff))
                }
                crossterm::event::KeyCode::Char('h') => {
                    Ok(Some(Action::ToggleHelp))
                }
                crossterm::event::KeyCode::Char('t') => {
                    // Show theme picker when 't' is pressed (not in palette mode)
                    if !state.command_palette {
                        Ok(Some(Action::ShowThemePicker))
                    } else {
                        Ok(None)
                    }
                }
                crossterm::event::KeyCode::Right => {
                    Ok(Some(Action::FocusDiff))
                }
                crossterm::event::KeyCode::Char(':') => {
                    Ok(Some(Action::ShowPalette))
                }
                crossterm::event::KeyCode::Tab => {
                    Ok(Some(Action::FocusNext))
                }
                crossterm::event::KeyCode::BackTab => {
                    Ok(Some(Action::FocusPrev))
                }
                // Command shortcuts are now handled by ShortcutHandler (supports multi-character)
                // Only navigation and special keys remain here
                _ => Ok(None),
            }
        }
        _ => Ok(None),
    }
}