This PR fixes an issue where extension operations would never show in the activity indicator despite this being implemented for ages. This happened because we were always returning `None` whenever the app has a global auto updater, which is always the case, so the code path for showing extension updates in the indicator could never be hit despite existing prior. Also slightly improves the messages shown for ongoing extension operations, as these were previously context unaware. While I was at this, I also quickly took a stab at cleaning up some remotely related stuff, namely: - The `AnimationExt` trait is now by default only implemented for anything that also implements `IntoElement`. This prevents `with_animation` from showing up for e.g. `u32` within the suggestions (finally). - Commonly used animations are now implemented in the `CommonAnimationExt` trait within the `ui` crate so the needed code does not always need to be copied and element IDs for the animations are truly unique. Relevant change here regarding the original issue is the change from the `return match` to just a `match` within the activitiy indicator, which solved the issue at hand. If we find this to be too noisy at some point, we can easily revisit, but I think this holds important enough information to be shown in the activity indicator, especially whilst developing extensions. Release Notes: - Extension installation and updates will now be shown in the activity indicator.
182 lines
5.4 KiB
Rust
182 lines
5.4 KiB
Rust
use std::sync::Arc;
|
|
|
|
use gpui::Transformation;
|
|
use gpui::{App, IntoElement, Rems, RenderOnce, Size, Styled, Window, svg};
|
|
use serde::{Deserialize, Serialize};
|
|
use strum::{EnumIter, EnumString, IntoStaticStr};
|
|
|
|
use crate::Color;
|
|
use crate::prelude::*;
|
|
use crate::traits::transformable::Transformable;
|
|
|
|
#[derive(
|
|
Debug, PartialEq, Eq, Copy, Clone, EnumIter, EnumString, IntoStaticStr, Serialize, Deserialize,
|
|
)]
|
|
#[strum(serialize_all = "snake_case")]
|
|
pub enum VectorName {
|
|
AcpGrid,
|
|
AcpLogo,
|
|
AcpLogoSerif,
|
|
AiGrid,
|
|
DebuggerGrid,
|
|
Grid,
|
|
ProTrialStamp,
|
|
ProUserStamp,
|
|
ZedLogo,
|
|
ZedXCopilot,
|
|
}
|
|
|
|
impl VectorName {
|
|
/// Returns the path to this vector image.
|
|
pub fn path(&self) -> Arc<str> {
|
|
let file_stem: &'static str = self.into();
|
|
format!("images/{file_stem}.svg").into()
|
|
}
|
|
}
|
|
|
|
/// A vector image, such as an SVG.
|
|
///
|
|
/// A [`Vector`] is different from an [`crate::Icon`] in that it is intended
|
|
/// to be displayed at a specific size, or series of sizes, rather
|
|
/// than conforming to the standard size of an icon.
|
|
#[derive(IntoElement, RegisterComponent)]
|
|
pub struct Vector {
|
|
path: Arc<str>,
|
|
color: Color,
|
|
size: Size<Rems>,
|
|
transformation: Transformation,
|
|
}
|
|
|
|
impl Vector {
|
|
/// Creates a new [`Vector`] image with the given [`VectorName`] and size.
|
|
pub fn new(vector: VectorName, width: Rems, height: Rems) -> Self {
|
|
Self {
|
|
path: vector.path(),
|
|
color: Color::default(),
|
|
size: Size { width, height },
|
|
transformation: Transformation::default(),
|
|
}
|
|
}
|
|
|
|
/// Creates a new [`Vector`] image where the width and height are the same.
|
|
pub fn square(vector: VectorName, size: Rems) -> Self {
|
|
Self::new(vector, size, size)
|
|
}
|
|
|
|
/// Sets the vector color.
|
|
pub fn color(mut self, color: Color) -> Self {
|
|
self.color = color;
|
|
self
|
|
}
|
|
|
|
/// Sets the vector size.
|
|
pub fn size(mut self, size: impl Into<Size<Rems>>) -> Self {
|
|
let size = size.into();
|
|
self.size = size;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Transformable for Vector {
|
|
fn transform(mut self, transformation: Transformation) -> Self {
|
|
self.transformation = transformation;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl RenderOnce for Vector {
|
|
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
|
let width = self.size.width;
|
|
let height = self.size.height;
|
|
|
|
svg()
|
|
// By default, prevent the SVG from stretching
|
|
// to fill its container.
|
|
.flex_none()
|
|
.w(width)
|
|
.h(height)
|
|
.path(self.path)
|
|
.text_color(self.color.color(cx))
|
|
.with_transformation(self.transformation)
|
|
}
|
|
}
|
|
|
|
impl Component for Vector {
|
|
fn scope() -> ComponentScope {
|
|
ComponentScope::Images
|
|
}
|
|
|
|
fn name() -> &'static str {
|
|
"Vector"
|
|
}
|
|
|
|
fn description() -> Option<&'static str> {
|
|
Some("A vector image component that can be displayed at specific sizes.")
|
|
}
|
|
|
|
fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
|
|
Some(
|
|
v_flex()
|
|
.gap_6()
|
|
.children(vec![
|
|
example_group_with_title(
|
|
"Basic Usage",
|
|
vec![
|
|
single_example(
|
|
"Default",
|
|
Vector::square(VectorName::ZedLogo, rems(8.)).into_any_element(),
|
|
),
|
|
single_example(
|
|
"Custom Size",
|
|
Vector::new(VectorName::ZedLogo, rems(12.), rems(6.))
|
|
.into_any_element(),
|
|
),
|
|
],
|
|
),
|
|
example_group_with_title(
|
|
"Colored",
|
|
vec![
|
|
single_example(
|
|
"Accent Color",
|
|
Vector::square(VectorName::ZedLogo, rems(8.))
|
|
.color(Color::Accent)
|
|
.into_any_element(),
|
|
),
|
|
single_example(
|
|
"Error Color",
|
|
Vector::square(VectorName::ZedLogo, rems(8.))
|
|
.color(Color::Error)
|
|
.into_any_element(),
|
|
),
|
|
],
|
|
),
|
|
example_group_with_title(
|
|
"Different Vectors",
|
|
vec![
|
|
single_example(
|
|
"Zed Logo",
|
|
Vector::square(VectorName::ZedLogo, rems(8.)).into_any_element(),
|
|
),
|
|
single_example(
|
|
"Zed X Copilot",
|
|
Vector::square(VectorName::ZedXCopilot, rems(8.))
|
|
.into_any_element(),
|
|
),
|
|
],
|
|
),
|
|
])
|
|
.into_any_element(),
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn vector_path() {
|
|
assert_eq!(VectorName::ZedLogo.path().as_ref(), "images/zed_logo.svg");
|
|
}
|
|
}
|