mirror of
https://github.com/storytold/craft-anything.git
synced 2026-11-05 20:47:45 +01:00
The command palette stays where it's scrolled (#658)
The command palette follows its selection only when the arrow keys or typing move it, so the wheel's scroll isn't pulled back to the top on the next frame (fixes #584).
This commit is contained in:
@@ -101,6 +101,9 @@ pub fn show(app: &mut CraftApp, ctx: &egui::Context) {
|
||||
p.selected = p.selected.saturating_sub(1);
|
||||
}
|
||||
p.selected = p.selected.min(n.saturating_sub(1));
|
||||
// The list follows the selection only when the keys or typing moved it: every frame would pull
|
||||
// the wheel's scroll back to it (#584).
|
||||
let mut follow = down || up;
|
||||
let mut chosen: Option<usize> = None;
|
||||
let screen = ctx.content_rect();
|
||||
let width = 620.0_f32.min(screen.width() - 40.0);
|
||||
@@ -128,6 +131,7 @@ pub fn show(app: &mut CraftApp, ctx: &egui::Context) {
|
||||
r.request_focus();
|
||||
if r.changed() {
|
||||
app.state.palette.selected = 0;
|
||||
follow = true;
|
||||
}
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
@@ -142,7 +146,7 @@ pub fn show(app: &mut CraftApp, ctx: &egui::Context) {
|
||||
if on || r.hovered() {
|
||||
ui.painter().rect_filled(rect, t.radius_sm, if on { t.accent_soft } else { t.hover });
|
||||
}
|
||||
if on {
|
||||
if on && follow {
|
||||
r.scroll_to_me(None);
|
||||
}
|
||||
let (icon, title, sub, tag) = match e {
|
||||
|
||||
@@ -960,6 +960,33 @@ fn command_palette_opens_and_lists_tools() {
|
||||
assert!(!h.state().state.palette.open);
|
||||
}
|
||||
|
||||
/// #584: the palette's list jumped back to the top after every scroll, because the selected row
|
||||
/// asked to be scrolled into view on every frame.
|
||||
#[test]
|
||||
fn the_command_palette_stays_where_it_was_scrolled() {
|
||||
let mut h = harness(|| demo::app(demo::engine(Mode::Experienced, true)));
|
||||
h.run_steps(3);
|
||||
h.key_press_modifiers(egui::Modifiers::COMMAND, egui::Key::K);
|
||||
h.run_steps(3);
|
||||
let before = h.get_by_label("Session status").rect();
|
||||
// Over the list's first rows (this one may be below what the list shows).
|
||||
h.event(egui::Event::PointerMoved(egui::pos2(before.center().x, 250.0)));
|
||||
h.event(egui::Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Point,
|
||||
delta: egui::vec2(0.0, -300.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: egui::Modifiers::NONE,
|
||||
});
|
||||
h.run_steps(20);
|
||||
let after = h.get_by_label("Session status").rect();
|
||||
assert!(after.top() < before.top() - 100.0, "it scrolled and stayed scrolled: {before:?} → {after:?}");
|
||||
// The arrow keys still bring the selection back into view.
|
||||
h.key_press(egui::Key::ArrowDown);
|
||||
h.key_press(egui::Key::ArrowUp);
|
||||
h.run_steps(20);
|
||||
assert_eq!(h.get_by_label("Session status").rect().top(), before.top());
|
||||
}
|
||||
|
||||
/// A stand-in model server whose every answer lists an embedding model, then `qwen3:8b`. Its
|
||||
/// OpenAI-style address.
|
||||
fn model_server() -> String {
|
||||
|
||||
@@ -501,6 +501,8 @@ Gaps found while using the app for real projects.
|
||||
check against DNS rebinding), streams large files instead of reading them into memory,
|
||||
sends no body for HEAD on a missing file, and caps open connections and the time a
|
||||
request may take to arrive (#597, #598, #600, #601, by Afloat16)
|
||||
- [x] The command palette stays where the wheel scrolls it; it follows the selection only when the
|
||||
arrow keys or typing move it (#584)
|
||||
|
||||
### R2.10 Pinned builds
|
||||
Owner: maintainers · Status: in progress
|
||||
|
||||
@@ -564,3 +564,8 @@ parser between JSON recovery and ReAct: count the opener, require a standalone c
|
||||
least that long, and reject an earlier matching close followed by more text. Shorter backtick
|
||||
lines inside a longer fence are content. Test both paths and the next HTTP request, including
|
||||
malformed suffixes and non-call JSON examples whose strings contain protocol markers.
|
||||
|
||||
**A view that asked to be scrolled on every frame.** The command palette called `scroll_to_me` on
|
||||
the selected row each frame, so the wheel's scroll was pulled back to it at once and the list
|
||||
kept jumping to the top (#584). Scroll something into view on the frame it changed (a key, a new
|
||||
query), never as a standing request.
|
||||
|
||||
Reference in New Issue
Block a user