Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial git panel refinements #21912

Merged
merged 7 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions assets/settings/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,14 @@
// Default width of the chat panel.
"default_width": 240
},
"git_panel": {
// Whether to show the git panel button in the status bar.
"button": true,
// Where to the git panel. Can be 'left' or 'right'.
"dock": "left",
// Default width of the git panel.
"default_width": 360
},
"message_editor": {
// Whether to automatically replace emoji shortcodes with emoji characters.
// For example: typing `:wave:` gets replaced with `👋`.
Expand Down
10 changes: 9 additions & 1 deletion crates/git_ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@ name = "git_ui"
path = "src/git_ui.rs"

[dependencies]
anyhow.workspace = true
db.workspace = true
gpui.workspace = true
project.workspace = true
schemars.workspace = true
serde.workspace = true
workspace.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
settings.workspace = true
ui.workspace = true
util.workspace = true
workspace.workspace = true

[target.'cfg(windows)'.dependencies]
windows.workspace = true
Expand Down
100 changes: 80 additions & 20 deletions crates/git_ui/src/git_panel.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
use std::sync::Arc;
use util::TryFutureExt;

use db::kvp::KEY_VALUE_STORE;
use gpui::*;
use project::Fs;
use serde::{Deserialize, Serialize};
use settings::Settings as _;
use ui::{prelude::*, Checkbox, Divider, DividerColor, ElevationIndex};
use workspace::dock::{DockPosition, Panel, PanelEvent};
use workspace::Workspace;

use crate::settings::GitPanelSettings;

const GIT_PANEL_KEY: &str = "GitPanel";

pub fn init(cx: &mut AppContext) {
cx.observe_new_views(
|workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
Expand All @@ -14,11 +25,17 @@ pub fn init(cx: &mut AppContext) {
.detach();
}

#[derive(Serialize, Deserialize)]
struct SerializedGitPanel {
width: Option<Pixels>,
}

actions!(git_panel, [Deploy, ToggleFocus]);

#[derive(Clone)]
pub struct GitPanel {
_workspace: WeakView<Workspace>,
pending_serialization: Task<Option<()>>,
fs: Arc<dyn Fs>,
focus_handle: FocusHandle,
width: Option<Pixels>,
}
Expand All @@ -29,20 +46,39 @@ impl GitPanel {
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))
})
// Clippy incorrectly classifies this as a redundant closure
#[allow(clippy::redundant_closure)]
workspace.update(&mut cx, |workspace, cx| Self::new(workspace, cx))
})
}

pub fn new(workspace: WeakView<Workspace>, cx: &mut ViewContext<Self>) -> Self {
Self {
_workspace: workspace,
pub fn new(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> View<Self> {
let fs = workspace.app_state().fs.clone();
let weak_workspace = workspace.weak_handle();

cx.new_view(|cx| Self {
fs,
_workspace: weak_workspace,
pending_serialization: Task::ready(None),
focus_handle: cx.focus_handle(),
width: Some(px(360.)),
}
})
}

fn serialize(&mut self, cx: &mut ViewContext<Self>) {
let width = self.width;
self.pending_serialization = cx.background_executor().spawn(
async move {
KEY_VALUE_STORE
.write_kvp(
GIT_PANEL_KEY.into(),
serde_json::to_string(&SerializedGitPanel { width })?,
)
.await?;
anyhow::Ok(())
}
.log_err(),
);
}

pub fn render_panel_header(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Expand All @@ -53,14 +89,14 @@ impl GitPanel {
.bg(ElevationIndex::Surface.bg(cx))
.child(
h_flex()
.gap_1()
.gap_2()
.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()
.gap_2()
.child(
IconButton::new("discard-changes", IconName::Undo)
.icon_size(IconSize::Small)
Expand Down Expand Up @@ -104,6 +140,22 @@ impl GitPanel {
.opacity(0.5),
)
}

fn render_empty_state(&self, cx: &ViewContext<Self>) -> impl IntoElement {
h_flex()
.h_full()
.flex_1()
.justify_center()
.items_center()
.child(
v_flex()
.gap_3()
.child("No changes to commit")
.text_ui_sm(cx)
.mx_auto()
.text_color(Color::Placeholder.color(cx)),
)
}
}

impl Render for GitPanel {
Expand All @@ -124,7 +176,7 @@ impl Render for GitPanel {
.h(px(8.))
.child(Divider::horizontal_dashed().color(DividerColor::Border)),
)
.child(div().flex_1())
.child(self.render_empty_state(cx))
.child(
h_flex()
.items_center()
Expand All @@ -148,27 +200,35 @@ impl Panel for GitPanel {
"GitPanel"
}

fn position(&self, _cx: &gpui::WindowContext) -> DockPosition {
DockPosition::Left
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
GitPanelSettings::get_global(cx).dock
}

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 set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
settings::update_settings_file::<GitPanelSettings>(
self.fs.clone(),
cx,
move |settings, _| settings.dock = Some(position),
);
}

fn size(&self, _cx: &gpui::WindowContext) -> Pixels {
self.width.unwrap_or(px(360.))
fn size(&self, cx: &gpui::WindowContext) -> Pixels {
self.width
.unwrap_or_else(|| GitPanelSettings::get_global(cx).default_width)
}

fn set_size(&mut self, size: Option<Pixels>, cx: &mut ViewContext<Self>) {
self.width = size;
self.serialize(cx);
cx.notify();
}

fn icon(&self, _cx: &gpui::WindowContext) -> Option<ui::IconName> {
Some(ui::IconName::GitBranch)
fn icon(&self, cx: &WindowContext) -> Option<ui::IconName> {
Some(ui::IconName::GitBranch).filter(|_| GitPanelSettings::get_global(cx).button)
}

fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
Expand Down
9 changes: 9 additions & 0 deletions crates/git_ui/src/git_ui.rs
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
use ::settings::Settings;
use gpui::AppContext;
use settings::GitPanelSettings;

pub mod git_panel;
mod settings;

pub fn init(cx: &mut AppContext) {
GitPanelSettings::register(cx);
}
41 changes: 41 additions & 0 deletions crates/git_ui/src/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use gpui::Pixels;
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use workspace::dock::DockPosition;

#[derive(Deserialize, Debug)]
pub struct GitPanelSettings {
pub button: bool,
pub dock: DockPosition,
pub default_width: Pixels,
}

#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
pub struct PanelSettingsContent {
/// Whether to show the panel button in the status bar.
///
/// Default: true
pub button: Option<bool>,
/// Where to dock the panel.
///
/// Default: left
pub dock: Option<DockPosition>,
/// Default width of the panel in pixels.
///
/// Default: 360
pub default_width: Option<f32>,
}

impl Settings for GitPanelSettings {
const KEY: Option<&'static str> = Some("git_panel");

type FileContent = PanelSettingsContent;

fn load(
sources: SettingsSources<Self::FileContent>,
_: &mut gpui::AppContext,
) -> anyhow::Result<Self> {
sources.json_merge()
}
}
1 change: 1 addition & 0 deletions crates/zed/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ fn main() {
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx);
collab_ui::init(&app_state, cx);
git_ui::init(cx);
vcs_menu::init(cx);
feedback::init(cx);
markdown_preview::init(cx);
Expand Down
1 change: 1 addition & 0 deletions crates/zed/src/zed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3477,6 +3477,7 @@ mod tests {
language::init(cx);
editor::init(cx);
collab_ui::init(&app_state, cx);
git_ui::init(cx);
project_panel::init((), cx);
outline_panel::init((), cx);
terminal_view::init(cx);
Expand Down
Loading