| 174 | } |
| 175 | |
| 176 | fn render_footer(&self, frame: &mut Frame, area: Rect) { |
| 177 | if area.width == 0 || area.height == 0 { |
| 178 | return; |
| 179 | } |
| 180 | let theme = self.context.theme.read(); |
| 181 | let directory = self.context.directory.read(); |
| 182 | let mcp_servers = self.context.mcp_servers.read(); |
| 183 | |
| 184 | let horizontal_padding = 2u16.min(area.width / 2); |
| 185 | let vertical_padding = if area.height >= 3 { 1 } else { 0 }; |
| 186 | let content_area = Rect { |
| 187 | x: area.x.saturating_add(horizontal_padding), |
| 188 | y: area.y.saturating_add(vertical_padding), |
| 189 | width: area |
| 190 | .width |
| 191 | .saturating_sub(horizontal_padding.saturating_mul(2)), |
| 192 | height: area |
| 193 | .height |
| 194 | .saturating_sub(vertical_padding.saturating_mul(2)), |
| 195 | }; |
| 196 | if content_area.width == 0 || content_area.height == 0 { |
| 197 | return; |
| 198 | } |
| 199 | |
| 200 | let connected_count = mcp_servers |
| 201 | .iter() |
| 202 | .filter(|s| matches!(s.status, McpConnectionStatus::Connected)) |
| 203 | .count(); |
| 204 | |
| 205 | let mut spans: Vec<Span> = Vec::new(); |
| 206 | |
| 207 | // Left: directory |
| 208 | let dir_text = directory.to_string(); |
| 209 | spans.push(Span::styled( |
| 210 | dir_text.clone(), |
| 211 | Style::default().fg(theme.text_muted), |
| 212 | )); |
| 213 | |
| 214 | // Middle: MCP status (only when servers exist) |
| 215 | let mcp_text = if !mcp_servers.is_empty() { |
| 216 | let has_errors = mcp_servers.iter().any(|s| { |
| 217 | matches!( |
| 218 | s.status, |
| 219 | McpConnectionStatus::Failed | McpConnectionStatus::NeedsClientRegistration |
| 220 | ) |
| 221 | }); |
| 222 | let dot_color = if has_errors { |
| 223 | theme.error |
| 224 | } else if connected_count > 0 { |
| 225 | theme.success |
| 226 | } else { |
| 227 | theme.text_muted |
| 228 | }; |
| 229 | let label = format!("{} MCP", connected_count); |
| 230 | Some((dot_color, label)) |
| 231 | } else { |
| 232 | None |
| 233 | }; |