244 lines · 8.2 KB · Rust
RawDownload
#![allow(unused, dead_code)] use crate::git_panel::{commit_message_editor, GitPanel};use crate::repository_selector::RepositorySelector;use anyhow::Result;use git::Commit;use language::Buffer;use panel::{panel_editor_container, panel_editor_style, panel_filled_button, panel_icon_button};use settings::Settings;use theme::ThemeSettings;use ui::{prelude::*, Tooltip}; use editor::{Editor, EditorElement, EditorMode, MultiBuffer};use gpui::*;use project::git::Repository;use project::{Fs, Project};use std::sync::Arc;use workspace::dock::{Dock, DockPosition, PanelHandle};use workspace::{ModalView, Workspace}; pub fn init(cx: &mut App) {    cx.observe_new(|workspace: &mut Workspace, window, cx| {        let Some(window) = window else {            return;        };        CommitModal::register(workspace, window, cx)    })    .detach();} pub struct CommitModal {    git_panel: Entity<GitPanel>,    commit_editor: Entity<Editor>,    restore_dock: RestoreDock,} impl Focusable for CommitModal {    fn focus_handle(&self, cx: &App) -> gpui::FocusHandle {        self.commit_editor.focus_handle(cx)    }} impl EventEmitter<DismissEvent> for CommitModal {}impl ModalView for CommitModal {    fn on_before_dismiss(        &mut self,        window: &mut Window,        cx: &mut Context<Self>,    ) -> workspace::DismissDecision {        self.git_panel.update(cx, |git_panel, cx| {            git_panel.set_modal_open(false, cx);        });        self.restore_dock.dock.update(cx, |dock, cx| {            if let Some(active_index) = self.restore_dock.active_index {                dock.activate_panel(active_index, window, cx)            }            dock.set_open(self.restore_dock.is_open, window, cx)        });        workspace::DismissDecision::Dismiss(true)    }} struct RestoreDock {    dock: WeakEntity<Dock>,    is_open: bool,    active_index: Option<usize>,} impl CommitModal {    pub fn register(workspace: &mut Workspace, _: &mut Window, cx: &mut Context<Workspace>) {        workspace.register_action(|workspace, _: &Commit, window, cx| {            let Some(git_panel) = workspace.panel::<GitPanel>(cx) else {                return;            };             let (can_commit, conflict) = git_panel.update(cx, |git_panel, cx| {                let can_commit = git_panel.can_commit();                let conflict = git_panel.has_unstaged_conflicts();                (can_commit, conflict)            });            if !can_commit {                let message = if conflict {                    "There are still conflicts. You must stage these before committing."                } else {                    "No changes to commit."                };                let prompt = window.prompt(PromptLevel::Warning, message, None, &["Ok"], cx);                cx.spawn(|_, _| async move {                    prompt.await.ok();                })                .detach();            }             let dock = workspace.dock_at_position(git_panel.position(window, cx));            let is_open = dock.read(cx).is_open();            let active_index = dock.read(cx).active_panel_index();            let dock = dock.downgrade();            let restore_dock_position = RestoreDock {                dock,                is_open,                active_index,            };            workspace.open_panel::<GitPanel>(window, cx);            workspace.toggle_modal(window, cx, move |window, cx| {                CommitModal::new(git_panel, restore_dock_position, window, cx)            })        });    }     fn new(        git_panel: Entity<GitPanel>,        restore_dock: RestoreDock,        window: &mut Window,        cx: &mut Context<Self>,    ) -> Self {        let panel = git_panel.read(cx);         let commit_editor = git_panel.update(cx, |git_panel, cx| {            git_panel.set_modal_open(true, cx);            let buffer = git_panel.commit_message_buffer(cx).clone();            let project = git_panel.project.clone();            cx.new(|cx| commit_message_editor(buffer, project.clone(), false, window, cx))        });         Self {            git_panel,            commit_editor,            restore_dock,        }    }     pub fn render_commit_editor(        &self,        name_and_email: Option<(SharedString, SharedString)>,        window: &mut Window,        cx: &mut Context<Self>,    ) -> impl IntoElement {        let editor = self.commit_editor.clone();         let panel_editor_style = panel_editor_style(true, window, cx);         let settings = ThemeSettings::get_global(cx);        let line_height = relative(settings.buffer_line_height.value())            .to_pixels(settings.buffer_font_size(cx).into(), window.rem_size());         v_flex()            .justify_between()            .relative()            .w_full()            .h_full()            .pt_2()            .bg(cx.theme().colors().editor_background)            .child(EditorElement::new(&self.commit_editor, panel_editor_style))            .child(self.render_footer(window, cx))    }     pub fn render_footer(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {        let (branch, tooltip, title, co_authors) = self.git_panel.update(cx, |git_panel, cx| {            let branch = git_panel                .active_repository                .as_ref()                .and_then(|repo| repo.read(cx).branch().map(|b| b.name.clone()))                .unwrap_or_else(|| "<no branch>".into());            let tooltip = if git_panel.has_staged_changes() {                "Commit staged changes"            } else {                "Commit changes to tracked files"            };            let title = if git_panel.has_staged_changes() {                "Commit"            } else {                "Commit All"            };            let co_authors = git_panel.render_co_authors(cx);            (branch, tooltip, title, co_authors)        });         let branch_selector = Button::new("branch-selector", branch)            .color(Color::Muted)            .style(ButtonStyle::Subtle)            .icon(IconName::GitBranch)            .icon_size(IconSize::Small)            .icon_color(Color::Muted)            .size(ButtonSize::Compact)            .icon_position(IconPosition::Start)            .tooltip(Tooltip::for_action_title(                "Switch Branch",                &zed_actions::git::Branch,            ))            .on_click(cx.listener(|_, _, window, cx| {                window.dispatch_action(zed_actions::git::Branch.boxed_clone(), cx);            }))            .style(ButtonStyle::Transparent);        h_flex()            .w_full()            .justify_between()            .child(branch_selector)            .child(                h_flex().children(co_authors).child(                    panel_filled_button(title)                        .tooltip(Tooltip::for_action_title(tooltip, &git::Commit))                        .on_click(cx.listener(|this, _, window, cx| {                            this.commit(&Default::default(), window, cx);                        })),                ),            )    }     fn dismiss(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {        cx.emit(DismissEvent);    }    fn commit(&mut self, _: &git::Commit, window: &mut Window, cx: &mut Context<Self>) {        self.git_panel            .update(cx, |git_panel, cx| git_panel.commit_changes(window, cx));        cx.emit(DismissEvent);    }} impl Render for CommitModal {    fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {        v_flex()            .id("commit-modal")            .key_context("GitCommit")            .elevation_3(cx)            .on_action(cx.listener(Self::dismiss))            .on_action(cx.listener(Self::commit))            .relative()            .bg(cx.theme().colors().editor_background)            .rounded(px(16.))            .border_1()            .border_color(cx.theme().colors().border)            .py_2()            .px_4()            .w(px(480.))            .min_h(rems(18.))            .flex_1()            .overflow_hidden()            .child(                v_flex()                    .flex_1()                    .child(self.render_commit_editor(None, window, cx)),            )    }}