use crate::theme::Theme;
use super::{
AgentOutputsState, AgentSelectorState, AnnotationState, BookmarkState, ChecklistState,
CommandBarState, DiffOptions, DiffState, FilePickerState, GlobalSearchState, NavigatorState,
ReviewState, SelectionState, TextBuffer, WorktreeState,
};
use super::annotation_state::{AnnotationCategory, AnnotationSeverity};
use super::settings_state::SettingsState;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CategoryPickerPhase {
SelectCategory,
SelectSeverity,
}
#[derive(Debug, Clone)]
pub struct AnnotationMenuItem {
pub file_path: String,
pub old_range: Option<(u32, u32)>,
pub new_range: Option<(u32, u32)>,
pub comment: String,
pub category: AnnotationCategory,
pub severity: AnnotationSeverity,
}
impl AnnotationMenuItem {
pub fn sort_line(&self) -> u32 {
self.new_range
.map(|(s, _)| s)
.or(self.old_range.map(|(s, _)| s))
.unwrap_or(0)
}
pub fn range_text(&self) -> String {
match (self.old_range, self.new_range) {
(_, Some((s, e))) if s == e => format!("Line {s}"),
(_, Some((s, e))) => format!("Lines {s}-{e}"),
(Some((s, e)), None) if s == e => format!("Removed line {s} (old)"),
(Some((s, e)), None) => format!("Removed lines {s}-{e} (old)"),
(None, None) => "Line ?".to_string(),
}
}
}
#[derive(Debug, Clone)]
pub struct EditingAnnotation {
pub file_path: String,
pub old_range: Option<(u32, u32)>,
pub new_range: Option<(u32, u32)>,
pub old_comment: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActiveView {
DiffExplorer,
WorktreeBrowser,
AgentOutputs,
FeedbackSummary,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FocusPanel {
Navigator,
DiffView,
ReviewPanel,
ChecklistPanel,
AgentRunList,
AgentOutput,
}
pub struct AppState {
pub active_view: ActiveView,
pub focus: FocusPanel,
pub diff: DiffState,
pub navigator: NavigatorState,
pub worktree: WorktreeState,
pub should_quit: bool,
pub commit_dialog_open: bool,
pub commit_message: TextBuffer,
pub target_dialog_open: bool,
pub target_dialog_input: TextBuffer,
pub status_message: Option<(String, bool)>, pub target_label: String,
pub hud_expanded: bool,
pub selection: SelectionState,
pub annotations: AnnotationState,
pub comment_editor_open: bool,
pub comment_editor_text: TextBuffer,
pub category_picker_open: bool,
pub category_picker_phase: CategoryPickerPhase,
pub pending_category: Option<AnnotationCategory>,
pub pending_severity: Option<AnnotationSeverity>,
pub prompt_preview_visible: bool,
pub prompt_preview_text: String,
pub annotation_menu_open: bool,
pub annotation_menu_items: Vec<AnnotationMenuItem>,
pub annotation_menu_selected: usize,
pub editing_annotation: Option<EditingAnnotation>,
pub agent_outputs: AgentOutputsState,
pub agent_selector: AgentSelectorState,
pub pty_focus: bool,
pub review: ReviewState,
pub restore_confirm_open: bool,
pub theme: Theme,
pub settings: SettingsState,
pub which_key_visible: bool,
pub global_search: GlobalSearchState,
pub feedback_summary_scroll: usize,
pub checklist: ChecklistState,
pub bookmarks: BookmarkState,
pub command_bar: CommandBarState,
pub file_picker: FilePickerState,
pub agentic_review_modal_open: bool, pub agentic_review_composing: bool,
pub agentic_review_text: TextBuffer,
pub agentic_review_running: bool,
pub agentic_review_panel_open: bool,
pub agentic_review_stream_output: String,
pub agentic_review_child_done: usize,
pub agentic_review_child_total: usize,
pub agentic_review_scroll: usize,
pub agentic_review_auto_scroll: bool,
}
impl AppState {
pub fn new(diff_options: DiffOptions, theme: Theme) -> Self {
Self {
active_view: ActiveView::DiffExplorer,
focus: FocusPanel::Navigator,
diff: DiffState::new(diff_options),
navigator: NavigatorState::new(),
worktree: WorktreeState::new(),
should_quit: false,
commit_dialog_open: false,
commit_message: TextBuffer::new(),
target_dialog_open: false,
target_dialog_input: TextBuffer::new(),
status_message: None,
target_label: String::new(),
hud_expanded: false,
selection: SelectionState::default(),
annotations: AnnotationState::default(),
comment_editor_open: false,
comment_editor_text: TextBuffer::new(),
category_picker_open: false,
category_picker_phase: CategoryPickerPhase::SelectCategory,
pending_category: None,
pending_severity: None,
prompt_preview_visible: false,
prompt_preview_text: String::new(),
annotation_menu_open: false,
annotation_menu_items: Vec::new(),
annotation_menu_selected: 0,
editing_annotation: None,
agent_outputs: AgentOutputsState::default(),
agent_selector: AgentSelectorState::default(),
pty_focus: false,
review: ReviewState::default(),
restore_confirm_open: false,
theme,
settings: SettingsState::default(),
global_search: GlobalSearchState::default(),
feedback_summary_scroll: 0,
which_key_visible: false,
checklist: ChecklistState::new(),
bookmarks: BookmarkState::new(),
command_bar: CommandBarState::new(),
file_picker: FilePickerState::new(),
agentic_review_modal_open: false,
agentic_review_composing: false,
agentic_review_text: TextBuffer::new(),
agentic_review_running: false,
agentic_review_panel_open: false,
agentic_review_stream_output: String::new(),
agentic_review_child_done: 0,
agentic_review_child_total: 0,
agentic_review_scroll: 0,
agentic_review_auto_scroll: true,
}
}
}