feat: pr file tree item switching
This commit is contained in:
119
src/screen/dashboard/pull_request_change_view.rs
Normal file
119
src/screen/dashboard/pull_request_change_view.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
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, 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.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)
|
||||
.p_1()
|
||||
.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, _, cx| {
|
||||
this.handle_file_tree_item_click(*i, cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
gpui::AnyView::from(self.diff_view.clone())
|
||||
.cached(gpui::StyleRefinement::default().size_full()),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user