C14.8 r1: the outline scrolls in its pane
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
53ce8eec0b
commit
1539c3a018
6 files changed
+67
-9
No files matched your search
@@ -40,7 +40,7 @@ pub struct Desk {
|
||||
pub going: Option<(PathBuf, usize)>,
|
||||
/// The path each tab last put in the recent list.
|
||||
pub remembered: HashMap<u64, PathBuf>,
|
||||
side: Entity<crate::side::Side>,
|
||||
pub(crate) side: Entity<crate::side::Side>,
|
||||
pub watcher: Option<notify::RecommendedWatcher>,
|
||||
/// The folders the watcher covers.
|
||||
pub watched: Vec<PathBuf>,
|
||||
@@ -449,4 +449,4 @@ fn large_banner(
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
pub(crate) mod tests;
|
||||
@@ -7,7 +7,7 @@ use super::{Desk, open_in};
|
||||
use crate::view::Mode;
|
||||
|
||||
/// ElyMark over a fresh data folder, as `main` opens it.
|
||||
fn start(cx: &mut TestAppContext, data: &Path) -> (Entity<Desk>, &'static mut VisualTestContext) {
|
||||
pub(crate) fn start(cx: &mut TestAppContext, data: &Path) -> (Entity<Desk>, &'static mut VisualTestContext) {
|
||||
// The file watcher runs on a real thread.
|
||||
cx.executor().allow_parking();
|
||||
cx.update(ely_gpui_component::init_for_tests);
|
||||
@@ -33,7 +33,7 @@ fn start(cx: &mut TestAppContext, data: &Path) -> (Entity<Desk>, &'static mut Vi
|
||||
(desk, cx)
|
||||
}
|
||||
|
||||
fn open(desk: &Entity<Desk>, path: &Path, cx: &mut VisualTestContext) {
|
||||
pub(crate) fn open(desk: &Entity<Desk>, path: &Path, cx: &mut VisualTestContext) {
|
||||
desk.update(cx, |desk, cx| desk.open_path(path.to_path_buf(), cx));
|
||||
cx.run_until_parked();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use ely_gpui_component::{
|
||||
buttons::{Button, SegmentedControl},
|
||||
feedback::EmptyState,
|
||||
forms::{InputEvent, SearchInput, TextInput},
|
||||
layout::ScrollArea,
|
||||
lists::{FileTree, ListItem, Outline, SelectableList},
|
||||
primitives::IconName,
|
||||
theme::ControlSize,
|
||||
@@ -13,7 +14,8 @@ use ely_gpui_component::{
|
||||
use ely_office::prelude::*;
|
||||
use ely_ui::{commands, i18n::text};
|
||||
use gpui::{
|
||||
AnyElement, AppContext as _, Context, Entity, IntoElement, ParentElement as _, Render,
|
||||
AnyElement, AppContext as _, Context, Entity, InteractiveElement as _, IntoElement,
|
||||
ParentElement as _, Render,
|
||||
SharedString, Styled as _, WeakEntity, Window, div,
|
||||
};
|
||||
|
||||
@@ -248,15 +250,18 @@ impl Side {
|
||||
outline.item(at.to_string(), heading.title.clone(), heading.level)
|
||||
},
|
||||
);
|
||||
outline
|
||||
.on_select(move |key, window, cx| {
|
||||
let outline = outline.on_select(move |key, window, cx| {
|
||||
let Some(heading) = key.parse::<usize>().ok().and_then(|at| headings.get(at)) else {
|
||||
return log::error!("mark: the outline chose no heading");
|
||||
};
|
||||
// The heading in view, the caret on it.
|
||||
let line = heading.line;
|
||||
view.update(cx, |view, cx| view.reveal(line, window, cx));
|
||||
})
|
||||
});
|
||||
ScrollArea::new("mark-outline-scroll")
|
||||
.vertical()
|
||||
.size_full()
|
||||
.child(div().debug_selector(|| "mark-outline".into()).child(outline))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -374,3 +379,6 @@ impl Render for Side {
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@@ -0,0 +1,47 @@
|
||||
use gpui::{ScrollDelta, ScrollWheelEvent, TestAppContext, point, px};
|
||||
|
||||
use super::Pane;
|
||||
use crate::desk::tests::{open, start};
|
||||
|
||||
#[gpui::test]
|
||||
fn a_long_outline_scrolls_to_its_last_heading(cx: &mut TestAppContext) {
|
||||
let (data, files) = (
|
||||
tempfile::tempdir().expect("data"),
|
||||
tempfile::tempdir().expect("files"),
|
||||
);
|
||||
let path = files.path().join("long.md");
|
||||
let text: String = (0..100).map(|n| format!("# Heading {n}\n\n")).collect();
|
||||
std::fs::write(&path, text).expect("a file");
|
||||
let (desk, cx) = start(cx, data.path());
|
||||
open(&desk, &path, cx);
|
||||
let side = desk.read_with(cx, |desk, _| desk.side.clone());
|
||||
side.update(cx, |side, cx| {
|
||||
side.pane = Pane::Outline;
|
||||
cx.notify();
|
||||
});
|
||||
cx.run_until_parked();
|
||||
let before = cx
|
||||
.debug_bounds("mark-outline")
|
||||
.expect("the outline is drawn");
|
||||
let window = cx.update(|window, _| window.viewport_size());
|
||||
assert!(
|
||||
before.bottom() > window.height,
|
||||
"the outline is longer than the window"
|
||||
);
|
||||
let at = point(before.left() + px(20.0), px(300.0));
|
||||
for _ in 0..20 {
|
||||
cx.simulate_event(ScrollWheelEvent {
|
||||
position: at,
|
||||
delta: ScrollDelta::Pixels(point(px(0.0), px(-1000.0))),
|
||||
..Default::default()
|
||||
});
|
||||
cx.run_until_parked();
|
||||
}
|
||||
let after = cx
|
||||
.debug_bounds("mark-outline")
|
||||
.expect("the outline is drawn");
|
||||
assert!(
|
||||
after.bottom() <= window.height,
|
||||
"the last heading is in view: {after:?}"
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user