Add file icons to multibuffer view (#36836)

<img width="1988" height="1420" alt="multi-buffer-icons-git-diff"
src="https://github.com/user-attachments/assets/48f9722f-ca09-4aa7-ad7a-0b7e85f440d9"
/>

Unfortunately, `cargo format` decided to reformat everything. Probably,
because of hitting the right margin, no idea. The essence of this change
is the following:

```rust
.map(|path_header| {
    let filename = filename
        .map(SharedString::from)
        .unwrap_or_else(|| "untitled".into());
    let path = path::Path::new(filename.as_str());
    let icon =
        FileIcons::get_icon(path, cx).unwrap_or_default();
    let icon = Icon::from_path(icon).color(Color::Muted);

    let label = Label::new(filename).single_line().when_some(
        file_status,
        |el, status| {
            el.color(if status.is_conflicted() {
                Color::Conflict
            } else if status.is_modified() {
                Color::Modified
            } else if status.is_deleted() {
                Color::Disabled
            } else {
                Color::Created
            })
            .when(status.is_deleted(), |el| el.strikethrough())
        },
    );

    path_header.child(icon).child(label)
})
``` 

Release Notes:

- Added file icons to multi buffer view
This commit is contained in:
Aleksei Gusev 2025-08-24 19:57:12 +03:00 committed by GitHub
parent a79aef7bdd
commit 11545c669e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -74,7 +74,7 @@ use std::{
fmt::{self, Write},
iter, mem,
ops::{Deref, Range},
path::Path,
path::{self, Path},
rc::Rc,
sync::Arc,
time::{Duration, Instant},
@ -90,8 +90,8 @@ use unicode_segmentation::UnicodeSegmentation;
use util::post_inc;
use util::{RangeExt, ResultExt, debug_panic};
use workspace::{
CollaboratorId, OpenInTerminal, OpenTerminal, RevealInProjectPanel, Workspace, item::Item,
notifications::NotifyTaskExt,
CollaboratorId, ItemSettings, OpenInTerminal, OpenTerminal, RevealInProjectPanel, Workspace,
item::Item, notifications::NotifyTaskExt,
};
/// Determines what kinds of highlights should be applied to a lines background.
@ -3603,8 +3603,7 @@ impl EditorElement {
let focus_handle = editor.focus_handle(cx);
let colors = cx.theme().colors();
let header =
div()
let header = div()
.p_1()
.w_full()
.h(FILE_HEADER_HEIGHT as f32 * window.line_height())
@ -3710,14 +3709,23 @@ impl EditorElement {
.child(
h_flex()
.gap_2()
.child(
Label::new(
filename
.map(|path_header| {
let filename = filename
.map(SharedString::from)
.unwrap_or_else(|| "untitled".into()),
)
.single_line()
.when_some(file_status, |el, status| {
.unwrap_or_else(|| "untitled".into());
path_header
.when(ItemSettings::get_global(cx).file_icons, |el| {
let path = path::Path::new(filename.as_str());
let icon = FileIcons::get_icon(path, cx)
.unwrap_or_default();
let icon =
Icon::from_path(icon).color(Color::Muted);
el.child(icon)
})
.child(Label::new(filename).single_line().when_some(
file_status,
|el, status| {
el.color(if status.is_conflicted() {
Color::Conflict
} else if status.is_modified() {
@ -3727,9 +3735,12 @@ impl EditorElement {
} else {
Color::Created
})
.when(status.is_deleted(), |el| el.strikethrough())
}),
)
.when(status.is_deleted(), |el| {
el.strikethrough()
})
},
))
})
.when_some(parent_path, |then, path| {
then.child(div().child(path).text_color(
if file_status.is_some_and(FileStatus::is_deleted) {