aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 20:12:05 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 20:12:05 +0300
commit42ec7221310a4193f2a3717e2ea557c604dd07ae (patch)
tree614688c2f3a17f7ae32077f4dd5692d00f90a943 /src/ui
parent09c0dabfb51d8bc48b450d84958d19b1b647d77a (diff)
feat: gate kimi integration install behind minimum agent version
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/settings.rs93
1 files changed, 61 insertions, 32 deletions
diff --git a/src/ui/settings.rs b/src/ui/settings.rs
index d17ba4ed..8975d6f3 100644
--- a/src/ui/settings.rs
+++ b/src/ui/settings.rs
@@ -18,11 +18,26 @@ use crate::{
config::ToastDelivery,
};
+pub(crate) const SETTINGS_POPUP_WIDTH: u16 = 76;
+pub(crate) const SETTINGS_POPUP_BASE_HEIGHT: u16 = 22;
+
+pub(crate) fn settings_popup_height(app: &AppState) -> u16 {
+ if app.settings.section != crate::app::state::SettingsSection::Integrations {
+ return SETTINGS_POPUP_BASE_HEIGHT;
+ }
+ let list_rows = app.integration_recommendations.len().max(1) as u16;
+ let footer_rows = integrations_footer_height(app, SETTINGS_POPUP_WIDTH - 2);
+ // borders 2 + header 3 + stack gaps 2 + modal footer 2
+ // + section title 1 + description 2 + spacers 2
+ (14 + list_rows + footer_rows).max(SETTINGS_POPUP_BASE_HEIGHT)
+}
+
pub(super) fn render_settings_overlay(app: &AppState, frame: &mut Frame, area: Rect) {
use crate::app::state::SettingsSection;
let p = &app.palette;
- let Some(popup) = centered_popup_rect(area, 76, 22) else {
+ let Some(popup) = centered_popup_rect(area, SETTINGS_POPUP_WIDTH, settings_popup_height(app))
+ else {
return;
};
@@ -239,15 +254,58 @@ pub(crate) fn settings_button_rects(
(Some(rects[0]), rects[1])
}
+fn integrations_footer_paragraph(app: &AppState) -> Paragraph<'static> {
+ let p = &app.palette;
+ let mut footer_lines = Vec::new();
+ if !app.integration_install_messages.is_empty() {
+ for message in &app.integration_install_messages {
+ footer_lines.push(Line::from(Span::styled(
+ format!(" {message}"),
+ Style::default().fg(p.overlay1),
+ )));
+ }
+ } else {
+ let found_any = app.integration_recommendations.iter().any(|item| {
+ item.available || item.state != crate::integration::IntegrationStatusKind::NotInstalled
+ });
+ let hint = if app
+ .integration_recommendations
+ .iter()
+ .any(crate::integration::IntegrationRecommendation::needs_install)
+ {
+ " press install to add available or outdated integrations"
+ } else if found_any {
+ " all detected integrations are installed"
+ } else {
+ " no supported agent CLIs found on PATH"
+ };
+ footer_lines.push(Line::from(Span::styled(
+ hint.to_string(),
+ Style::default().fg(p.overlay1),
+ )));
+ }
+ Paragraph::new(footer_lines).wrap(ratatui::widgets::Wrap { trim: false })
+}
+
+fn integrations_footer_height(app: &AppState, width: u16) -> u16 {
+ (integrations_footer_paragraph(app).line_count(width) as u16).min(6)
+}
+
fn render_settings_integrations(app: &AppState, frame: &mut Frame, area: Rect) {
let p = &app.palette;
+
+ let footer = integrations_footer_paragraph(app);
+ let footer_height = integrations_footer_height(app, area.width);
+
let rows = Layout::vertical([
Constraint::Length(1),
Constraint::Length(2),
Constraint::Length(1),
Constraint::Min(0),
+ Constraint::Length(1),
+ Constraint::Length(footer_height),
])
- .areas::<4>(area);
+ .areas::<6>(area);
frame.render_widget(
Paragraph::new("agent integrations")
@@ -298,37 +356,8 @@ fn render_settings_integrations(app: &AppState, frame: &mut Frame, area: Rect) {
)));
}
- if !app.integration_install_messages.is_empty() {
- lines.push(Line::from(""));
- for message in &app.integration_install_messages {
- lines.push(Line::from(Span::styled(
- format!(" {message}"),
- Style::default().fg(p.overlay1),
- )));
- }
- } else {
- lines.push(Line::from(""));
- let found_any = app.integration_recommendations.iter().any(|item| {
- item.available || item.state != crate::integration::IntegrationStatusKind::NotInstalled
- });
- let hint = if app
- .integration_recommendations
- .iter()
- .any(crate::integration::IntegrationRecommendation::needs_install)
- {
- " press install to add available or outdated integrations"
- } else if found_any {
- " all detected integrations are installed"
- } else {
- " no supported agent CLIs found on PATH"
- };
- lines.push(Line::from(Span::styled(
- hint,
- Style::default().fg(p.overlay1),
- )));
- }
-
frame.render_widget(Paragraph::new(lines), rows[3]);
+ frame.render_widget(footer, rows[5]);
}
fn render_settings_theme(app: &AppState, frame: &mut Frame, area: Rect) {