feat: add combobox filter

This commit is contained in:
2026-11-06 21:27:31 +07:00
parent 265d2d129b
commit 0ad5c3fe90
8 changed files with 256 additions and 65 deletions
+35 -24
View File
@@ -5,7 +5,8 @@ use std::time::Duration;
use gpui::prelude::FluentBuilder as _;
use gpui::{
AnyView, App, ClipboardItem, ElementId, Entity, IntoElement, RenderOnce, SharedString, Window,
AnyView, App, ClipboardItem, ElementId, Entity, IntoElement, RenderOnce, SharedString, Task,
Window,
};
use gpui_native_icons::IconRole;
use gpui_native_theme::Size;
@@ -92,11 +93,22 @@ impl Sizable for ClipboardButton {
}
}
/// The transient copied marker keyed per button.
struct CopiedState {
generation: u64,
tasks: Vec<Task<()>>,
}
impl RenderOnce for ClipboardButton {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let copied: Entity<Option<u64>> =
window.use_keyed_state((self.id.clone(), "clipboard-copied"), cx, |_, _| None);
let is_copied = copied.read(cx).is_some();
let copied: Entity<CopiedState> =
window.use_keyed_state((self.id.clone(), "clipboard-copied"), cx, |_, _| {
CopiedState {
generation: 0,
tasks: Vec::new(),
}
});
let is_copied = copied.read(cx).generation != 0;
let selector = if is_copied {
"clipboard-copied"
@@ -126,30 +138,29 @@ impl RenderOnce for ClipboardButton {
cx.write_to_clipboard(ClipboardItem::new_string(value.to_string()));
let generation = copied.update(cx, |state, cx| {
let generation = state.map_or(1, |generation| generation.wrapping_add(1));
*state = Some(generation);
state.generation += 1;
cx.notify();
generation
state.generation
});
// Clear the copied state after the duration expires
window
.spawn(cx, {
let copied = copied.clone();
async move |cx| {
cx.background_executor().timer(COPIED_DURATION).await;
cx.update(|_, cx| {
copied.update(cx, |state, cx| {
if *state == Some(generation) {
*state = None;
cx.notify();
}
})
})
.ok();
}
let weak = copied.downgrade();
let task = window.spawn(cx, async move |cx| {
cx.background_executor().timer(COPIED_DURATION).await;
cx.update(|_, cx| {
weak.update(cx, |state, cx| {
if state.generation == generation {
state.generation = 0;
cx.notify();
}
})
.ok();
})
.detach();
.ok();
});
copied.update(cx, |state, _| {
state.tasks.push(task);
});
// Invoke the callback after copying
if let Some(on_copied) = &on_copied {