This commit is contained in:
2026-09-02 09:14:04 +07:00
parent 6f1256757f
commit c054f61593
10 changed files with 373 additions and 41 deletions
@@ -8,6 +8,7 @@ use gpui::{
SharedString, Size, WeakEntity, Window, div, px, size,
};
use gpui_component::button::{Button, ButtonVariants};
use gpui_component::checkbox::Checkbox;
use gpui_component::dialog::{DialogDescription, DialogFooter, DialogHeader, DialogTitle};
use gpui_component::form::{field, v_form};
use gpui_component::input::{Input, InputState, Textarea, TextareaState};
@@ -282,9 +283,15 @@ impl PullRequestsView {
}
}
/// Open the "new pull request" dialog: a title, an optional description and
/// a patch input that submit through [`RepoStore::open_pull_request`] when
/// confirmed.
/// State of the new pull request dialog, so the draft checkbox re-renders.
#[derive(Default)]
struct NewPullRequestDialogState {
draft: bool,
}
/// Open the "new pull request" dialog: a title, an optional description,
/// an optional branch name and a patch input that submit through
/// [`RepoStore::open_pull_request`] when confirmed.
pub(super) fn open_new_pull_request_dialog(
store: Entity<RepoStore>,
window: &mut Window,
@@ -293,19 +300,24 @@ pub(super) fn open_new_pull_request_dialog(
let subject = cx.new(|cx| InputState::new(window, cx).placeholder("Pull request title"));
let description =
cx.new(|cx| TextareaState::new(window, cx).placeholder("Describe the change..."));
let branch = cx.new(|cx| InputState::new(window, cx).placeholder("Branch name (optional)"));
let patch = cx
.new(|cx| TextareaState::new(window, cx).placeholder("Paste `git format-patch` output..."));
let state = cx.new(|_| NewPullRequestDialogState::default());
window.open_dialog(cx, move |dialog, _window, _cx| {
let subject = subject.clone();
let description = description.clone();
let branch = branch.clone();
let patch = patch.clone();
let store = store.clone();
let state = state.clone();
dialog
.width(px(520.))
.margin_top(px(50.))
.content(move |body, _window, _cx| {
.content(move |body, _window, cx| {
let draft = state.read(cx).draft;
body.child(
DialogHeader::new()
.child(DialogTitle::new().child("New pull request"))
@@ -327,10 +339,29 @@ pub(super) fn open_new_pull_request_dialog(
.label("Description")
.child(Textarea::new(&description).h(px(96.))),
)
.child(
field()
.label("Branch")
.description("Optional: the branch the change is proposed from")
.child(Input::new(&branch)),
)
.child(
field()
.label("Patch")
.child(Textarea::new(&patch).h(px(160.))),
)
.child(
field().child(
Checkbox::new("pr-draft")
.label("Create as draft")
.checked(draft)
.on_click({
let state = state.clone();
move |checked, _window, cx| {
state.update(cx, |state, _| state.draft = *checked);
}
}),
),
),
)
.child(
@@ -342,17 +373,29 @@ pub(super) fn open_new_pull_request_dialog(
.on_click({
let subject = subject.clone();
let description = description.clone();
let branch = branch.clone();
let patch = patch.clone();
let store = store.clone();
let state = state.clone();
move |_event, window, cx| {
let subject = subject.read(cx).value().to_string();
let description = description.read(cx).value().to_string();
let branch = branch.read(cx).value().to_string();
let patch = patch.read(cx).value().to_string();
let subject = (!subject.is_empty()).then_some(subject);
let branch = (!branch.is_empty()).then_some(branch);
let draft = state.read(cx).draft;
store.update(cx, |store, cx| {
store.open_pull_request(subject, description, patch, cx);
store.open_pull_request(
subject,
description,
branch,
patch,
draft,
cx,
);
});
window.close_dialog(cx);