alt scroll via context and couple fixes
[?]
Jul 15, 2025, 3:47 PM
3TLPJ57B2OD5OWJN5WMS7A4W7IGFUWJJHVIXRM34VT6KUN6R4YSACDependencies
- [2]
S2NVIFXRallow to enter record msg - [3]
D7A7MSIHallow to defer or abandon record, add buttons - [4]
23SFYK4Qbig view refactor into a new crate - [5]
WW36JYLRadd iced_nav_scrollable widget crate - [6]
KWTBNTO3diffs selection and scrolling - [7]
5MUEECMJsmooth scrolling nav - [8]
XHWLKCLDauto-scroll past skip sections on load - [9]
L6KSEFQImove cursor related stuff into its module - [*]
XSZZB47Urefactor stuff into lib - [*]
6YZAVBWUInitial commit - [*]
WT3GA27Padd cursor with selection
Change contents
- edit in inflorescence_view/src/cursor.rs at line 9
/// Directional key press with a modifierAltPressDir(Dir), - edit in inflorescence/src/main.rs at line 873
}"j" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Down),)))}"k" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Up),))) - edit in inflorescence/src/main.rs at line 884
"h" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Left),)))}"l" if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Right),)))} - edit in inflorescence/src/main.rs at line 896
Key::Named(key::Named::ArrowDown)if mods == Modifiers::SHIFT =>{Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Down,))))}Key::Named(key::Named::ArrowUp) if mods == Modifiers::SHIFT => {Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Up,))))}Key::Named(key::Named::ArrowLeft)if mods == Modifiers::SHIFT =>{Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Left,))))}Key::Named(key::Named::ArrowRight)if mods == Modifiers::SHIFT =>{Some(Msg::View(app::Msg::Cursor(cursor::Msg::AltPressDir(cursor::Dir::Right,))))} - replacement in inflorescence/src/cursor.rs at line 24
let delta = state.held_key.as_ref().and_then(|HeldKey {dir: held_dir,last_tick,}| {(dir == *held_dir).then(|| {// Ceil to 50 ms, because the first key repeat in Iced// is delayed 500 ms and that creates too much of a jumpcmp::min(Duration::from_millis(50),Instant::now() - *last_tick,)})},);let delta = {state.held_key.as_ref().and_then(|HeldKey {dir: held_dir,last_tick,}| {(dir == *held_dir).then(|| {// Ceil to 50 ms, because the first key repeat in// Iced is delayed 500// ms and that creates too much of a jumpcmp::min(Duration::from_millis(50),Instant::now() - *last_tick,)})},)}; - edit in inflorescence/src/cursor.rs at line 64
Msg::AltPressDir(dir) => {let delta = {state.held_key.as_ref().and_then(|HeldKey {dir: held_dir,last_tick,}| {(dir == *held_dir).then(|| {// Ceil to 50 ms, because the first key repeat in// Iced is delayed 500// ms and that creates too much of a jumpcmp::min(Duration::from_millis(50),Instant::now() - *last_tick,)})},)};state.held_key = Some(HeldKey {dir,last_tick: Instant::now(),});match dir {Dir::Down => {alt_select_down(state, files_diffs, log_diffs, delta)}Dir::Up => alt_select_up(state, files_diffs, log_diffs, delta),Dir::Left | Dir::Right => {// Nothing here yetTask::none()}}} - edit in inflorescence/src/cursor.rs at line 576
}}fn alt_select_down<M>(state: &mut State,files_diffs: &mut diff::FilesState,logs: &mut diff::LogFilesAndState,delta: Option<Duration>,) -> Task<M> {match state.selection.as_mut() {Some(Selection::UntrackedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);if let Some(nav) = files_diffs.get_mut(&id_hash).and_then(|state| state.nav.as_mut()){iced_nav_scrollable::alt_scroll_down(nav, delta)} else {Task::none()}}Some(Selection::ChangedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Changed);if let Some(nav) = files_diffs.get_mut(&id_hash).and_then(|state| state.nav.as_mut()){iced_nav_scrollable::alt_scroll_down(nav, delta)} else {Task::none()}}Some(Selection::LogChange {ix: _,hash,message: _,file:Some(LogChangeFileSelection {ix: _,path,diff_selected: true,}),}) => {let id_hash = file::log_id_parts_hash(*hash, &path);if let Some(nav) = logs.diffs.get_mut(&id_hash).and_then(|diff| diff.state.nav.as_mut()){iced_nav_scrollable::alt_scroll_down(nav, delta)} else {Task::none()}}Some(Selection::UntrackedFile { .. })| Some(Selection::ChangedFile { .. })| Some(Selection::LogChange { .. })| None => Task::none(),}}fn alt_select_up<M>(state: &mut State,files_diffs: &mut diff::FilesState,logs: &mut diff::LogFilesAndState,delta: Option<Duration>,) -> Task<M> {match state.selection.as_mut() {Some(Selection::UntrackedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);if let Some(nav) = files_diffs.get_mut(&id_hash).and_then(|state| state.nav.as_mut()){iced_nav_scrollable::alt_scroll_up(nav, delta)} else {Task::none()}}Some(Selection::ChangedFile {ix: _,path,diff_selected: true,}) => {let id_hash = file::id_parts_hash(&path, file::Kind::Changed);if let Some(nav) = files_diffs.get_mut(&id_hash).and_then(|state| state.nav.as_mut()){iced_nav_scrollable::alt_scroll_up(nav, delta)} else {Task::none()}}Some(Selection::LogChange {ix: _,hash,message: _,file:Some(LogChangeFileSelection {ix: _,path,diff_selected: true,}),}) => {let id_hash = file::log_id_parts_hash(*hash, &path);if let Some(nav) = logs.diffs.get_mut(&id_hash).and_then(|diff| diff.state.nav.as_mut()){iced_nav_scrollable::alt_scroll_up(nav, delta)} else {Task::none()}}Some(Selection::UntrackedFile { .. })| Some(Selection::ChangedFile { .. })| Some(Selection::LogChange { .. })| None => Task::none(), - replacement in iced_nav_scrollable/src/lib.rs at line 22
const SPEED: f32 = 500.0;const SPEED: f32 = 1000.0; - replacement in iced_nav_scrollable/src/lib.rs at line 292
} else if *offset > nav.offset + nav.height {} else if *offset > bottom_frame { - replacement in iced_nav_scrollable/src/lib.rs at line 368
} else if offset + height< saturating_sub(nav.offset, VISIBLE_CONTEXT_HEIGHT){} else if offset + height < top_frame { - edit in iced_nav_scrollable/src/lib.rs at line 429
}/// Scroll down, skipping any sections that are marked to skippub fn alt_scroll_down<M>(nav: &mut NavScrollable,delta: Option<Duration>,) -> Task<M> {let offset_delta = delta.map(|delta| delta.as_millis() as f32).unwrap_or(DEFAULT_DELTA)/ 1_000.0* SPEED;let y = nav.offset + offset_delta;task::scroll_to(nav.id.clone(), scrollable::AbsoluteOffset { x: 0.0, y })}/// Scroll up, skipping any sections that are marked to skippub fn alt_scroll_up<M>(nav: &mut NavScrollable,delta: Option<Duration>,) -> Task<M> {let offset_delta = delta.map(|delta| delta.as_millis() as f32).unwrap_or(DEFAULT_DELTA)/ 1_000.0* SPEED;let y = saturating_sub(nav.offset, offset_delta);task::scroll_to(nav.id.clone(), scrollable::AbsoluteOffset { x: 0.0, y })