feat: pr tab switching btwn body/diff
This commit is contained in:
@@ -157,8 +157,8 @@ impl gpui::RenderOnce for IssueListItem {
|
||||
}
|
||||
|
||||
let repo_name_text = match self.repo_name {
|
||||
| Some(name) => text(name),
|
||||
| None => text("Unknown repo"),
|
||||
| Some(name) => text(name),
|
||||
| None => text("Unknown repo"),
|
||||
}
|
||||
.text_xs()
|
||||
.opacity(0.5);
|
||||
@@ -171,21 +171,21 @@ impl gpui::RenderOnce for IssueListItem {
|
||||
.bg(theme.colors.surface)
|
||||
} else {
|
||||
match self.status {
|
||||
| api::issues::PullRequestState::Closed => pill(
|
||||
text("Closed").text_color(theme.colors.danger_on_solid),
|
||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.bg(theme.colors.danger_solid),
|
||||
| api::issues::PullRequestState::Merged => pill(
|
||||
text("Merged").text_color(theme.colors.accent_on_solid),
|
||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.accent_on_solid),
|
||||
)
|
||||
.bg(theme.colors.accent_solid),
|
||||
| _ => pill(
|
||||
text("Open").text_color(theme.colors.success_on_solid),
|
||||
font_icon(FontIcon::PullRequestArrow).text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.bg(theme.colors.success_solid),
|
||||
| api::issues::PullRequestState::Closed => pill(
|
||||
text("Closed").text_color(theme.colors.danger_on_solid),
|
||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.bg(theme.colors.danger_solid),
|
||||
| api::issues::PullRequestState::Merged => pill(
|
||||
text("Merged").text_color(theme.colors.accent_on_solid),
|
||||
font_icon(FontIcon::PullRequestClosed).text_color(theme.colors.accent_on_solid),
|
||||
)
|
||||
.bg(theme.colors.accent_solid),
|
||||
| _ => pill(
|
||||
text("Open").text_color(theme.colors.success_on_solid),
|
||||
font_icon(FontIcon::PullRequestArrow).text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.bg(theme.colors.success_solid),
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -117,8 +117,8 @@ impl PullRequestDiffView {
|
||||
) {
|
||||
if let Some(diff) = {
|
||||
match read_query(query, cx) {
|
||||
| QueryStatus::Loaded(diff) => Some(Arc::clone(diff)),
|
||||
| _ => None,
|
||||
| QueryStatus::Loaded(diff) => Some(Arc::clone(diff)),
|
||||
| _ => None,
|
||||
}
|
||||
} {
|
||||
self.load_diff_view(diff, cx);
|
||||
@@ -153,16 +153,16 @@ impl PullRequestDiffView {
|
||||
|
||||
_ = cx
|
||||
.spawn(async move |weak, cx| match tokio::join!(t1, t2) {
|
||||
| (Some(old_side_highlights), Some(new_side_highlights)) => {
|
||||
_ = weak.update(cx, |this, cx| {
|
||||
this.diff_view_state
|
||||
.set_old_side_highlights(old_side_highlights);
|
||||
this.diff_view_state
|
||||
.set_new_side_highlights(new_side_highlights);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
| _ => {}
|
||||
| (Some(old_side_highlights), Some(new_side_highlights)) => {
|
||||
_ = weak.update(cx, |this, cx| {
|
||||
this.diff_view_state
|
||||
.set_old_side_highlights(old_side_highlights);
|
||||
this.diff_view_state
|
||||
.set_new_side_highlights(new_side_highlights);
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
| _ => {}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -184,18 +184,18 @@ impl gpui::Render for PullRequestDiffView {
|
||||
.unwrap_or(QueryStatus::Loading);
|
||||
|
||||
match content_diff {
|
||||
| QueryStatus::Err(_) | QueryStatus::Loading => div()
|
||||
.size_full()
|
||||
.bg(theme.colors.surface)
|
||||
.p_4()
|
||||
.child(text("asd")),
|
||||
| QueryStatus::Err(_) | QueryStatus::Loading => div()
|
||||
.size_full()
|
||||
.bg(theme.colors.surface)
|
||||
.p_4()
|
||||
.child(text("asd")),
|
||||
|
||||
| QueryStatus::Loaded(_) => match &self.diff_view_content {
|
||||
| Some(content) => div()
|
||||
.size_full()
|
||||
.child(diff_view(self.diff_view_state.clone(), content.clone())),
|
||||
| None => div(),
|
||||
},
|
||||
| QueryStatus::Loaded(_) => match &self.diff_view_content {
|
||||
| Some(content) => div()
|
||||
.size_full()
|
||||
.child(diff_view(self.diff_view_state.clone(), content.clone())),
|
||||
| None => div(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||
|
||||
use gpui::{
|
||||
AppContext, InteractiveElement, IntoElement, ParentElement, StatefulInteractiveElement, Styled,
|
||||
div, img, linear_gradient, prelude::FluentBuilder,
|
||||
div, img, prelude::FluentBuilder,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -12,6 +12,7 @@ use crate::{
|
||||
button::{self, Button, button},
|
||||
font_icon::{FontIcon, font_icon},
|
||||
markdown::{self, MarkdownText},
|
||||
segmented_control::segmented_control,
|
||||
text::text,
|
||||
},
|
||||
query::{self, QueryStatus, read_query, use_query, watch_query},
|
||||
@@ -19,17 +20,23 @@ use crate::{
|
||||
};
|
||||
|
||||
pub(crate) struct PullRequestView {
|
||||
current_tab: Tab,
|
||||
|
||||
markdown_viewer: Option<gpui::Entity<MarkdownText>>,
|
||||
diff_view: Option<gpui::Entity<PullRequestDiffView>>,
|
||||
|
||||
pull_request_query: Option<query::Entity<api::issues::FetchPullRequest>>,
|
||||
}
|
||||
|
||||
#[derive(gpui::IntoElement)]
|
||||
struct Toolbar {}
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Tab {
|
||||
PullRequestBody,
|
||||
DiffView,
|
||||
}
|
||||
|
||||
pub fn new(_cx: &mut gpui::Context<PullRequestView>) -> PullRequestView {
|
||||
PullRequestView {
|
||||
current_tab: Tab::PullRequestBody,
|
||||
markdown_viewer: None,
|
||||
diff_view: None,
|
||||
pull_request_query: None,
|
||||
@@ -45,6 +52,7 @@ impl PullRequestView {
|
||||
let query = use_query(api::issues::FetchPullRequest { id }, cx);
|
||||
|
||||
self.pull_request_query = Some(query.clone());
|
||||
self.current_tab = Tab::PullRequestBody;
|
||||
|
||||
_ = watch_query(&query, Self::sync_pull_request_query, cx).detach();
|
||||
|
||||
@@ -98,6 +106,65 @@ impl PullRequestView {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn toolbar(&self, cx: &gpui::Context<Self>) -> gpui::AnyElement {
|
||||
fn toolbar_button(id: impl Into<gpui::ElementId>) -> Button {
|
||||
button(id)
|
||||
.px_2p5()
|
||||
.py_1()
|
||||
.variant(button::Variant::Secondary)
|
||||
.border_0()
|
||||
}
|
||||
|
||||
fn divider() -> gpui::Div {
|
||||
div().h_full().w_px()
|
||||
}
|
||||
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
div()
|
||||
.w_full()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.items_center()
|
||||
.justify_start()
|
||||
.p_1()
|
||||
.bg(theme.colors.surface)
|
||||
.border_b_1()
|
||||
.border_color(theme.colors.border_muted)
|
||||
.child(
|
||||
segmented_control()
|
||||
.selected_value(self.current_tab)
|
||||
.item(Tab::PullRequestBody, FontIcon::MessageCircleMore)
|
||||
.item(Tab::DiffView, FontIcon::FileBracesCorner)
|
||||
.on_select(cx.listener(|this, tab, _, cx| {
|
||||
this.current_tab = *tab;
|
||||
cx.notify();
|
||||
})),
|
||||
)
|
||||
.child(div().flex_1())
|
||||
.child(
|
||||
toolbar_button("pr-close-btn")
|
||||
.leading(font_icon(FontIcon::PullRequestClosed))
|
||||
.mr_1(),
|
||||
)
|
||||
.child(
|
||||
toolbar_button("pr-merge-btn")
|
||||
.variant(button::Variant::Primary)
|
||||
.leading(font_icon(FontIcon::GitMerge))
|
||||
.rounded_r_none(),
|
||||
)
|
||||
.child(divider())
|
||||
.child(
|
||||
toolbar_button("chevron")
|
||||
.py_1()
|
||||
.px_0p5()
|
||||
.variant(button::Variant::Primary)
|
||||
.leading(font_icon(FontIcon::ChevronDown))
|
||||
.rounded_l_none(),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn pr_content(
|
||||
&self,
|
||||
pr: &api::issues::DetailedPullRequest,
|
||||
@@ -114,41 +181,41 @@ impl PullRequestView {
|
||||
.rounded_full();
|
||||
|
||||
match pr.state {
|
||||
| api::issues::PullRequestState::Open => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.success_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestArrow)
|
||||
.size_3()
|
||||
.text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Open")
|
||||
.text_color(theme.colors.success_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Closed => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.danger_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestClosed)
|
||||
.size_3()
|
||||
.text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Closed")
|
||||
.text_color(theme.colors.danger_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Merged => {
|
||||
status_pill = status_pill.bg(theme.colors.accent_solid).child(
|
||||
text("Merged")
|
||||
.text_color(theme.colors.accent_on_solid)
|
||||
| api::issues::PullRequestState::Open => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.success_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestArrow)
|
||||
.size_3()
|
||||
.text_color(theme.colors.success_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Open")
|
||||
.text_color(theme.colors.success_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
}
|
||||
| api::issues::PullRequestState::Closed => {
|
||||
status_pill = status_pill
|
||||
.bg(theme.colors.danger_solid)
|
||||
.child(
|
||||
font_icon(FontIcon::PullRequestClosed)
|
||||
.size_3()
|
||||
.text_color(theme.colors.danger_on_solid),
|
||||
)
|
||||
.child(
|
||||
text("Closed")
|
||||
.text_color(theme.colors.danger_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
| api::issues::PullRequestState::Merged => {
|
||||
status_pill = status_pill.bg(theme.colors.accent_solid).child(
|
||||
text("Merged")
|
||||
.text_color(theme.colors.accent_on_solid)
|
||||
.text_xs(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let merge_text = pr.author.as_ref().map(|author| {
|
||||
@@ -228,7 +295,6 @@ impl PullRequestView {
|
||||
.flex_col()
|
||||
.bg(theme.colors.surface)
|
||||
.overflow_hidden()
|
||||
.child(Toolbar {})
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
@@ -282,9 +348,18 @@ impl gpui::Render for PullRequestView {
|
||||
_window: &mut gpui::Window,
|
||||
cx: &mut gpui::Context<Self>,
|
||||
) -> impl gpui::IntoElement {
|
||||
div().size_full().child(match &self.pull_request_query {
|
||||
| Some(q) => match read_query(q, cx) {
|
||||
| QueryStatus::Loaded(pr) => self.pr_content(pr, cx),
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.child(self.toolbar(cx))
|
||||
.child(match &self.pull_request_query {
|
||||
| Some(q) => {
|
||||
match read_query(q, cx) {
|
||||
| QueryStatus::Loaded(pr) => match (&self.diff_view, self.current_tab) {
|
||||
| (Some(diff_view), Tab::DiffView) => diff_view.clone().into_any_element(),
|
||||
| _ => self.pr_content(pr, cx),
|
||||
},
|
||||
|
||||
| QueryStatus::Err(e) => div()
|
||||
.size_full()
|
||||
@@ -294,83 +369,10 @@ impl gpui::Render for PullRequestView {
|
||||
.size_full()
|
||||
.child("loading pr content")
|
||||
.into_any_element(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
| None => div().size_full().child("no pr selected").into_any_element(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl gpui::RenderOnce for Toolbar {
|
||||
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
|
||||
fn toolbar_button(id: impl Into<gpui::ElementId>) -> Button {
|
||||
button(id)
|
||||
.px_2p5()
|
||||
.py_1()
|
||||
.variant(button::Variant::Secondary)
|
||||
.border_0()
|
||||
}
|
||||
|
||||
fn divider() -> gpui::Div {
|
||||
div().h_full().w_px()
|
||||
}
|
||||
|
||||
let theme = app::current_theme(cx);
|
||||
|
||||
div()
|
||||
.w_full()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.items_center()
|
||||
.justify_start()
|
||||
.p_1()
|
||||
.bg(theme.colors.surface)
|
||||
.border_b_1()
|
||||
.border_color(theme.colors.border_muted)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.border_t_1()
|
||||
.border_color(theme.colors.border_strong)
|
||||
.rounded_sm()
|
||||
.child(
|
||||
div()
|
||||
.px_2()
|
||||
.py_1()
|
||||
.bg(theme.colors.surface_elevated)
|
||||
.child(font_icon(FontIcon::MessageCircleMore).size_3p5()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.px_2()
|
||||
.py_1()
|
||||
.bg(theme.colors.surface_elevated)
|
||||
.child(font_icon(FontIcon::FileBracesCorner).size_3p5()),
|
||||
),
|
||||
)
|
||||
.child(div().flex_1())
|
||||
.child(
|
||||
toolbar_button("pr-close-btn")
|
||||
.leading(font_icon(FontIcon::PullRequestClosed))
|
||||
.mr_1(),
|
||||
)
|
||||
.child(
|
||||
toolbar_button("pr-merge-btn")
|
||||
.variant(button::Variant::Primary)
|
||||
.leading(font_icon(FontIcon::GitMerge))
|
||||
.rounded_r_none(),
|
||||
)
|
||||
.child(divider())
|
||||
.child(
|
||||
toolbar_button("chevron")
|
||||
.py_1()
|
||||
.px_0p5()
|
||||
.variant(button::Variant::Primary)
|
||||
.leading(font_icon(FontIcon::ChevronDown))
|
||||
.rounded_l_none(),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user