//! Header layout used when the `GitOperationsInCodeReview` feature flag is //! enabled. This replaces the legacy header (which lives in the parent module) //! with a simplified layout: the diff-mode dropdown on the left, and file-nav / //! overflow / maximize buttons on the right. //! //! Separated into its own module so the two codepaths are easy to distinguish. use crate::code_review::code_review_view::{ CodeReviewAction, CodeReviewHeaderFields, PrimaryGitActionMode, }; use crate::code_review::diff_selector::DiffSelector; use crate::menu::Menu; use crate::view_components::action_button::ActionButton; use pathfinder_geometry::vector::vec2f; use warp_core::features::FeatureFlag; use warpui::elements::{ ChildAnchor, ChildView, Clipped, ConstrainedBox, Container, CrossAxisAlignment, Flex, MainAxisAlignment, MainAxisSize, OffsetPositioning, ParentAnchor, ParentElement, ParentOffsetBounds, Shrinkable, Stack, }; use warpui::{Element, ViewHandle}; use crate::appearance::Appearance; use super::CodeReviewHeader; impl CodeReviewHeader { /// Entry-point for the new header layout (feature-flagged behind /// `GitOperationsInCodeReview`). Renders a single row: diff-mode dropdown /// on the left, action buttons on the right. pub fn render_new( &self, appearance: &Appearance, code_review_header_fields: &CodeReviewHeaderFields, ) -> Box { let mut right_section = Flex::row() .with_main_axis_alignment(MainAxisAlignment::End) .with_cross_axis_alignment(CrossAxisAlignment::Center); if let Some(git_button) = Self::render_git_operations_button(code_review_header_fields) { right_section.add_child(git_button); } if let Some(nav_button) = &code_review_header_fields.file_nav_button { right_section.add_child(Self::render_file_nav_button(nav_button)); } if code_review_header_fields.has_header_menu_items { right_section.add_child(self.render_new_header_dropdown_button( &code_review_header_fields.header_dropdown_button, &code_review_header_fields.header_menu, code_review_header_fields.header_menu_open, )); } if code_review_header_fields.is_in_split_pane { right_section = right_section.with_child(self.render_maximize_pane_button( &code_review_header_fields.maximize_button, appearance, )); } let row = Clipped::new( Shrinkable::new( 1., Flex::row() .with_main_axis_alignment(MainAxisAlignment::SpaceBetween) .with_main_axis_size(MainAxisSize::Max) .with_cross_axis_alignment(CrossAxisAlignment::Center) .with_child(Self::render_diff_mode_dropdown( &code_review_header_fields.diff_selector, )) .with_child(right_section.finish()) .finish(), ) .finish(), ) .finish(); Container::new(row).with_margin_bottom(8.).finish() } /// Renders the diff target selector in the left section of the header. fn render_diff_mode_dropdown(diff_selector: &ViewHandle) -> Box { Container::new(ChildView::new(diff_selector).finish()) .with_margin_right(8.) .finish() } fn render_file_nav_button(button: &ViewHandle) -> Box { ConstrainedBox::new(ChildView::new(button).finish()) .with_height(warp_core::ui::icons::ICON_DIMENSIONS) .with_width(warp_core::ui::icons::ICON_DIMENSIONS) .finish() } fn render_git_operations_button( code_review_header_fields: &CodeReviewHeaderFields, ) -> Option> { if !FeatureFlag::GitOperationsInCodeReview.is_enabled() { return None; } let mut row = Flex::row().with_child( ChildView::new(&code_review_header_fields.git_primary_action_button).finish(), ); if matches!( code_review_header_fields.primary_git_action_mode, PrimaryGitActionMode::Commit | PrimaryGitActionMode::Push ) { row.add_child( ChildView::new(&code_review_header_fields.git_operations_chevron).finish(), ); } let button_row = Container::new(row.finish()).with_margin_right(4.).finish(); let mut stack = Stack::new().with_child(button_row); if code_review_header_fields.git_operations_menu_open { stack.add_positioned_overlay_child( ChildView::new(&code_review_header_fields.git_operations_menu).finish(), OffsetPositioning::offset_from_parent( vec2f(0., 0.), ParentOffsetBounds::WindowByPosition, ParentAnchor::BottomRight, ChildAnchor::TopRight, ), ); } Some(stack.finish()) } /// Like `render_header_dropdown_button` but without `margin_left(4.)`, /// matching the tighter spacing of the new header layout. fn render_new_header_dropdown_button( &self, header_dropdown_button: &ViewHandle, header_menu: &ViewHandle>, header_menu_open: bool, ) -> Box { let button_container = Container::new( ConstrainedBox::new(ChildView::new(header_dropdown_button).finish()) .with_height(warp_core::ui::icons::ICON_DIMENSIONS) .with_width(warp_core::ui::icons::ICON_DIMENSIONS) .finish(), ) .finish(); let mut stack = Stack::new().with_child(button_container); if header_menu_open { stack.add_positioned_overlay_child( ChildView::new(header_menu).finish(), OffsetPositioning::offset_from_parent( vec2f(0., 0.), ParentOffsetBounds::WindowByPosition, ParentAnchor::BottomRight, ChildAnchor::TopRight, ), ); } stack.finish() } }