Add placeholder git panel (#21894)
Adds a simple git placeholder panel for us to iterate from. Also includes a number of assets from the git prototyping branch that we will use. Note: This panel is staff flagged for now. Release Notes: - N/A
This commit is contained in:
parent
611abcadc0
commit
59afc27f03
26 changed files with 352 additions and 170 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -5169,6 +5169,17 @@ dependencies = [
|
|||
"util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "git_ui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gpui",
|
||||
"serde",
|
||||
"ui",
|
||||
"windows 0.58.0",
|
||||
"workspace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
|
@ -15994,6 +16005,7 @@ dependencies = [
|
|||
"futures 0.3.31",
|
||||
"git",
|
||||
"git_hosting_providers",
|
||||
"git_ui",
|
||||
"go_to_line",
|
||||
"gpui",
|
||||
"http_client",
|
||||
|
|
|
@ -142,6 +142,7 @@ members = [
|
|||
"crates/zed",
|
||||
"crates/zed_actions",
|
||||
"crates/zeta",
|
||||
"crates/git_ui",
|
||||
|
||||
#
|
||||
# Extensions
|
||||
|
@ -227,6 +228,7 @@ fs = { path = "crates/fs" }
|
|||
fsevent = { path = "crates/fsevent" }
|
||||
fuzzy = { path = "crates/fuzzy" }
|
||||
git = { path = "crates/git" }
|
||||
git_ui = { path = "crates/git_ui" }
|
||||
git_hosting_providers = { path = "crates/git_hosting_providers" }
|
||||
go_to_line = { path = "crates/go_to_line" }
|
||||
google_ai = { path = "crates/google_ai" }
|
||||
|
|
1
assets/icons/git_branch.svg
Normal file
1
assets/icons/git_branch.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-git-branch"><line x1="6" x2="6" y1="3" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
|
After Width: | Height: | Size: 348 B |
1
assets/icons/panel_left.svg
Normal file
1
assets/icons/panel_left.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-panel-left"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/></svg>
|
After Width: | Height: | Size: 289 B |
1
assets/icons/panel_right.svg
Normal file
1
assets/icons/panel_right.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-panel-right"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/></svg>
|
After Width: | Height: | Size: 291 B |
1
assets/icons/square_dot.svg
Normal file
1
assets/icons/square_dot.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-dot"><rect width="18" height="18" x="3" y="3" rx="2"/><circle cx="12" cy="12" r="1"/></svg>
|
After Width: | Height: | Size: 301 B |
1
assets/icons/square_minus.svg
Normal file
1
assets/icons/square_minus.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-minus"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M8 12h8"/></svg>
|
After Width: | Height: | Size: 291 B |
1
assets/icons/square_plus.svg
Normal file
1
assets/icons/square_plus.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-square-plus"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M8 12h8"/><path d="M12 8v8"/></svg>
|
After Width: | Height: | Size: 309 B |
|
@ -64,6 +64,11 @@ impl FeatureFlag for ZetaFeatureFlag {
|
|||
const NAME: &'static str = "zeta";
|
||||
}
|
||||
|
||||
pub struct GitUiFeatureFlag;
|
||||
impl FeatureFlag for GitUiFeatureFlag {
|
||||
const NAME: &'static str = "git-ui";
|
||||
}
|
||||
|
||||
pub struct Remoting {}
|
||||
impl FeatureFlag for Remoting {
|
||||
const NAME: &'static str = "remoting";
|
||||
|
|
25
crates/git_ui/Cargo.toml
Normal file
25
crates/git_ui/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "git_ui"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
name = "git_ui"
|
||||
path = "src/git_ui.rs"
|
||||
|
||||
[dependencies]
|
||||
gpui.workspace = true
|
||||
serde.workspace = true
|
||||
workspace.workspace = true
|
||||
ui.workspace = true
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
1
crates/git_ui/LICENSE-GPL
Symbolic link
1
crates/git_ui/LICENSE-GPL
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../LICENSE-GPL
|
181
crates/git_ui/src/git_panel.rs
Normal file
181
crates/git_ui/src/git_panel.rs
Normal file
|
@ -0,0 +1,181 @@
|
|||
use gpui::*;
|
||||
use ui::{prelude::*, Checkbox, Divider, DividerColor, ElevationIndex};
|
||||
use workspace::dock::{DockPosition, Panel, PanelEvent};
|
||||
use workspace::Workspace;
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.observe_new_views(
|
||||
|workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
|
||||
workspace.register_action(|workspace, _: &ToggleFocus, cx| {
|
||||
workspace.toggle_panel_focus::<GitPanel>(cx);
|
||||
});
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
}
|
||||
|
||||
actions!(git_panel, [Deploy, ToggleFocus]);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GitPanel {
|
||||
_workspace: WeakView<Workspace>,
|
||||
focus_handle: FocusHandle,
|
||||
width: Option<Pixels>,
|
||||
}
|
||||
|
||||
impl GitPanel {
|
||||
pub fn load(
|
||||
workspace: WeakView<Workspace>,
|
||||
cx: AsyncWindowContext,
|
||||
) -> Task<Result<View<Self>>> {
|
||||
cx.spawn(|mut cx| async move {
|
||||
workspace.update(&mut cx, |workspace, cx| {
|
||||
let workspace_handle = workspace.weak_handle();
|
||||
|
||||
cx.new_view(|cx| Self::new(workspace_handle, cx))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new(workspace: WeakView<Workspace>, cx: &mut ViewContext<Self>) -> Self {
|
||||
Self {
|
||||
_workspace: workspace,
|
||||
focus_handle: cx.focus_handle(),
|
||||
width: Some(px(360.)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_panel_header(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.h(px(32.))
|
||||
.items_center()
|
||||
.px_3()
|
||||
.bg(ElevationIndex::Surface.bg(cx))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(Checkbox::new("all-changes", true.into()).disabled(true))
|
||||
.child(div().text_buffer(cx).text_ui_sm(cx).child("0 changes")),
|
||||
)
|
||||
.child(div().flex_grow())
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new("discard-changes", IconName::Undo)
|
||||
.icon_size(IconSize::Small)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("stage-all", "Stage All")
|
||||
.label_size(LabelSize::Small)
|
||||
.layer(ElevationIndex::ElevatedSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.style(ButtonStyle::Filled)
|
||||
.disabled(true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn render_commit_editor(&self, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
div().w_full().h(px(140.)).px_2().pt_1().pb_2().child(
|
||||
v_flex()
|
||||
.h_full()
|
||||
.py_2p5()
|
||||
.px_3()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.font_buffer(cx)
|
||||
.text_ui_sm(cx)
|
||||
.text_color(cx.theme().colors().text_muted)
|
||||
.child("Add a message")
|
||||
.gap_1()
|
||||
.child(div().flex_grow())
|
||||
.child(
|
||||
h_flex().child(div().gap_1().flex_grow()).child(
|
||||
Button::new("commit", "Commit")
|
||||
.label_size(LabelSize::Small)
|
||||
.layer(ElevationIndex::ElevatedSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.style(ButtonStyle::Filled)
|
||||
.disabled(true),
|
||||
),
|
||||
)
|
||||
.cursor(CursorStyle::OperationNotAllowed)
|
||||
.opacity(0.5),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for GitPanel {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.key_context("GitPanel")
|
||||
.font_buffer(cx)
|
||||
.py_1()
|
||||
.id("git_panel")
|
||||
.track_focus(&self.focus_handle)
|
||||
.size_full()
|
||||
.overflow_hidden()
|
||||
.bg(ElevationIndex::Surface.bg(cx))
|
||||
.child(self.render_panel_header(cx))
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.h(px(8.))
|
||||
.child(Divider::horizontal_dashed().color(DividerColor::Border)),
|
||||
)
|
||||
.child(div().flex_1())
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.h(px(8.))
|
||||
.child(Divider::horizontal_dashed().color(DividerColor::Border)),
|
||||
)
|
||||
.child(self.render_commit_editor(cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl FocusableView for GitPanel {
|
||||
fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for GitPanel {}
|
||||
|
||||
impl Panel for GitPanel {
|
||||
fn persistent_name() -> &'static str {
|
||||
"GitPanel"
|
||||
}
|
||||
|
||||
fn position(&self, _cx: &gpui::WindowContext) -> DockPosition {
|
||||
DockPosition::Left
|
||||
}
|
||||
|
||||
fn position_is_valid(&self, position: DockPosition) -> bool {
|
||||
matches!(position, DockPosition::Left | DockPosition::Right)
|
||||
}
|
||||
|
||||
fn set_position(&mut self, _position: DockPosition, _cx: &mut ViewContext<Self>) {}
|
||||
|
||||
fn size(&self, _cx: &gpui::WindowContext) -> Pixels {
|
||||
self.width.unwrap_or(px(360.))
|
||||
}
|
||||
|
||||
fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
|
||||
self.width = size;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn icon(&self, _cx: &gpui::WindowContext) -> Option<ui::IconName> {
|
||||
Some(ui::IconName::GitBranch)
|
||||
}
|
||||
|
||||
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
|
||||
Some("Git Panel")
|
||||
}
|
||||
|
||||
fn toggle_action(&self) -> Box<dyn Action> {
|
||||
Box::new(ToggleFocus)
|
||||
}
|
||||
}
|
1
crates/git_ui/src/git_ui.rs
Normal file
1
crates/git_ui/src/git_ui.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod git_panel;
|
|
@ -445,7 +445,7 @@ impl ComponentPreview for Button {
|
|||
"A button allows users to take actions, and make choices, with a single tap."
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Styles",
|
||||
|
|
|
@ -118,7 +118,7 @@ impl ComponentPreview for Checkbox {
|
|||
"A checkbox lets people choose between a pair of opposing states, like enabled and disabled, using a different appearance to indicate each state."
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Default",
|
||||
|
@ -214,7 +214,7 @@ impl ComponentPreview for CheckboxWithLabel {
|
|||
"A checkbox with an associated label, allowing users to select an option while providing a descriptive text."
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![example_group(vec![
|
||||
single_example(
|
||||
"Unselected",
|
||||
|
|
|
@ -95,7 +95,7 @@ impl ComponentPreview for ContentGroup {
|
|||
ExampleLabelSide::Bottom
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![example_group(vec![
|
||||
single_example(
|
||||
"Default",
|
||||
|
|
|
@ -3,6 +3,13 @@ use gpui::{Hsla, IntoElement};
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum DividerStyle {
|
||||
Solid,
|
||||
Dashed,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum DividerDirection {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
|
@ -27,6 +34,7 @@ impl DividerColor {
|
|||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Divider {
|
||||
style: DividerStyle,
|
||||
direction: DividerDirection,
|
||||
color: DividerColor,
|
||||
inset: bool,
|
||||
|
@ -34,22 +42,17 @@ pub struct Divider {
|
|||
|
||||
impl RenderOnce for Divider {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
div()
|
||||
.map(|this| match self.direction {
|
||||
DividerDirection::Horizontal => {
|
||||
this.h_px().w_full().when(self.inset, |this| this.mx_1p5())
|
||||
}
|
||||
DividerDirection::Vertical => {
|
||||
this.w_px().h_full().when(self.inset, |this| this.my_1p5())
|
||||
}
|
||||
})
|
||||
.bg(self.color.hsla(cx))
|
||||
match self.style {
|
||||
DividerStyle::Solid => self.render_solid(cx).into_any_element(),
|
||||
DividerStyle::Dashed => self.render_dashed(cx).into_any_element(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Divider {
|
||||
pub fn horizontal() -> Self {
|
||||
Self {
|
||||
style: DividerStyle::Solid,
|
||||
direction: DividerDirection::Horizontal,
|
||||
color: DividerColor::default(),
|
||||
inset: false,
|
||||
|
@ -58,6 +61,25 @@ impl Divider {
|
|||
|
||||
pub fn vertical() -> Self {
|
||||
Self {
|
||||
style: DividerStyle::Solid,
|
||||
direction: DividerDirection::Vertical,
|
||||
color: DividerColor::default(),
|
||||
inset: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn horizontal_dashed() -> Self {
|
||||
Self {
|
||||
style: DividerStyle::Dashed,
|
||||
direction: DividerDirection::Horizontal,
|
||||
color: DividerColor::default(),
|
||||
inset: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertical_dashed() -> Self {
|
||||
Self {
|
||||
style: DividerStyle::Dashed,
|
||||
direction: DividerDirection::Vertical,
|
||||
color: DividerColor::default(),
|
||||
inset: false,
|
||||
|
@ -73,4 +95,49 @@ impl Divider {
|
|||
self.color = color;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn render_solid(self, cx: &WindowContext) -> impl IntoElement {
|
||||
div()
|
||||
.map(|this| match self.direction {
|
||||
DividerDirection::Horizontal => {
|
||||
this.h_px().w_full().when(self.inset, |this| this.mx_1p5())
|
||||
}
|
||||
DividerDirection::Vertical => {
|
||||
this.w_px().h_full().when(self.inset, |this| this.my_1p5())
|
||||
}
|
||||
})
|
||||
.bg(self.color.hsla(cx))
|
||||
}
|
||||
|
||||
// TODO: Use canvas or a shader here
|
||||
// This obviously is a short term approach
|
||||
pub fn render_dashed(self, cx: &WindowContext) -> impl IntoElement {
|
||||
let segment_count = 128;
|
||||
let segment_count_f = segment_count as f32;
|
||||
let segment_min_w = 6.;
|
||||
let base = match self.direction {
|
||||
DividerDirection::Horizontal => h_flex(),
|
||||
DividerDirection::Vertical => v_flex(),
|
||||
};
|
||||
let (w, h) = match self.direction {
|
||||
DividerDirection::Horizontal => (px(segment_min_w), px(1.)),
|
||||
DividerDirection::Vertical => (px(1.), px(segment_min_w)),
|
||||
};
|
||||
let color = self.color.hsla(cx);
|
||||
let total_min_w = segment_min_w * segment_count_f * 2.; // * 2 because of the gap
|
||||
|
||||
base.min_w(px(total_min_w))
|
||||
.map(|this| {
|
||||
if self.direction == DividerDirection::Horizontal {
|
||||
this.w_full().h_px()
|
||||
} else {
|
||||
this.w_px().h_full()
|
||||
}
|
||||
})
|
||||
.gap(px(segment_min_w))
|
||||
.overflow_hidden()
|
||||
.children(
|
||||
(0..segment_count).map(|_| div().flex_grow().flex_shrink_0().w(w).h(h).bg(color)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ impl ComponentPreview for Facepile {
|
|||
\n\nFacepiles are used to display a group of people or things,\
|
||||
such as a list of participants in a collaboration session."
|
||||
}
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let few_faces: [&'static str; 3] = [
|
||||
"https://avatars.githubusercontent.com/u/1714999?s=60&v=4",
|
||||
"https://avatars.githubusercontent.com/u/67129314?s=60&v=4",
|
||||
|
|
|
@ -200,6 +200,7 @@ pub enum IconName {
|
|||
GenericRestore,
|
||||
Github,
|
||||
Globe,
|
||||
GitBranch,
|
||||
Hash,
|
||||
HistoryRerun,
|
||||
Indicator,
|
||||
|
@ -224,6 +225,8 @@ pub enum IconName {
|
|||
Option,
|
||||
PageDown,
|
||||
PageUp,
|
||||
PanelLeft,
|
||||
PanelRight,
|
||||
Pencil,
|
||||
Person,
|
||||
PhoneIncoming,
|
||||
|
@ -267,6 +270,9 @@ pub enum IconName {
|
|||
SparkleFilled,
|
||||
Spinner,
|
||||
Split,
|
||||
SquareDot,
|
||||
SquareMinus,
|
||||
SquarePlus,
|
||||
Star,
|
||||
StarFilled,
|
||||
Stop,
|
||||
|
@ -497,7 +503,7 @@ impl RenderOnce for IconDecoration {
|
|||
}
|
||||
|
||||
impl ComponentPreview for IconDecoration {
|
||||
fn examples(cx: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let all_kinds = IconDecorationKind::iter().collect::<Vec<_>>();
|
||||
|
||||
let examples = all_kinds
|
||||
|
@ -539,7 +545,7 @@ impl RenderOnce for DecoratedIcon {
|
|||
}
|
||||
|
||||
impl ComponentPreview for DecoratedIcon {
|
||||
fn examples(cx: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
let icon_1 = Icon::new(IconName::FileDoc);
|
||||
let icon_2 = Icon::new(IconName::FileDoc);
|
||||
let icon_3 = Icon::new(IconName::FileDoc);
|
||||
|
@ -658,7 +664,7 @@ impl RenderOnce for IconWithIndicator {
|
|||
}
|
||||
|
||||
impl ComponentPreview for Icon {
|
||||
fn examples(_cx: &WindowContext) -> Vec<ComponentExampleGroup<Icon>> {
|
||||
fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Icon>> {
|
||||
let arrow_icons = vec![
|
||||
IconName::ArrowDown,
|
||||
IconName::ArrowLeft,
|
||||
|
|
|
@ -89,7 +89,7 @@ impl ComponentPreview for Indicator {
|
|||
"An indicator visually represents a status or state."
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group_with_title(
|
||||
"Types",
|
||||
|
|
|
@ -160,7 +160,7 @@ impl ComponentPreview for Table {
|
|||
ExampleLabelSide::Top
|
||||
}
|
||||
|
||||
fn examples(_: &WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
fn examples(_: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>> {
|
||||
vec![
|
||||
example_group(vec![
|
||||
single_example(
|
||||
|
|
|
@ -30,20 +30,20 @@ pub trait ComponentPreview: IntoElement {
|
|||
ExampleLabelSide::default()
|
||||
}
|
||||
|
||||
fn examples(_cx: &WindowContext) -> Vec<ComponentExampleGroup<Self>>;
|
||||
fn examples(_cx: &mut WindowContext) -> Vec<ComponentExampleGroup<Self>>;
|
||||
|
||||
fn custom_example(_cx: &WindowContext) -> impl Into<Option<AnyElement>> {
|
||||
None::<AnyElement>
|
||||
}
|
||||
|
||||
fn component_previews(cx: &WindowContext) -> Vec<AnyElement> {
|
||||
fn component_previews(cx: &mut WindowContext) -> Vec<AnyElement> {
|
||||
Self::examples(cx)
|
||||
.into_iter()
|
||||
.map(|example| Self::render_example_group(example))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn render_component_previews(cx: &WindowContext) -> AnyElement {
|
||||
fn render_component_previews(cx: &mut WindowContext) -> AnyElement {
|
||||
let title = Self::title();
|
||||
let (source, title) = title
|
||||
.rsplit_once("::")
|
||||
|
|
|
@ -108,147 +108,6 @@ impl ThemePreview {
|
|||
cx.theme().colors().editor_background
|
||||
}
|
||||
|
||||
fn render_avatars(&self, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
Headline::new("Avatars")
|
||||
.size(HeadlineSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.gap_4()
|
||||
.child(Avatar::new(AVATAR_URL).size(px(24.)))
|
||||
.child(Avatar::new(AVATAR_URL).size(px(24.)).grayscale(true))
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.size(px(24.))
|
||||
.indicator(AvatarAudioStatusIndicator::new(AudioStatus::Muted)),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.size(px(24.))
|
||||
.indicator(AvatarAudioStatusIndicator::new(AudioStatus::Deafened)),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.size(px(24.))
|
||||
.indicator(AvatarAvailabilityIndicator::new(Availability::Free)),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.size(px(24.))
|
||||
.indicator(AvatarAvailabilityIndicator::new(Availability::Free)),
|
||||
)
|
||||
.child(
|
||||
Facepile::empty()
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.border_color(Self::preview_bg(cx))
|
||||
.size(px(22.))
|
||||
.into_any_element(),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.border_color(Self::preview_bg(cx))
|
||||
.size(px(22.))
|
||||
.into_any_element(),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.border_color(Self::preview_bg(cx))
|
||||
.size(px(22.))
|
||||
.into_any_element(),
|
||||
)
|
||||
.child(
|
||||
Avatar::new(AVATAR_URL)
|
||||
.border_color(Self::preview_bg(cx))
|
||||
.size(px(22.))
|
||||
.into_any_element(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn render_buttons(&self, layer: ElevationIndex, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
Headline::new("Buttons")
|
||||
.size(HeadlineSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_start()
|
||||
.gap_px()
|
||||
.child(
|
||||
IconButton::new("icon_button_transparent", IconName::Check)
|
||||
.style(ButtonStyle::Transparent),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("icon_button_subtle", IconName::Check)
|
||||
.style(ButtonStyle::Subtle),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("icon_button_filled", IconName::Check)
|
||||
.style(ButtonStyle::Filled),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("icon_button_selected_accent", IconName::Check)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.selected(true),
|
||||
)
|
||||
.child(IconButton::new("icon_button_selected", IconName::Check).selected(true))
|
||||
.child(
|
||||
IconButton::new("icon_button_positive", IconName::Check)
|
||||
.style(ButtonStyle::Tinted(TintColor::Positive)),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("icon_button_warning", IconName::Check)
|
||||
.style(ButtonStyle::Tinted(TintColor::Warning)),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("icon_button_negative", IconName::Check)
|
||||
.style(ButtonStyle::Tinted(TintColor::Negative)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_px()
|
||||
.child(
|
||||
Button::new("button_transparent", "Transparent")
|
||||
.style(ButtonStyle::Transparent),
|
||||
)
|
||||
.child(Button::new("button_subtle", "Subtle").style(ButtonStyle::Subtle))
|
||||
.child(Button::new("button_filled", "Filled").style(ButtonStyle::Filled))
|
||||
.child(
|
||||
Button::new("button_selected", "Selected")
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.selected(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button_selected_tinted", "Selected (Tinted)")
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.selected(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button_positive", "Tint::Positive")
|
||||
.style(ButtonStyle::Tinted(TintColor::Positive)),
|
||||
)
|
||||
.child(
|
||||
Button::new("button_warning", "Tint::Warning")
|
||||
.style(ButtonStyle::Tinted(TintColor::Warning)),
|
||||
)
|
||||
.child(
|
||||
Button::new("button_negative", "Tint::Negative")
|
||||
.style(ButtonStyle::Tinted(TintColor::Negative)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn render_text(&self, layer: ElevationIndex, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
let bg = layer.bg(cx);
|
||||
|
||||
|
@ -502,7 +361,7 @@ impl ThemePreview {
|
|||
)
|
||||
}
|
||||
|
||||
fn render_components_page(&self, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
fn render_components_page(&self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let layer = ElevationIndex::Surface;
|
||||
|
||||
v_flex()
|
||||
|
@ -520,8 +379,6 @@ impl ThemePreview {
|
|||
.child(Indicator::render_component_previews(cx))
|
||||
.child(Icon::render_component_previews(cx))
|
||||
.child(Table::render_component_previews(cx))
|
||||
.child(self.render_avatars(cx))
|
||||
.child(self.render_buttons(layer, cx))
|
||||
}
|
||||
|
||||
fn render_page_nav(&self, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
|
|
|
@ -52,6 +52,7 @@ file_icons.workspace = true
|
|||
fs.workspace = true
|
||||
futures.workspace = true
|
||||
git.workspace = true
|
||||
git_ui.workspace = true
|
||||
git_hosting_providers.workspace = true
|
||||
go_to_line.workspace = true
|
||||
gpui = { workspace = true, features = ["wayland", "x11", "font-kit"] }
|
||||
|
|
|
@ -447,6 +447,7 @@ fn main() {
|
|||
outline::init(cx);
|
||||
project_symbols::init(cx);
|
||||
project_panel::init(Assets, cx);
|
||||
git_ui::git_panel::init(cx);
|
||||
outline_panel::init(Assets, cx);
|
||||
tasks_ui::init(cx);
|
||||
snippets_ui::init(cx);
|
||||
|
|
|
@ -216,7 +216,7 @@ pub fn initialize_workspace(
|
|||
status_bar.add_left_item(activity_indicator, cx);
|
||||
status_bar.add_right_item(inline_completion_button, cx);
|
||||
status_bar.add_right_item(active_buffer_language, cx);
|
||||
status_bar.add_right_item(active_toolchain_language, cx);
|
||||
status_bar.add_right_item(active_toolchain_language, cx);
|
||||
status_bar.add_right_item(vim_mode_indicator, cx);
|
||||
status_bar.add_right_item(cursor_position, cx);
|
||||
});
|
||||
|
@ -237,8 +237,11 @@ pub fn initialize_workspace(
|
|||
|
||||
let release_channel = ReleaseChannel::global(cx);
|
||||
let assistant2_feature_flag = cx.wait_for_flag::<feature_flags::Assistant2FeatureFlag>();
|
||||
let git_ui_feature_flag = cx.wait_for_flag::<feature_flags::GitUiFeatureFlag>();
|
||||
|
||||
let prompt_builder = prompt_builder.clone();
|
||||
let is_staff = cx.is_staff();
|
||||
|
||||
cx.spawn(|workspace_handle, mut cx| async move {
|
||||
let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone());
|
||||
let outline_panel = OutlinePanel::load(workspace_handle.clone(), cx.clone());
|
||||
|
@ -276,13 +279,26 @@ pub fn initialize_workspace(
|
|||
workspace.add_panel(chat_panel, cx);
|
||||
workspace.add_panel(notification_panel, cx);
|
||||
})?;
|
||||
let git_ui_enabled = git_ui_feature_flag.await || is_staff;
|
||||
|
||||
let git_panel = if git_ui_enabled {
|
||||
Some(git_ui::git_panel::GitPanel::load(workspace_handle.clone(), cx.clone()).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
workspace_handle.update(&mut cx, |workspace, cx| {
|
||||
if let Some(git_panel) = git_panel {
|
||||
workspace.add_panel(git_panel, cx);
|
||||
}
|
||||
})?;
|
||||
|
||||
let is_assistant2_enabled =
|
||||
if cfg!(test) || release_channel != ReleaseChannel::Dev {
|
||||
false
|
||||
} else {
|
||||
assistant2_feature_flag.await
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
let (assistant_panel, assistant2_panel) = if is_assistant2_enabled {
|
||||
let assistant2_panel =
|
||||
|
@ -303,6 +319,7 @@ pub fn initialize_workspace(
|
|||
if let Some(assistant2_panel) = assistant2_panel {
|
||||
workspace.add_panel(assistant2_panel, cx);
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue