editor: Render dirty and conflict markers in multibuffer headers (#36489)

Release Notes:

- Added rendering of status indicators for multi buffer headers
This commit is contained in:
Lukas Wirth 2025-08-19 18:43:42 +02:00 committed by GitHub
parent 43b4363b34
commit 013eaaeadd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 21 additions and 10 deletions

View file

@ -82,7 +82,7 @@ use sum_tree::Bias;
use text::{BufferId, SelectionGoal}; use text::{BufferId, SelectionGoal};
use theme::{ActiveTheme, Appearance, BufferLineHeight, PlayerColor}; use theme::{ActiveTheme, Appearance, BufferLineHeight, PlayerColor};
use ui::{ use ui::{
ButtonLike, ContextMenu, KeyBinding, POPOVER_Y_PADDING, Tooltip, h_flex, prelude::*, ButtonLike, ContextMenu, Indicator, KeyBinding, POPOVER_Y_PADDING, Tooltip, h_flex, prelude::*,
right_click_menu, right_click_menu,
}; };
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
@ -3563,9 +3563,8 @@ impl EditorElement {
cx: &mut App, cx: &mut App,
) -> impl IntoElement { ) -> impl IntoElement {
let editor = self.editor.read(cx); let editor = self.editor.read(cx);
let file_status = editor let multi_buffer = editor.buffer.read(cx);
.buffer let file_status = multi_buffer
.read(cx)
.all_diff_hunks_expanded() .all_diff_hunks_expanded()
.then(|| { .then(|| {
editor editor
@ -3575,6 +3574,17 @@ impl EditorElement {
.status_for_buffer_id(for_excerpt.buffer_id, cx) .status_for_buffer_id(for_excerpt.buffer_id, cx)
}) })
.flatten(); .flatten();
let indicator = multi_buffer
.buffer(for_excerpt.buffer_id)
.and_then(|buffer| {
let buffer = buffer.read(cx);
let indicator_color = match (buffer.has_conflict(), buffer.is_dirty()) {
(true, _) => Some(Color::Warning),
(_, true) => Some(Color::Accent),
(false, false) => None,
};
indicator_color.map(|indicator_color| Indicator::dot().color(indicator_color))
});
let include_root = editor let include_root = editor
.project .project
@ -3683,6 +3693,7 @@ impl EditorElement {
}) })
.take(1), .take(1),
) )
.children(indicator)
.child( .child(
h_flex() h_flex()
.cursor_pointer() .cursor_pointer()

View file

@ -395,11 +395,11 @@ impl DivInspector {
.zip(self.rust_completion_replace_range.as_ref()) .zip(self.rust_completion_replace_range.as_ref())
{ {
let before_text = snapshot let before_text = snapshot
.text_for_range(0..completion_range.start.to_offset(&snapshot)) .text_for_range(0..completion_range.start.to_offset(snapshot))
.collect::<String>(); .collect::<String>();
let after_text = snapshot let after_text = snapshot
.text_for_range( .text_for_range(
completion_range.end.to_offset(&snapshot) completion_range.end.to_offset(snapshot)
..snapshot.clip_offset(usize::MAX, Bias::Left), ..snapshot.clip_offset(usize::MAX, Bias::Left),
) )
.collect::<String>(); .collect::<String>();
@ -702,10 +702,10 @@ impl CompletionProvider for RustStyleCompletionProvider {
} }
fn completion_replace_range(snapshot: &BufferSnapshot, anchor: &Anchor) -> Option<Range<Anchor>> { fn completion_replace_range(snapshot: &BufferSnapshot, anchor: &Anchor) -> Option<Range<Anchor>> {
let point = anchor.to_point(&snapshot); let point = anchor.to_point(snapshot);
let offset = point.to_offset(&snapshot); let offset = point.to_offset(snapshot);
let line_start = Point::new(point.row, 0).to_offset(&snapshot); let line_start = Point::new(point.row, 0).to_offset(snapshot);
let line_end = Point::new(point.row, snapshot.line_len(point.row)).to_offset(&snapshot); let line_end = Point::new(point.row, snapshot.line_len(point.row)).to_offset(snapshot);
let mut lines = snapshot.text_for_range(line_start..line_end).lines(); let mut lines = snapshot.text_for_range(line_start..line_end).lines();
let line = lines.next()?; let line = lines.next()?;