1use super::super::app::{CONFIG_FIELDS, CONFIG_GLOBAL_FIELDS, ChatApp};
2use super::super::handler::{config_field_label, config_field_value};
3use ratatui::{
4 layout::Rect,
5 style::{Modifier, Style},
6 text::{Line, Span},
7 widgets::{Block, Borders, Paragraph},
8};
9
10pub fn draw_config_screen(f: &mut ratatui::Frame, area: Rect, app: &mut ChatApp) {
11 let t = &app.theme;
12 let bg = t.bg_title;
13 let total_provider_fields = CONFIG_FIELDS.len();
14
15 let mut lines: Vec<Line> = Vec::new();
16 lines.push(Line::from(""));
17
18 lines.push(Line::from(vec![Span::styled(
19 " ⚙️ 模型配置",
20 Style::default()
21 .fg(t.config_title)
22 .add_modifier(Modifier::BOLD),
23 )]));
24 lines.push(Line::from(""));
25
26 let provider_count = app.agent_config.providers.len();
27 if provider_count > 0 {
28 let mut tab_spans: Vec<Span> = vec![Span::styled(" ", Style::default())];
29 for (i, p) in app.agent_config.providers.iter().enumerate() {
30 let is_current = i == app.config_provider_idx;
31 let is_active = i == app.agent_config.active_index;
32 let marker = if is_active { "● " } else { "○ " };
33 let label = format!(" {}{} ", marker, p.name);
34 if is_current {
35 tab_spans.push(Span::styled(
36 label,
37 Style::default()
38 .fg(t.config_tab_active_fg)
39 .bg(t.config_tab_active_bg)
40 .add_modifier(Modifier::BOLD),
41 ));
42 } else {
43 tab_spans.push(Span::styled(
44 label,
45 Style::default().fg(t.config_tab_inactive),
46 ));
47 }
48 if i < provider_count - 1 {
49 tab_spans.push(Span::styled(" │ ", Style::default().fg(t.separator)));
50 }
51 }
52 tab_spans.push(Span::styled(
53 " (● = 活跃模型, Tab 切换, s 设为活跃)",
54 Style::default().fg(t.config_dim),
55 ));
56 lines.push(Line::from(tab_spans));
57 } else {
58 lines.push(Line::from(Span::styled(
59 " (无 Provider,按 a 新增)",
60 Style::default().fg(t.config_toggle_off),
61 )));
62 }
63 lines.push(Line::from(""));
64
65 lines.push(Line::from(Span::styled(
66 " ─────────────────────────────────────────",
67 Style::default().fg(t.separator),
68 )));
69 lines.push(Line::from(""));
70
71 if provider_count > 0 {
72 lines.push(Line::from(Span::styled(
73 " 📦 Provider 配置",
74 Style::default()
75 .fg(t.config_section)
76 .add_modifier(Modifier::BOLD),
77 )));
78 lines.push(Line::from(""));
79
80 for i in 0..total_provider_fields {
81 let is_selected = app.config_field_idx == i;
82 let label = config_field_label(i);
83 let value = if app.config_editing && is_selected {
84 app.config_edit_buf.clone()
85 } else {
86 config_field_value(app, i)
87 };
88
89 let pointer = if is_selected { " ▸ " } else { " " };
90 let pointer_style = if is_selected {
91 Style::default().fg(t.config_pointer)
92 } else {
93 Style::default()
94 };
95 let label_style = if is_selected {
96 Style::default()
97 .fg(t.config_label_selected)
98 .add_modifier(Modifier::BOLD)
99 } else {
100 Style::default().fg(t.config_label)
101 };
102 let value_style = if app.config_editing && is_selected {
103 Style::default().fg(t.text_white).bg(t.config_edit_bg)
104 } else if is_selected {
105 Style::default().fg(t.text_white)
106 } else if CONFIG_FIELDS[i] == "api_key" {
107 Style::default().fg(t.config_api_key)
108 } else {
109 Style::default().fg(t.config_value)
110 };
111 let edit_indicator = if app.config_editing && is_selected {
112 " ✏️"
113 } else {
114 ""
115 };
116
117 lines.push(Line::from(vec![
118 Span::styled(pointer, pointer_style),
119 Span::styled(format!("{:<10}", label), label_style),
120 Span::styled(" ", Style::default()),
121 Span::styled(
122 if value.is_empty() {
123 "(空)".to_string()
124 } else {
125 value
126 },
127 value_style,
128 ),
129 Span::styled(edit_indicator, Style::default()),
130 ]));
131 }
132 }
133
134 lines.push(Line::from(""));
135 lines.push(Line::from(Span::styled(
136 " ─────────────────────────────────────────",
137 Style::default().fg(t.separator),
138 )));
139 lines.push(Line::from(""));
140
141 lines.push(Line::from(Span::styled(
142 " 🌐 全局配置",
143 Style::default()
144 .fg(t.config_section)
145 .add_modifier(Modifier::BOLD),
146 )));
147 lines.push(Line::from(""));
148
149 for i in 0..CONFIG_GLOBAL_FIELDS.len() {
150 let field_idx = total_provider_fields + i;
151 let is_selected = app.config_field_idx == field_idx;
152 let label = config_field_label(field_idx);
153 let value = if app.config_editing && is_selected {
154 app.config_edit_buf.clone()
155 } else {
156 config_field_value(app, field_idx)
157 };
158
159 let pointer = if is_selected { " ▸ " } else { " " };
160 let pointer_style = if is_selected {
161 Style::default().fg(t.config_pointer)
162 } else {
163 Style::default()
164 };
165 let label_style = if is_selected {
166 Style::default()
167 .fg(t.config_label_selected)
168 .add_modifier(Modifier::BOLD)
169 } else {
170 Style::default().fg(t.config_label)
171 };
172 let value_style = if app.config_editing && is_selected {
173 Style::default().fg(t.text_white).bg(t.config_edit_bg)
174 } else if is_selected {
175 Style::default().fg(t.text_white)
176 } else {
177 Style::default().fg(t.config_value)
178 };
179 let edit_indicator = if app.config_editing && is_selected {
180 " ✏️"
181 } else {
182 ""
183 };
184
185 if CONFIG_GLOBAL_FIELDS[i] == "stream_mode" {
186 let toggle_on = app.agent_config.stream_mode;
187 let toggle_style = if toggle_on {
188 Style::default()
189 .fg(t.config_toggle_on)
190 .add_modifier(Modifier::BOLD)
191 } else {
192 Style::default().fg(t.config_toggle_off)
193 };
194 let toggle_text = if toggle_on {
195 "● 开启"
196 } else {
197 "○ 关闭"
198 };
199 lines.push(Line::from(vec![
200 Span::styled(pointer, pointer_style),
201 Span::styled(format!("{:<10}", label), label_style),
202 Span::styled(" ", Style::default()),
203 Span::styled(toggle_text, toggle_style),
204 Span::styled(
205 if is_selected { " (Enter 切换)" } else { "" },
206 Style::default().fg(t.config_dim),
207 ),
208 ]));
209 } else if CONFIG_GLOBAL_FIELDS[i] == "theme" {
210 let theme_name = app.agent_config.theme.display_name();
211 lines.push(Line::from(vec![
212 Span::styled(pointer, pointer_style),
213 Span::styled(format!("{:<10}", label), label_style),
214 Span::styled(" ", Style::default()),
215 Span::styled(
216 format!("🎨 {}", theme_name),
217 Style::default()
218 .fg(t.config_toggle_on)
219 .add_modifier(Modifier::BOLD),
220 ),
221 Span::styled(
222 if is_selected { " (Enter 切换)" } else { "" },
223 Style::default().fg(t.config_dim),
224 ),
225 ]));
226 } else {
227 lines.push(Line::from(vec![
228 Span::styled(pointer, pointer_style),
229 Span::styled(format!("{:<10}", label), label_style),
230 Span::styled(" ", Style::default()),
231 Span::styled(
232 if value.is_empty() {
233 "(空)".to_string()
234 } else {
235 value
236 },
237 value_style,
238 ),
239 Span::styled(edit_indicator, Style::default()),
240 ]));
241 }
242 }
243
244 lines.push(Line::from(""));
245 lines.push(Line::from(""));
246
247 lines.push(Line::from(Span::styled(
248 " ─────────────────────────────────────────",
249 Style::default().fg(t.separator),
250 )));
251 lines.push(Line::from(""));
252 lines.push(Line::from(vec![
253 Span::styled(" ", Style::default()),
254 Span::styled(
255 "↑↓/jk",
256 Style::default()
257 .fg(t.config_hint_key)
258 .add_modifier(Modifier::BOLD),
259 ),
260 Span::styled(" 切换字段 ", Style::default().fg(t.config_hint_desc)),
261 Span::styled(
262 "Enter",
263 Style::default()
264 .fg(t.config_hint_key)
265 .add_modifier(Modifier::BOLD),
266 ),
267 Span::styled(" 编辑 ", Style::default().fg(t.config_hint_desc)),
268 Span::styled(
269 "Tab/←→",
270 Style::default()
271 .fg(t.config_hint_key)
272 .add_modifier(Modifier::BOLD),
273 ),
274 Span::styled(" 切换 Provider ", Style::default().fg(t.config_hint_desc)),
275 Span::styled(
276 "a",
277 Style::default()
278 .fg(t.config_hint_key)
279 .add_modifier(Modifier::BOLD),
280 ),
281 Span::styled(" 新增 ", Style::default().fg(t.config_hint_desc)),
282 Span::styled(
283 "d",
284 Style::default()
285 .fg(t.config_hint_key)
286 .add_modifier(Modifier::BOLD),
287 ),
288 Span::styled(" 删除 ", Style::default().fg(t.config_hint_desc)),
289 Span::styled(
290 "s",
291 Style::default()
292 .fg(t.config_hint_key)
293 .add_modifier(Modifier::BOLD),
294 ),
295 Span::styled(" 设为活跃 ", Style::default().fg(t.config_hint_desc)),
296 Span::styled(
297 "Esc",
298 Style::default()
299 .fg(t.config_hint_key)
300 .add_modifier(Modifier::BOLD),
301 ),
302 Span::styled(" 保存返回", Style::default().fg(t.config_hint_desc)),
303 ]));
304
305 let content = Paragraph::new(lines)
306 .block(
307 Block::default()
308 .borders(Borders::ALL)
309 .border_type(ratatui::widgets::BorderType::Rounded)
310 .border_style(Style::default().fg(t.border_config))
311 .title(Span::styled(
312 " ⚙️ 模型配置编辑 ",
313 Style::default()
314 .fg(t.config_label_selected)
315 .add_modifier(Modifier::BOLD),
316 ))
317 .style(Style::default().bg(bg)),
318 )
319 .scroll((0, 0));
320 f.render_widget(content, area);
321}