diff --git a/crates/op-editor-ui/src/widgets/agent_settings_images.rs b/crates/op-editor-ui/src/widgets/agent_settings_images.rs index e9c46f794..804f0580c 100644 --- a/crates/op-editor-ui/src/widgets/agent_settings_images.rs +++ b/crates/op-editor-ui/src/widgets/agent_settings_images.rs @@ -33,6 +33,7 @@ const PROFILE_ROW_H: f32 = 32.0; const PROFILE_ROW_GAP: f32 = 6.0; const ACTIVE_DOT: f32 = 14.0; const DELETE_W: f32 = 24.0; +const CHEVRON_W: f32 = 24.0; const PROFILE_FORM_TOP: f32 = 40.0; const PROFILE_FIELD_H: f32 = 24.0; const PROFILE_TEST_BTN_W: f32 = 56.0; @@ -184,6 +185,16 @@ fn profile_remove_rect(row: Rect) -> Rect { } } +fn profile_chevron_rect(row: Rect) -> Rect { + Rect { + origin: Point2D::new( + row.origin.x + row.size.x - DELETE_W - CHEVRON_W, + row.origin.y + (PROFILE_ROW_H - CHEVRON_W) / 2.0, + ), + size: Point2D::new(CHEVRON_W, CHEVRON_W), + } +} + fn profile_header_rect(row: Rect) -> Rect { Rect { origin: row.origin, @@ -584,11 +595,25 @@ fn paint_profile_row( cx.backend.draw_text( &provider_lay, Point2D::new( - row.origin.x + row.size.x - DELETE_W - 12.0 - provider_w, + row.origin.x + row.size.x - DELETE_W - CHEVRON_W - 12.0 - provider_w, row.origin.y + 20.0, ), ); + let chevron = profile_chevron_rect(row); + draw_icon( + cx.backend, + if editing { + Icon::ChevronDown + } else { + Icon::ChevronRight + }, + Point2D::new(chevron.origin.x + 4.0, chevron.origin.y + 6.0), + 12.0, + theme.muted_foreground, + 1.5, + ); + draw_icon( cx.backend, Icon::Trash, diff --git a/crates/op-editor-ui/src/widgets/agent_settings_panel_tests.rs b/crates/op-editor-ui/src/widgets/agent_settings_panel_tests.rs index bb1bc1588..132512ec6 100644 --- a/crates/op-editor-ui/src/widgets/agent_settings_panel_tests.rs +++ b/crates/op-editor-ui/src/widgets/agent_settings_panel_tests.rs @@ -537,6 +537,36 @@ fn images_tab_profile_rows_expose_active_and_remove_targets() { ); } +#[test] +fn images_tab_profile_row_paints_expand_chevron_before_delete_like_ts() { + let mut state = EditorState::default(); + state.editor_ui.agent_settings.tab = AgentSettingsTab::Images; + state.editor_ui.agent_settings.add_image_gen_profile(); + let panel = AgentSettingsPanel::for_editor(&state); + let rect = panel.rect(1200.0, 800.0); + let content_x = rect.origin.x + 200.0 + 24.0; + let content_y = rect.origin.y + 24.0; + let content_w = rect.size.x - 200.0 - 48.0; + let gen_top = content_y + 36.0 + 24.0 + 28.0; + let row_y = gen_top + 36.0; + let chevron_origin = crate::Point2D::new(content_x + content_w - 44.0, row_y + 10.0); + + let mut backend = CaptureBackend::default(); + let mut cx = PaintCx { + backend: &mut backend, + }; + panel.paint(&mut cx, rect); + + assert!( + backend.icon_strokes.iter().any(|(at, size, _)| { + (*size - 12.0).abs() < 0.01 + && (at.x - chevron_origin.x).abs() < 0.01 + && (at.y - chevron_origin.y).abs() < 0.01 + }), + "profile rows should paint the TS expand/collapse chevron before the delete icon" + ); +} + #[test] fn images_tab_advanced_search_fields_are_focusable() { let mut state = EditorState::default();