Files
zed/crates/project/src/invalid_item_view.rs
Kirill Bulatov bc0bace81f Add basic ico support (#40822)
Closes https://github.com/zed-industries/zed/discussions/40763

<img width="867" height="1088" alt="Screenshot 2025-10-21 at 23 14 47"
src="https://github.com/user-attachments/assets/d691fb2a-afc6-4445-a335-054ef164e0d3"
/>

Also improves error handling on image open failure:

<img width="864" height="1083" alt="Screenshot 2025-10-21 at 23 14 30"
src="https://github.com/user-attachments/assets/d5388b61-995f-441b-b375-ad5136d1533b"
/>


Release Notes:

- Added basic ico support, improved unsupported image handling
2025-10-22 12:07:32 +03:00

119 lines
3.7 KiB
Rust

use std::{path::Path, sync::Arc};
use gpui::{EventEmitter, FocusHandle, Focusable};
use ui::{
App, Button, ButtonCommon, ButtonStyle, Clickable, Context, FluentBuilder, InteractiveElement,
KeyBinding, Label, LabelCommon, LabelSize, ParentElement, Render, SharedString, Styled as _,
Window, h_flex, v_flex,
};
use zed_actions::workspace::OpenWithSystem;
use crate::Item;
/// A view to display when a certain buffer fails to open.
#[derive(Debug)]
pub struct InvalidItemView {
/// Which path was attempted to open.
pub abs_path: Arc<Path>,
/// An error message, happened when opening the buffer.
pub error: SharedString,
is_local: bool,
focus_handle: FocusHandle,
}
impl InvalidItemView {
pub fn new(
abs_path: &Path,
is_local: bool,
e: &anyhow::Error,
_: &mut Window,
cx: &mut App,
) -> Self {
Self {
is_local,
abs_path: Arc::from(abs_path),
error: format!("{}", e.root_cause()).into(),
focus_handle: cx.focus_handle(),
}
}
}
impl Item for InvalidItemView {
type Event = ();
fn tab_content_text(&self, mut detail: usize, _: &App) -> SharedString {
// Ensure we always render at least the filename.
detail += 1;
let path = self.abs_path.as_ref();
let mut prefix = path;
while detail > 0 {
if let Some(parent) = prefix.parent() {
prefix = parent;
detail -= 1;
} else {
break;
}
}
let path = if detail > 0 {
path
} else {
path.strip_prefix(prefix).unwrap_or(path)
};
SharedString::new(path.to_string_lossy())
}
}
impl EventEmitter<()> for InvalidItemView {}
impl Focusable for InvalidItemView {
fn focus_handle(&self, _: &App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for InvalidItemView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl gpui::IntoElement {
let abs_path = self.abs_path.clone();
v_flex()
.size_full()
.track_focus(&self.focus_handle(cx))
.flex_none()
.justify_center()
.overflow_hidden()
.key_context("InvalidBuffer")
.child(
h_flex().size_full().justify_center().child(
v_flex()
.justify_center()
.gap_2()
.child(h_flex().justify_center().child("Could not open file"))
.child(
h_flex()
.justify_center()
.child(Label::new(self.error.clone()).size(LabelSize::Small)),
)
.when(self.is_local, |contents| {
contents.child(
h_flex().justify_center().child(
Button::new("open-with-system", "Open in Default App")
.on_click(move |_, _, cx| {
cx.open_with_system(&abs_path);
})
.style(ButtonStyle::Outlined)
.key_binding(KeyBinding::for_action(
&OpenWithSystem,
window,
cx,
)),
),
)
}),
),
)
}
}