127 lines
3.8 KiB
Rust
127 lines
3.8 KiB
Rust
use std::sync::Arc;
|
|
|
|
use crate::{
|
|
api, app,
|
|
component::file_tree::{FileTreeState, file_tree},
|
|
query::{self, QueryStatus, read_query, use_query, watch_query},
|
|
screen::dashboard::pull_request_diff_view::PullRequestDiffView,
|
|
util::{
|
|
self,
|
|
file::{FileTreeItem, FileTreeItemKind},
|
|
},
|
|
};
|
|
use gpui::{AppContext, ParentElement, Styled, div};
|
|
|
|
pub(crate) struct PullRequestChangeView {
|
|
selected_file_path: Option<Arc<str>>,
|
|
diff_view: gpui::Entity<PullRequestDiffView>,
|
|
|
|
file_tree_query: query::Entity<api::issues::FetchPullRequestFileTree>,
|
|
file_tree_state: FileTreeState,
|
|
file_tree_items: Vec<FileTreeItem>,
|
|
}
|
|
|
|
pub(crate) fn new(
|
|
pr_id: api::issues::Id,
|
|
cx: &mut gpui::Context<PullRequestChangeView>,
|
|
) -> PullRequestChangeView {
|
|
let mut view = PullRequestChangeView {
|
|
selected_file_path: None,
|
|
diff_view: cx.new(|cx| PullRequestDiffView::new(pr_id.clone(), cx)),
|
|
|
|
file_tree_query: use_query(
|
|
api::issues::FetchPullRequestFileTree {
|
|
id: pr_id,
|
|
first: 100,
|
|
},
|
|
cx,
|
|
),
|
|
file_tree_state: FileTreeState::new(),
|
|
file_tree_items: Vec::new(),
|
|
};
|
|
view.on_create(cx);
|
|
view
|
|
}
|
|
|
|
impl PullRequestChangeView {
|
|
fn on_create(&mut self, cx: &mut gpui::Context<Self>) {
|
|
watch_query(
|
|
&self.file_tree_query,
|
|
|this, query, cx| {
|
|
if let QueryStatus::Loaded(changed_files) = read_query(query, cx) {
|
|
let tree = util::file::build_file_tree(changed_files, |f| &f.path);
|
|
this.file_tree_state.reset(&tree);
|
|
this.file_tree_items = tree;
|
|
cx.notify();
|
|
};
|
|
},
|
|
cx,
|
|
)
|
|
.detach();
|
|
}
|
|
|
|
fn handle_file_tree_item_click(
|
|
&mut self,
|
|
i: usize,
|
|
window: &mut gpui::Window,
|
|
cx: &mut gpui::Context<Self>,
|
|
) {
|
|
let item = &self.file_tree_items[i];
|
|
match item.kind {
|
|
| FileTreeItemKind::Directory => {
|
|
self.file_tree_state
|
|
.toggle_directory(&item.full_path, &self.file_tree_items);
|
|
cx.notify();
|
|
}
|
|
| FileTreeItemKind::File => {
|
|
self.selected_file_path = Some(Arc::clone(&item.full_path));
|
|
self.file_tree_state.highlight_item(i);
|
|
self.diff_view.update(cx, |diff_view, cx| {
|
|
diff_view.show_diff_for_file(&item.full_path, cx);
|
|
});
|
|
cx.focus_view(&self.diff_view, window);
|
|
cx.notify();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl gpui::Render for PullRequestChangeView {
|
|
fn render(
|
|
&mut self,
|
|
_window: &mut gpui::Window,
|
|
cx: &mut gpui::Context<Self>,
|
|
) -> impl gpui::IntoElement {
|
|
let theme = app::current_theme(cx);
|
|
let weak = cx.entity();
|
|
|
|
div()
|
|
.size_full()
|
|
.flex()
|
|
.flex_row()
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.w_80()
|
|
.h_full()
|
|
.bg(theme.colors.surface_chrome)
|
|
.border_r_1()
|
|
.border_color(theme.colors.border_muted)
|
|
.child(
|
|
file_tree(self.file_tree_state.clone(), move |i, _, cx| {
|
|
weak.read(cx).file_tree_items[i].clone()
|
|
})
|
|
.on_item_click(cx.listener(
|
|
|this, i, window, cx| {
|
|
this.handle_file_tree_item_click(*i, window, cx);
|
|
},
|
|
)),
|
|
),
|
|
)
|
|
.child(
|
|
gpui::AnyView::from(self.diff_view.clone())
|
|
.cached(gpui::StyleRefinement::default().size_full()),
|
|
)
|
|
}
|
|
}
|