feat: add dummy search bar in diff view

This commit is contained in:
2026-05-31 00:45:25 +01:00
parent 4a7ebf660e
commit f5ebb210ac
11 changed files with 1273 additions and 262 deletions

View File

@@ -1,6 +1,6 @@
mod issue_list;
mod pull_request_change_view;
mod pull_request_diff_view;
pub(crate) mod pull_request_diff_view;
mod pull_request_file_tree;
mod pull_request_view;
mod screen;

View File

@@ -60,22 +60,28 @@ impl PullRequestChangeView {
.detach();
}
fn handle_file_tree_item_click(&mut self, i: usize, cx: &mut gpui::Context<Self>) {
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.notify();
}
| 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();
}
}
}
}
@@ -106,9 +112,11 @@ impl gpui::Render for PullRequestChangeView {
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);
})),
.on_item_click(cx.listener(
|this, i, window, cx| {
this.handle_file_tree_item_click(*i, window, cx);
},
)),
),
)
.child(

View File

@@ -1,11 +1,17 @@
use std::sync::Arc;
use gpui::{AppContext, IntoElement, div};
use gpui::{
AppContext, FocusHandle, InteractiveElement, IntoElement, ParentElement, Styled, div,
prelude::FluentBuilder,
};
use crate::{
api::{self},
app,
component::diff_view::{DiffViewContent, DiffViewState, diff_view},
component::{
diff_view::{DiffViewContent, DiffViewState, diff_view},
text_input::{TextInput, text_input},
},
query::{self, QueryStatus, read_query, use_query, watch_query},
util,
};
@@ -16,8 +22,16 @@ pub(crate) struct PullRequestDiffView {
diff_view_state: DiffViewState,
diff_view_content: Option<DiffViewContent>,
current_file_path: Option<Arc<str>>,
focus_handle: gpui::FocusHandle,
is_search_input_visible: bool,
search_input: gpui::Entity<TextInput>,
}
gpui::actions!([Search, Escape]);
const KEY_CONTEXT: &'static str = "PullRequestDiffView";
impl PullRequestDiffView {
pub(crate) fn new(pr_id: api::issues::Id, cx: &mut gpui::Context<Self>) -> Self {
let mut s = Self {
@@ -26,11 +40,22 @@ impl PullRequestDiffView {
diff_view_state: DiffViewState::new(),
diff_view_content: None,
current_file_path: None,
focus_handle: cx.focus_handle(),
is_search_input_visible: false,
search_input: cx.new(|cx| TextInput::with_placeholder("Search", cx)),
};
s.on_create(cx);
s
}
pub(crate) fn key_bindings() -> [gpui::KeyBinding; 2] {
[
gpui::KeyBinding::new("cmd-f", Search, Some(KEY_CONTEXT)),
gpui::KeyBinding::new("escape", Escape, Some(KEY_CONTEXT)),
]
}
pub(crate) fn show_diff_for_file(
&mut self,
file_path: &Arc<str>,
@@ -146,6 +171,24 @@ impl PullRequestDiffView {
.detach();
}
}
fn open_search_box(&mut self, window: &mut gpui::Window, cx: &mut gpui::Context<Self>) {
self.is_search_input_visible = true;
cx.focus_view(&self.search_input, window);
cx.notify();
}
fn close_search_box(&mut self, window: &mut gpui::Window, cx: &mut gpui::Context<Self>) {
self.is_search_input_visible = false;
self.focus_handle.focus(window);
cx.notify();
}
}
impl gpui::Focusable for PullRequestDiffView {
fn focus_handle(&self, _: &gpui::App) -> FocusHandle {
self.focus_handle.clone()
}
}
impl gpui::Render for PullRequestDiffView {
@@ -154,18 +197,49 @@ impl gpui::Render for PullRequestDiffView {
_window: &mut gpui::Window,
cx: &mut gpui::prelude::Context<Self>,
) -> impl gpui::IntoElement {
let theme = app::current_theme(cx);
let content_diff = self
.content_diff_query
.as_ref()
.map(|q| read_query(q, cx))
.unwrap_or(QueryStatus::Loading);
match (content_diff, &self.diff_view_content) {
| (QueryStatus::Loaded(_), Some(content)) => {
diff_view(self.diff_view_state.clone(), content.clone()).into_any_element()
}
| (_, _) => div().into_any_element(),
}
div()
.id(KEY_CONTEXT)
.key_context(KEY_CONTEXT)
.track_focus(&self.focus_handle)
.flex()
.flex_col()
.size_full()
.when(self.is_search_input_visible, |it| {
it.child(
text_input(self.search_input.clone())
.w_full()
.text_color(theme.colors.text)
.text_xs()
.px_3()
.bg(theme.colors.surface_chrome)
.border_0()
.border_b_1()
.border_color(theme.colors.border_muted),
)
})
.when_some(
match (content_diff, &self.diff_view_content) {
| (QueryStatus::Loaded(_), Some(content)) => Some(content.clone()),
| (_, _) => None,
},
|it, content| {
it.child(
diff_view(self.diff_view_state.clone(), content.clone()).into_any_element(),
)
},
)
.on_action(cx.listener(|this, _: &Search, window, cx| {
this.open_search_box(window, cx);
}))
.on_action(cx.listener(|this, _: &Escape, window, cx| {
this.close_search_box(window, cx);
}))
}
}