Skip to content

Commit fc54615

Browse files
authored
Cancel the swipe back gesture on vertical swipes (#95)
1 parent 7c54bae commit fc54615

File tree

1 file changed

+54
-31
lines changed

1 file changed

+54
-31
lines changed

crates/egui_router/src/router.rs

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ enum SwipeBackGestureState {
2121
/// Distance swiped in pixels
2222
distance: f32,
2323
},
24+
/// Gesture was cancelled due to vertical movement, wait for release
25+
Cancelled,
2426
}
2527

2628
/// A router instance
@@ -345,6 +347,7 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
345347
}
346348
}
347349

350+
#[allow(clippy::too_many_lines)]
348351
fn handle_swipe_gesture(&mut self, ui: &mut Ui) {
349352
let gesture_id = Id::new("router_swipe_back_gesture");
350353

@@ -386,45 +389,65 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
386389
// Check if the gesture started from the left edge
387390
if let Some(pos) = pointer_pos {
388391
if pos.x <= content_rect.min.x + self.swipe_back_edge_width {
389-
// Start the gesture
390-
gesture_state = SwipeBackGestureState::Swiping { distance: 0.0 };
391-
392-
// Start a manual backward transition
393-
if self.current_transition.is_none() {
394-
let mut transition = CurrentTransition {
395-
active_transition: ActiveTransition::manual(
396-
self.backward_transition.clone(),
397-
)
398-
.with_default_duration(self.default_duration),
399-
leaving_route: None,
400-
};
401-
// Initialize progress to 1.0 (fully showing current page)
402-
transition.active_transition.set_progress(1.0);
403-
self.current_transition = Some(transition);
392+
// Cancel if velocity is more vertical than horizontal
393+
if velocity.y.abs() > velocity.x.abs() && velocity.y.abs() > 0.0 {
394+
// Vertical movement dominates, don't start the gesture
395+
gesture_state = SwipeBackGestureState::Cancelled;
396+
} else {
397+
// Start the gesture
398+
gesture_state =
399+
SwipeBackGestureState::Swiping { distance: 0.0 };
400+
401+
// Start a manual backward transition
402+
if self.current_transition.is_none() {
403+
let mut transition = CurrentTransition {
404+
active_transition: ActiveTransition::manual(
405+
self.backward_transition.clone(),
406+
)
407+
.with_default_duration(self.default_duration),
408+
leaving_route: None,
409+
};
410+
// Initialize progress to 1.0 (fully showing current page)
411+
transition.active_transition.set_progress(1.0);
412+
self.current_transition = Some(transition);
413+
}
404414
}
405415
}
406416
}
407417
}
408418
SwipeBackGestureState::Swiping { distance, .. } => {
409-
// Update the gesture distance (only positive horizontal movement)
410-
let new_distance = (distance + delta.x).max(0.0);
411-
412-
gesture_state = SwipeBackGestureState::Swiping {
413-
distance: new_distance,
414-
};
415-
416-
if new_distance > 10.0 {
417-
// Steal the drag in case a scroll area is also detecting it
418-
ui.ctx().set_dragged_id(gesture_id);
419-
}
419+
// Cancel if velocity becomes too vertical before we've committed
420+
if distance < 10.0
421+
&& velocity.y.abs() > velocity.x.abs()
422+
&& velocity.y.abs() > 0.0
423+
{
424+
// Vertical movement dominates, cancel the gesture
425+
self.current_transition = None;
426+
gesture_state = SwipeBackGestureState::Cancelled;
427+
} else {
428+
// Update the gesture distance (only positive horizontal movement)
429+
let new_distance = (distance + delta.x).max(0.0);
430+
431+
gesture_state = SwipeBackGestureState::Swiping {
432+
distance: new_distance,
433+
};
434+
435+
if new_distance > 10.0 {
436+
// Steal the drag in case a scroll area is also detecting it
437+
ui.ctx().set_dragged_id(gesture_id);
438+
}
420439

421-
// Update the transition progress
422-
if let Some(transition) = &mut self.current_transition {
423-
let screen_width = content_rect.width();
424-
let progress = 1.0 - (new_distance / screen_width).at_most(1.0);
425-
transition.active_transition.set_progress(progress);
440+
// Update the transition progress
441+
if let Some(transition) = &mut self.current_transition {
442+
let screen_width = content_rect.width();
443+
let progress = 1.0 - (new_distance / screen_width).at_most(1.0);
444+
transition.active_transition.set_progress(progress);
445+
}
426446
}
427447
}
448+
SwipeBackGestureState::Cancelled => {
449+
// Wait for release before allowing new gestures
450+
}
428451
}
429452
}
430453

0 commit comments

Comments
 (0)