feat add command palette component
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::time::Instant;
|
||||
|
||||
use gpui::{
|
||||
AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render, SharedString,
|
||||
Styled as _, TestAppContext, Window, div,
|
||||
};
|
||||
use gpui_native_core::command_palette::{Command, CommandPalette, CommandPaletteState};
|
||||
use gpui_native_core::init;
|
||||
|
||||
fn command(label: &'static str) -> Command {
|
||||
Command::new(SharedString::from(label), SharedString::from(label))
|
||||
}
|
||||
|
||||
struct Host {
|
||||
palette: Entity<CommandPaletteState>,
|
||||
renders: Rc<RefCell<usize>>,
|
||||
}
|
||||
|
||||
impl Render for Host {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
*self.renders.borrow_mut() += 1;
|
||||
div().size_full().child(self.palette.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typing_with_the_palette_open_is_not_pathologically_slow() {
|
||||
let cx = TestAppContext::single();
|
||||
cx.update(init);
|
||||
let (state, renders, window) = cx.update(|cx| {
|
||||
let renders = Rc::new(RefCell::new(0));
|
||||
let state_cell: Rc<RefCell<Option<Entity<CommandPaletteState>>>> =
|
||||
Rc::new(RefCell::new(None));
|
||||
let renders_for_host = renders.clone();
|
||||
let cell = state_cell.clone();
|
||||
let window = cx
|
||||
.open_window(gpui::WindowOptions::default(), |window, cx| {
|
||||
let matcher = |query: &str, commands: &[Command]| {
|
||||
let query = query.to_lowercase();
|
||||
commands
|
||||
.iter()
|
||||
.filter(|command| command.label.to_lowercase().contains(&query))
|
||||
.cloned()
|
||||
.collect()
|
||||
};
|
||||
let state = cx.new(|cx| {
|
||||
CommandPaletteState::new(
|
||||
CommandPalette::new(
|
||||
"bench-palette",
|
||||
vec![
|
||||
command("Open File"),
|
||||
command("Close Tab"),
|
||||
command("Save All"),
|
||||
command("Toggle Theme"),
|
||||
],
|
||||
matcher,
|
||||
),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let state_for_host = state.clone();
|
||||
cell.borrow_mut().replace(state.clone());
|
||||
cx.new(|_| Host {
|
||||
palette: state_for_host,
|
||||
renders: renders_for_host,
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
let state = state_cell.borrow().clone().expect("state captured");
|
||||
(state, renders, window)
|
||||
});
|
||||
let mut visual = gpui::VisualTestContext::from_window(window.into(), &cx);
|
||||
visual.update(|window, cx| {
|
||||
state.update(cx, |state, cx| state.open(window, cx));
|
||||
window.draw(cx).clear(cx);
|
||||
});
|
||||
|
||||
let started = Instant::now();
|
||||
for letter in "abcdefghijklmnopqrstuvwxyz".chars() {
|
||||
visual.simulate_keystrokes(&letter.to_string());
|
||||
visual.update(|window, cx| {
|
||||
window.draw(cx).clear(cx);
|
||||
});
|
||||
}
|
||||
let elapsed = started.elapsed();
|
||||
|
||||
let total_renders = *renders.borrow();
|
||||
println!(
|
||||
"26 real keystrokes with the palette open: {elapsed:?}, host renders: {total_renders} ({} per keystroke)",
|
||||
total_renders as f32 / 26.
|
||||
);
|
||||
assert!(elapsed.as_millis() < 2000, "typing took {elapsed:?}");
|
||||
}
|
||||
Reference in New Issue
Block a user