eazygit 0.5.1

A fast TUI for Git with staging, conflicts, rebase, and palette-first UX
Documentation
use crate::app::{actions::Action, state::AppState};

pub fn reduce(mut state: AppState, action: &Action) -> Option<AppState> {
    match action {
        Action::Quit => {
            state.running = false;
        }
        Action::Tick => { /* no-op */ }
        Action::ToggleHelp => {
            state.show_help = !state.show_help;
        }
        Action::HelpUp => {
            if state.help_selected > 0 {
                state.help_selected -= 1;
            }
        }
        Action::HelpDown => {
            let max = state.key_help.len().saturating_sub(1);
            if state.help_selected < max {
                state.help_selected += 1;
            }
        }
        Action::ShowThemePicker => {
            if state.theme_preview_prior.is_none() {
                state.theme_preview_prior = Some(state.theme.clone());
            }
            state.command_palette = false;
            state.theme_picker = true;
            let current = state.theme.name.as_str();
            state.theme_picker_selected = state
                .available_themes
                .iter()
                .position(|t| t == current)
                .unwrap_or(0);
        }
        Action::HideThemePicker => {
            state.theme_picker = false;
            state.theme_preview_prior = None;
        }
        Action::ThemePickerUp => {
            if state.theme_picker_selected > 0 {
                state.theme_picker_selected -= 1;
            }
        }
        Action::ThemePickerDown => {
            let max = state.available_themes.len().saturating_sub(1);
            if state.theme_picker_selected < max {
                state.theme_picker_selected += 1;
            }
        }
        Action::LoadFullDiff => {
            state.load_full_diff = true;
            // Close palette if invoked from palette to reveal diff.
            state.command_palette = false;
            state.palette_input.clear();
            state.palette_selected = 0;
        }
        Action::FocusDiff => {
            state.diff_focus = true;
            state.command_palette = false;
        }
        Action::FocusStatus => {
            state.diff_focus = false;
            state.command_palette = false;
        }
        Action::ThemePreviewStart(prior) => {
            state.theme_preview_prior = Some((**prior).clone());
        }
        Action::ThemePreviewApply(new_theme) => {
            state.theme = (**new_theme).clone();
        }
        Action::ThemePreviewSet(idx, new_theme) => {
            state.theme_picker_selected = *idx;
            state.theme = (**new_theme).clone();
        }
        Action::ThemePreviewCancel => {
            if let Some(prior) = state.theme_preview_prior.take() {
                state.theme = prior;
            }
            state.theme_picker = false;
        }
        Action::ApplyTheme(_) => {
            state.theme_picker = false;
            state.theme_preview_prior = None;
            state.command_palette = false;
        }
        Action::ReloadTheme => {
            state.command_palette = false;
        }
        Action::ReloadConfig => {
            state.command_palette = false;
        }
        Action::SetAvailableThemes(list) => {
            state.available_themes = list.clone();
        }
        _ => return None,
    }
    Some(state)
}