diff --git a/assets/settings/default.json b/assets/settings/default.json index 5abb055899..dcbf999190 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -975,6 +975,11 @@ // // Default: true "diff_stats": true, + // Maximum length of the commit message title before a warning is shown. + // Set to 0 to disable. + // + // Default: 72 + "commit_title_max_length": 72, }, "message_editor": { // Whether to automatically replace emoji shortcodes with emoji characters. diff --git a/crates/git_ui/src/commit_modal.rs b/crates/git_ui/src/commit_modal.rs index ad6d960a30..921bcd1960 100644 --- a/crates/git_ui/src/commit_modal.rs +++ b/crates/git_ui/src/commit_modal.rs @@ -1,5 +1,6 @@ use crate::branch_picker::{self, BranchList}; use crate::git_panel::{GitPanel, commit_message_editor, panel_editor_style}; +use crate::git_panel_settings::GitPanelSettings; use git::repository::CommitOptions; use git::{Amend, Commit, GenerateCommitMessage, Signoff}; use panel::panel_button; @@ -539,6 +540,18 @@ impl Render for CommitModal { let border_radius = properties.modal_border_radius; let editor_focus_handle = self.commit_editor.focus_handle(cx); + let max_title_length = GitPanelSettings::get_global(cx).commit_title_max_length; + let title_exceeds_limit = if max_title_length > 0 { + self.commit_editor + .read(cx) + .text(cx) + .lines() + .next() + .is_some_and(|title| title.len() > max_title_length) + } else { + false + }; + v_flex() .id("commit-modal") .key_context("GitCommit") @@ -567,6 +580,9 @@ impl Render for CommitModal { this.toggle_branch_selector(window, cx); }), ) + .w(width) + .h_112() + .p(container_padding) .elevation_3(cx) .overflow_hidden() .flex_none() @@ -575,30 +591,50 @@ impl Render for CommitModal { .rounded(px(border_radius)) .border_1() .border_color(cx.theme().colors().border) - .w(width) - .p(container_padding) .child( v_flex() .id("editor-container") - .justify_between() + .cursor_text() .p_2() .size_full() .gap_2() + .justify_between() .rounded(properties.editor_border_radius()) .overflow_hidden() - .cursor_text() .bg(cx.theme().colors().editor_background) .border_1() - .border_color(cx.theme().colors().border_variant) + .border_color(if title_exceeds_limit { + cx.theme().status().warning_border + } else { + cx.theme().colors().border_variant + }) .on_click(cx.listener(move |_, _: &ClickEvent, window, cx| { window.focus(&editor_focus_handle, cx); })) - .child( - div() - .flex_1() - .size_full() - .child(self.render_commit_editor(window, cx)), - ) + .child(self.render_commit_editor(window, cx)) + .when(title_exceeds_limit, |this| { + this.child( + h_flex() + .absolute() + .bottom_12() + .w_full() + .py_1() + .px_2() + .gap_1() + .justify_center() + .child( + Icon::new(IconName::Warning) + .size(IconSize::XSmall) + .color(Color::Warning), + ) + .child( + Label::new(format!( + "Commit message title exceeds {max_title_length}-character limit." + )) + .size(LabelSize::Small), + ), + ) + }) .child(self.render_footer(window, cx)), ) } diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index e2bd1c553f..8257b3cf4f 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -4343,6 +4343,18 @@ impl GitPanel { editor.max_point(cx).row().0 >= MAX_PANEL_EDITOR_LINES as u32 }); + let max_title_length = GitPanelSettings::get_global(cx).commit_title_max_length; + let title_exceeds_limit = if max_title_length > 0 { + self.commit_editor + .read(cx) + .text(cx) + .lines() + .next() + .is_some_and(|title| title.len() > max_title_length) + } else { + false + }; + let footer = v_flex() .child(PanelRepoFooter::new( display_name, @@ -4350,15 +4362,41 @@ impl GitPanel { head_commit, Some(git_panel), )) + .when(title_exceeds_limit, |this| { + this.child( + h_flex() + .px_2() + .py_1() + .gap_1() + .border_t_1() + .border_color(cx.theme().status().warning_border) + .bg(cx.theme().status().warning_background.opacity(0.5)) + .child( + Icon::new(IconName::Warning) + .size(IconSize::XSmall) + .color(Color::Warning), + ) + .child( + Label::new(format!( + "Commit message title exceeds {max_title_length}-character limit." + )) + .size(LabelSize::Small), + ), + ) + }) .child( panel_editor_container(window, cx) .id("commit-editor-container") + .cursor_text() .relative() .w_full() .h(max_height + footer_size) .border_t_1() - .border_color(cx.theme().colors().border) - .cursor_text() + .border_color(if title_exceeds_limit { + cx.theme().status().warning_border + } else { + cx.theme().colors().border + }) .on_click(cx.listener(move |this, _: &ClickEvent, window, cx| { window.focus(&this.commit_editor.focus_handle(cx), cx); })) diff --git a/crates/git_ui/src/git_panel_settings.rs b/crates/git_ui/src/git_panel_settings.rs index 9ccbced249..caf4b22dc4 100644 --- a/crates/git_ui/src/git_panel_settings.rs +++ b/crates/git_ui/src/git_panel_settings.rs @@ -30,6 +30,7 @@ pub struct GitPanelSettings { pub diff_stats: bool, pub show_count_badge: bool, pub starts_open: bool, + pub commit_title_max_length: usize, } #[derive(Default)] @@ -76,6 +77,7 @@ impl Settings for GitPanelSettings { diff_stats: git_panel.diff_stats.unwrap(), show_count_badge: git_panel.show_count_badge.unwrap(), starts_open: git_panel.starts_open.unwrap(), + commit_title_max_length: git_panel.commit_title_max_length.unwrap(), } } } diff --git a/crates/settings_content/src/settings_content.rs b/crates/settings_content/src/settings_content.rs index aa3dc0d81a..704b13683b 100644 --- a/crates/settings_content/src/settings_content.rs +++ b/crates/settings_content/src/settings_content.rs @@ -647,6 +647,12 @@ pub struct GitPanelSettingsContent { /// /// Default: false pub starts_open: Option, + + /// Maximum length of the commit message title before a warning is shown. + /// Set to 0 to disable. + /// + /// Default: 72 + pub commit_title_max_length: Option, } #[derive( diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index a6cd5e186c..17d89b2f76 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -5424,7 +5424,7 @@ fn panels_page() -> SettingsPage { ] } - fn git_panel_section() -> [SettingsPageItem; 14] { + fn git_panel_section() -> [SettingsPageItem; 15] { [ SettingsPageItem::SectionHeader("Git Panel"), SettingsPageItem::SettingItem(SettingItem { @@ -5642,6 +5642,28 @@ fn panels_page() -> SettingsPage { metadata: None, files: USER, }), + SettingsPageItem::SettingItem(SettingItem { + title: "Commit Title Max Length", + description: "Maximum length of the commit message title before a warning is shown. Set to 0 to disable.", + field: Box::new(SettingField { + json_path: Some("git_panel.commit_title_max_length"), + pick: |settings_content| { + settings_content + .git_panel + .as_ref()? + .commit_title_max_length + .as_ref() + }, + write: |settings_content, value, _app: &App| { + settings_content + .git_panel + .get_or_insert_default() + .commit_title_max_length = value; + }, + }), + metadata: None, + files: USER, + }), SettingsPageItem::SettingItem(SettingItem { title: "Scroll Bar", description: "How and when the scrollbar should be displayed.",