git_tailor/views/
split_select.rs1use super::dialog::render_centered_dialog;
18use crate::app::{AppAction, AppMode, AppState, KeyCommand, SplitStrategy};
19use ratatui::{
20 Frame,
21 layout::Alignment,
22 style::{Color, Modifier, Style},
23 text::{Line, Span},
24};
25
26pub fn handle_key(action: KeyCommand, app: &mut AppState) -> AppAction {
28 match action {
29 KeyCommand::MoveUp => {
30 app.split_select_up();
31 AppAction::Handled
32 }
33 KeyCommand::MoveDown => {
34 app.split_select_down();
35 AppAction::Handled
36 }
37 KeyCommand::Confirm => {
38 let strategy = app.selected_split_strategy();
39 let commit_oid = app.commits[app.selection_index].oid.clone();
40 app.mode = AppMode::CommitList;
41 AppAction::PrepareSplit {
42 strategy,
43 commit_oid,
44 }
45 }
46 KeyCommand::ShowHelp => {
47 app.toggle_help();
48 AppAction::Handled
49 }
50 KeyCommand::Quit => {
51 app.mode = AppMode::CommitList;
52 AppAction::Handled
53 }
54 _ => AppAction::Handled,
55 }
56}
57
58pub fn handle_confirm_key(action: KeyCommand, app: &mut AppState) -> AppAction {
60 match action {
61 KeyCommand::Confirm => {
62 if let AppMode::SplitConfirm(pending) =
63 std::mem::replace(&mut app.mode, AppMode::CommitList)
64 {
65 AppAction::ExecuteSplit {
66 strategy: pending.strategy,
67 commit_oid: pending.commit_oid,
68 head_oid: pending.head_oid,
69 }
70 } else {
71 AppAction::Handled
72 }
73 }
74 KeyCommand::ShowHelp => {
75 app.toggle_help();
76 AppAction::Handled
77 }
78 KeyCommand::Quit => {
79 app.cancel_split_confirm();
80 AppAction::Handled
81 }
82 _ => AppAction::Handled,
83 }
84}
85
86pub fn render(app: &AppState, frame: &mut Frame) {
88 let commit_summary = app
89 .commits
90 .get(app.selection_index)
91 .map(|c| {
92 let short_oid = if c.oid.len() > 10 {
93 &c.oid[..10]
94 } else {
95 &c.oid
96 };
97 format!("{} {}", short_oid, c.summary)
98 })
99 .unwrap_or_default();
100
101 let max_summary_len = 44;
103 let display_summary = if commit_summary.len() > max_summary_len {
104 format!("{}…", &commit_summary[..max_summary_len - 1])
105 } else {
106 commit_summary
107 };
108
109 let mut lines = vec![
110 Line::from(""),
111 Line::from(Span::styled(
112 format!(" {}", display_summary),
113 Style::default()
114 .fg(Color::White)
115 .add_modifier(Modifier::DIM),
116 )),
117 Line::from(""),
118 Line::from(Span::styled(
119 " Choose split strategy:",
120 Style::default()
121 .fg(Color::Yellow)
122 .add_modifier(Modifier::BOLD),
123 )),
124 Line::from(""),
125 ];
126
127 let strategy_index = match app.mode {
128 AppMode::SplitSelect { strategy_index } => strategy_index,
129 _ => 0,
130 };
131 for (i, strategy) in SplitStrategy::ALL.iter().enumerate() {
132 let selected = i == strategy_index;
133 let marker = if selected { "▸ " } else { " " };
134 let style = if selected {
135 Style::default()
136 .fg(Color::Cyan)
137 .add_modifier(Modifier::BOLD)
138 } else {
139 Style::default().fg(Color::White)
140 };
141
142 lines.push(Line::from(Span::styled(
143 format!(" {} {}", marker, strategy.label()),
144 style,
145 )));
146
147 let desc_style = Style::default().fg(Color::DarkGray);
148 lines.push(Line::from(Span::styled(
149 format!(" {}", strategy.description()),
150 desc_style,
151 )));
152 lines.push(Line::from(""));
153 }
154
155 lines.push(
156 Line::from(vec![
157 Span::styled("Enter ", Style::default().fg(Color::Cyan)),
158 Span::raw("Select "),
159 Span::styled("Esc ", Style::default().fg(Color::Cyan)),
160 Span::raw("Cancel"),
161 ])
162 .alignment(Alignment::Center),
163 );
164 lines.push(Line::from(""));
165
166 let content_width = 50;
167
168 render_centered_dialog(frame, " Split Commit ", Color::Cyan, content_width, lines);
169}
170
171pub fn render_split_confirm(app: &AppState, frame: &mut Frame) {
173 let pending = match &app.mode {
174 AppMode::SplitConfirm(p) => p,
175 _ => return,
176 };
177 let strategy_name = match pending.strategy {
178 crate::app::SplitStrategy::PerFile => "per file",
179 crate::app::SplitStrategy::PerHunk => "per hunk",
180 crate::app::SplitStrategy::PerHunkGroup => "per hunk group",
181 };
182
183 let lines = vec![
184 Line::from(""),
185 Line::from(Span::styled(
186 format!(
187 " This will create {} commits ({}).",
188 pending.count, strategy_name
189 ),
190 Style::default()
191 .fg(Color::Yellow)
192 .add_modifier(Modifier::BOLD),
193 )),
194 Line::from(""),
195 Line::from(Span::raw(" Do you want to proceed?")),
196 Line::from(""),
197 Line::from(vec![
198 Span::styled("Enter ", Style::default().fg(Color::Cyan)),
199 Span::raw("Confirm "),
200 Span::styled("Esc ", Style::default().fg(Color::Cyan)),
201 Span::raw("Cancel"),
202 ])
203 .alignment(Alignment::Center),
204 Line::from(""),
205 ];
206
207 render_centered_dialog(frame, " Confirm Split ", Color::Yellow, 52, lines);
208}