search: Fix recently introduced issues with the search bars (#36271)

Follow-up to https://github.com/zed-industries/zed/pull/36233

The above PR simplified the handling but introduced some bugs: The
replace buttons were no longer clickable, some buttons also lost their
toggle states, some buttons shared their element id and, lastly, some
buttons were clickable but would not trigger the right action. This PR
fixes all that.

Release Notes:

- N/A
This commit is contained in:
Finn Evers 2025-08-15 22:21:21 +02:00 committed by GitHub
parent 2a9d4599cd
commit 65f64aa513
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 114 additions and 65 deletions

View file

@ -1,7 +1,7 @@
use bitflags::bitflags;
pub use buffer_search::BufferSearchBar;
use editor::SearchSettings;
use gpui::{Action, App, FocusHandle, IntoElement, actions};
use gpui::{Action, App, ClickEvent, FocusHandle, IntoElement, actions};
use project::search::SearchQuery;
pub use project_search::ProjectSearchView;
use ui::{ButtonStyle, IconButton, IconButtonShape};
@ -11,6 +11,8 @@ use workspace::{Toast, Workspace};
pub use search_status_button::SEARCH_ICON;
use crate::project_search::ProjectSearchBar;
pub mod buffer_search;
pub mod project_search;
pub(crate) mod search_bar;
@ -83,9 +85,14 @@ pub enum SearchOption {
Backwards,
}
pub(crate) enum SearchSource<'a, 'b> {
Buffer,
Project(&'a Context<'b, ProjectSearchBar>),
}
impl SearchOption {
pub fn as_options(self) -> SearchOptions {
SearchOptions::from_bits(1 << self as u8).unwrap()
pub fn as_options(&self) -> SearchOptions {
SearchOptions::from_bits(1 << *self as u8).unwrap()
}
pub fn label(&self) -> &'static str {
@ -119,25 +126,41 @@ impl SearchOption {
}
}
pub fn as_button(&self, active: SearchOptions, focus_handle: FocusHandle) -> impl IntoElement {
pub(crate) fn as_button(
&self,
active: SearchOptions,
search_source: SearchSource,
focus_handle: FocusHandle,
) -> impl IntoElement {
let action = self.to_toggle_action();
let label = self.label();
IconButton::new(label, self.icon())
.on_click({
IconButton::new(
(label, matches!(search_source, SearchSource::Buffer) as u32),
self.icon(),
)
.map(|button| match search_source {
SearchSource::Buffer => {
let focus_handle = focus_handle.clone();
move |_, window, cx| {
button.on_click(move |_: &ClickEvent, window, cx| {
if !focus_handle.is_focused(&window) {
window.focus(&focus_handle);
}
window.dispatch_action(action.boxed_clone(), cx)
}
})
.style(ButtonStyle::Subtle)
.shape(IconButtonShape::Square)
.toggle_state(active.contains(self.as_options()))
.tooltip({
move |window, cx| Tooltip::for_action_in(label, action, &focus_handle, window, cx)
})
window.dispatch_action(action.boxed_clone(), cx);
})
}
SearchSource::Project(cx) => {
let options = self.as_options();
button.on_click(cx.listener(move |this, _: &ClickEvent, window, cx| {
this.toggle_search_option(options, window, cx);
}))
}
})
.style(ButtonStyle::Subtle)
.shape(IconButtonShape::Square)
.toggle_state(active.contains(self.as_options()))
.tooltip({
move |window, cx| Tooltip::for_action_in(label, action, &focus_handle, window, cx)
})
}
}