git_ui: Add Git Panel settings (#23132)
This PR adds settings for the Git Panel. The new settings include: | Setting | Description | Default | |---------|-------------|---------| | `git_panel.button` | Toggle visibility of the Git Panel button in the status bar | `true` | | `git_panel.dock` | Choose where to dock the Git Panel | `"left"` | | `git_panel.default_width` | Set the default width of the Git Panel in pixels | `360` | | `git_panel.status_style` | Select how Git status is displayed | `"icon"` | | `git_panel.scrollbar.show` | Configure scrollbar behavior | Inherits from editor settings | Example usage: ```json "git_panel": { "button": true, "dock": "left", "default_width": 360, "status_style": "icon", "scrollbar": { "show": "auto" } } ``` Release Notes: - N/A
This commit is contained in:
parent
a67709629b
commit
78fd5b5f02
5 changed files with 166 additions and 73 deletions
|
@ -503,7 +503,17 @@
|
|||
// Where to the git panel. Can be 'left' or 'right'.
|
||||
"dock": "left",
|
||||
// Default width of the git panel.
|
||||
"default_width": 360
|
||||
"default_width": 360,
|
||||
// Style of the git status indicator in the panel.
|
||||
//
|
||||
// Default: icon
|
||||
"status_style": "icon",
|
||||
"scrollbar": {
|
||||
// When to show the scrollbar in the git panel.
|
||||
//
|
||||
// Default: inherits editor scrollbar settings
|
||||
"show": null
|
||||
}
|
||||
},
|
||||
"message_editor": {
|
||||
// Whether to automatically replace emoji shortcodes with emoji characters.
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use crate::git_panel_settings::StatusStyle;
|
||||
use crate::{first_repository_in_project, first_worktree_repository};
|
||||
use crate::{
|
||||
git_status_icon, settings::GitPanelSettings, CommitAllChanges, CommitChanges, GitState,
|
||||
GitViewMode, RevertAll, StageAll, ToggleStaged, UnstageAll,
|
||||
git_panel_settings::GitPanelSettings, git_status_icon, CommitAllChanges, CommitChanges,
|
||||
GitState, GitViewMode, RevertAll, StageAll, ToggleStaged, UnstageAll,
|
||||
};
|
||||
use anyhow::{Context as _, Result};
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use editor::Editor;
|
||||
use editor::scroll::ScrollbarAutoHide;
|
||||
use editor::{Editor, EditorSettings, ShowScrollbar};
|
||||
use git::repository::{GitFileStatus, RepoPath};
|
||||
use git::status::GitStatusPair;
|
||||
use gpui::*;
|
||||
|
@ -313,7 +315,7 @@ impl GitPanel {
|
|||
scrollbar_state: ScrollbarState::new(scroll_handle.clone()).parent_view(cx.view()),
|
||||
scroll_handle,
|
||||
selected_entry: None,
|
||||
show_scrollbar: !Self::should_autohide_scrollbar(cx),
|
||||
show_scrollbar: false,
|
||||
hide_scrollbar_task: None,
|
||||
rebuild_requested,
|
||||
commit_editor,
|
||||
|
@ -322,6 +324,7 @@ impl GitPanel {
|
|||
project,
|
||||
};
|
||||
git_panel.schedule_update();
|
||||
git_panel.show_scrollbar = git_panel.should_show_scrollbar(cx);
|
||||
git_panel
|
||||
});
|
||||
|
||||
|
@ -376,19 +379,38 @@ impl GitPanel {
|
|||
}
|
||||
}
|
||||
|
||||
fn should_show_scrollbar(_cx: &AppContext) -> bool {
|
||||
// TODO: plug into settings
|
||||
true
|
||||
fn show_scrollbar(&self, cx: &mut ViewContext<Self>) -> ShowScrollbar {
|
||||
GitPanelSettings::get_global(cx)
|
||||
.scrollbar
|
||||
.show
|
||||
.unwrap_or_else(|| EditorSettings::get_global(cx).scrollbar.show)
|
||||
}
|
||||
|
||||
fn should_autohide_scrollbar(_cx: &AppContext) -> bool {
|
||||
// TODO: plug into settings
|
||||
true
|
||||
fn should_show_scrollbar(&self, cx: &mut ViewContext<Self>) -> bool {
|
||||
let show = self.show_scrollbar(cx);
|
||||
match show {
|
||||
ShowScrollbar::Auto => true,
|
||||
ShowScrollbar::System => true,
|
||||
ShowScrollbar::Always => true,
|
||||
ShowScrollbar::Never => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn should_autohide_scrollbar(&self, cx: &mut ViewContext<Self>) -> bool {
|
||||
let show = self.show_scrollbar(cx);
|
||||
match show {
|
||||
ShowScrollbar::Auto => true,
|
||||
ShowScrollbar::System => cx
|
||||
.try_global::<ScrollbarAutoHide>()
|
||||
.map_or_else(|| cx.should_auto_hide_scrollbars(), |autohide| autohide.0),
|
||||
ShowScrollbar::Always => false,
|
||||
ShowScrollbar::Never => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn hide_scrollbar(&mut self, cx: &mut ViewContext<Self>) {
|
||||
const SCROLLBAR_SHOW_INTERVAL: Duration = Duration::from_secs(1);
|
||||
if !Self::should_autohide_scrollbar(cx) {
|
||||
if !self.should_autohide_scrollbar(cx) {
|
||||
return;
|
||||
}
|
||||
self.hide_scrollbar_task = Some(cx.spawn(|panel, mut cx| async move {
|
||||
|
@ -960,15 +982,26 @@ impl GitPanel {
|
|||
}
|
||||
|
||||
fn render_scrollbar(&self, cx: &mut ViewContext<Self>) -> Option<Stateful<Div>> {
|
||||
if !Self::should_show_scrollbar(cx)
|
||||
let scroll_bar_style = self.show_scrollbar(cx);
|
||||
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
|
||||
|
||||
if !self.should_show_scrollbar(cx)
|
||||
|| !(self.show_scrollbar || self.scrollbar_state.is_dragging())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(
|
||||
div()
|
||||
.id("git-panel-vertical-scroll")
|
||||
.occlude()
|
||||
.id("project-panel-vertical-scroll")
|
||||
.flex_none()
|
||||
.h_full()
|
||||
.cursor_default()
|
||||
.when(show_container, |this| this.pl_1().px_1p5())
|
||||
.when(!show_container, |this| {
|
||||
this.absolute().right_1().top_1().bottom_1().w(px(12.))
|
||||
})
|
||||
.on_mouse_move(cx.listener(|_, _, cx| {
|
||||
cx.notify();
|
||||
cx.stop_propagation()
|
||||
|
@ -995,13 +1028,6 @@ impl GitPanel {
|
|||
.on_scroll_wheel(cx.listener(|_, _, cx| {
|
||||
cx.notify();
|
||||
}))
|
||||
.h_full()
|
||||
.absolute()
|
||||
.right_1()
|
||||
.top_1()
|
||||
.bottom_1()
|
||||
.w(px(12.))
|
||||
.cursor_default()
|
||||
.children(Scrollbar::vertical(
|
||||
// percentage as f32..end_offset as f32,
|
||||
self.scrollbar_state.clone(),
|
||||
|
@ -1042,9 +1068,26 @@ impl GitPanel {
|
|||
let state = self.git_state.clone();
|
||||
let repo_path = entry_details.repo_path.clone();
|
||||
let selected = self.selected_entry == Some(ix);
|
||||
|
||||
let status_style = GitPanelSettings::get_global(cx).status_style;
|
||||
// TODO revisit, maybe use a different status here?
|
||||
let status = entry_details.status.combined();
|
||||
|
||||
let mut label_color = cx.theme().colors().text;
|
||||
if status_style == StatusStyle::LabelColor {
|
||||
label_color = match status {
|
||||
GitFileStatus::Added => cx.theme().status().created,
|
||||
GitFileStatus::Modified => cx.theme().status().modified,
|
||||
GitFileStatus::Conflict => cx.theme().status().conflict,
|
||||
GitFileStatus::Deleted => cx.theme().colors().text_disabled,
|
||||
// TODO: Should we even have this here?
|
||||
GitFileStatus::Untracked => cx.theme().colors().text_placeholder,
|
||||
}
|
||||
}
|
||||
|
||||
let path_color = matches!(status, GitFileStatus::Deleted)
|
||||
.then_some(cx.theme().colors().text_disabled)
|
||||
.unwrap_or(cx.theme().colors().text_muted);
|
||||
|
||||
let entry_id = ElementId::Name(format!("entry_{}", entry_details.display_name).into());
|
||||
let checkbox_id =
|
||||
ElementId::Name(format!("checkbox_{}", entry_details.display_name).into());
|
||||
|
@ -1125,21 +1168,19 @@ impl GitPanel {
|
|||
}
|
||||
}),
|
||||
)
|
||||
.child(git_status_icon(status))
|
||||
.when(status_style == StatusStyle::Icon, |this| {
|
||||
this.child(git_status_icon(status))
|
||||
})
|
||||
.child(
|
||||
h_flex()
|
||||
.when(status == GitFileStatus::Deleted, |this| {
|
||||
this.text_color(cx.theme().colors().text_disabled)
|
||||
.line_through()
|
||||
})
|
||||
.text_color(label_color)
|
||||
.when(status == GitFileStatus::Deleted, |this| this.line_through())
|
||||
.when_some(repo_path.parent(), |this, parent| {
|
||||
let parent_str = parent.to_string_lossy();
|
||||
if !parent_str.is_empty() {
|
||||
this.child(
|
||||
div()
|
||||
.when(status != GitFileStatus::Deleted, |this| {
|
||||
this.text_color(cx.theme().colors().text_muted)
|
||||
})
|
||||
.text_color(path_color)
|
||||
.child(format!("{}/", parent_str)),
|
||||
)
|
||||
} else {
|
||||
|
|
83
crates/git_ui/src/git_panel_settings.rs
Normal file
83
crates/git_ui/src/git_panel_settings.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use editor::ShowScrollbar;
|
||||
use gpui::Pixels;
|
||||
use schemars::JsonSchema;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use settings::{Settings, SettingsSources};
|
||||
use workspace::dock::DockPosition;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
pub struct ScrollbarSettingsContent {
|
||||
/// When to show the scrollbar in the git panel.
|
||||
///
|
||||
/// Default: inherits editor scrollbar settings
|
||||
pub show: Option<Option<ShowScrollbar>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
pub struct ScrollbarSettings {
|
||||
pub show: Option<ShowScrollbar>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
// Style of the git status indicator in the panel.
|
||||
//
|
||||
// Default: icon
|
||||
pub enum StatusStyleContent {
|
||||
Icon,
|
||||
LabelColor,
|
||||
}
|
||||
|
||||
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StatusStyle {
|
||||
#[default]
|
||||
Icon,
|
||||
LabelColor,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
|
||||
pub struct GitPanelSettingsContent {
|
||||
/// 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>,
|
||||
/// How entry statuses are displayed.
|
||||
///
|
||||
/// Default: icon
|
||||
pub status_style: Option<StatusStyle>,
|
||||
/// How and when the scrollbar should be displayed.
|
||||
///
|
||||
/// Default: inherits editor scrollbar settings
|
||||
pub scrollbar: Option<ScrollbarSettings>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
|
||||
pub struct GitPanelSettings {
|
||||
pub button: bool,
|
||||
pub dock: DockPosition,
|
||||
pub default_width: Pixels,
|
||||
pub status_style: StatusStyle,
|
||||
pub scrollbar: ScrollbarSettings,
|
||||
}
|
||||
|
||||
impl Settings for GitPanelSettings {
|
||||
const KEY: Option<&'static str> = Some("git_panel");
|
||||
|
||||
type FileContent = GitPanelSettingsContent;
|
||||
|
||||
fn load(
|
||||
sources: SettingsSources<Self::FileContent>,
|
||||
_: &mut gpui::AppContext,
|
||||
) -> anyhow::Result<Self> {
|
||||
sources.json_merge()
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@ use ::settings::Settings;
|
|||
use collections::HashMap;
|
||||
use futures::{future::FusedFuture, select, FutureExt};
|
||||
use git::repository::{GitFileStatus, GitRepository, RepoPath};
|
||||
use git_panel_settings::GitPanelSettings;
|
||||
use gpui::{actions, AppContext, Context, Global, Hsla, Model, ModelContext};
|
||||
use project::{Project, WorktreeId};
|
||||
use settings::GitPanelSettings;
|
||||
use std::sync::mpsc;
|
||||
use std::{
|
||||
pin::{pin, Pin},
|
||||
|
@ -16,7 +16,7 @@ use ui::{Color, Icon, IconName, IntoElement, SharedString};
|
|||
use worktree::RepositoryEntry;
|
||||
|
||||
pub mod git_panel;
|
||||
mod settings;
|
||||
mod git_panel_settings;
|
||||
|
||||
const GIT_TASK_DEBOUNCE: Duration = Duration::from_millis(50);
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
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()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue