Files
novem/src/screen/dashboard/pull_request_change_view.rs

120 lines
3.7 KiB
Rust
Raw Normal View History

2026-05-28 22:28:59 +01:00
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()),
)
}
}