Skip to content

refactor: centralize gesture state reset in useTrackpadGesture#334

Open
upendra512 wants to merge 1 commit intoAOSSIE-Org:mainfrom
upendra512:refactor/centralize-gesture-state-reset
Open

refactor: centralize gesture state reset in useTrackpadGesture#334
upendra512 wants to merge 1 commit intoAOSSIE-Org:mainfrom
upendra512:refactor/centralize-gesture-state-reset

Conversation

@upendra512
Copy link
Copy Markdown

@upendra512 upendra512 commented Apr 12, 2026

Closes #281

Gesture state was reset in multiple scattered places, making it easy to miss a ref when adding new gesture state.

Changes:

  • Add resetGestureState() helper that clears all gesture refs in one place: ongoingTouches, moved, releasedCount, dragging, lastPinchDist, pinching, and any pending draggingTimeout
  • Refactor handleTouchEnd to capture needed state (wasDragging, wasNotMoved, button) before calling resetGestureState(), then dispatch events after
  • Add handleTouchCancel that calls setIsTracking(false) + resetGestureState() for interrupted gestures
  • Expose onTouchCancel in the returned handlers object

Checklist:

  • Self-review completed
  • Code follows style guidelines

Summary by CodeRabbit

  • Bug Fixes
    • Improved touch and trackpad gesture handling to properly manage state when gestures are interrupted or cancelled, ensuring cleaner interaction recovery.

…E-Org#281)

Gesture state was reset in multiple scattered places across the hook,
making it easy to miss a ref when adding new gesture state in the future.

Introduce resetGestureState() which clears all gesture refs in one place:
ongoingTouches, moved, releasedCount, dragging, lastPinchDist, pinching,
and any pending draggingTimeout.

Refactor handleTouchEnd to capture needed state before calling
resetGestureState(), then dispatch drag release and tap events after.
This keeps the same external behavior while making the reset path clear.

Add handleTouchCancel that calls setIsTracking(false) + resetGestureState()
as a clean handler for interrupted gestures (phone call, system interrupt).
Expose onTouchCancel in the returned handlers object.

Fixes AOSSIE-Org#281

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

Walkthrough

The changes introduce a resetGestureState helper function to centralize clearing all gesture-related refs and associated timeouts. handleTouchEnd is refactored to capture gesture state before reset, enabling conditional emission of mouse and tap events. A new handleTouchCancel handler is added to manage touch cancellation events.

Changes

Cohort / File(s) Summary
Gesture State Management
src/hooks/useTrackpadGesture.ts
Added resetGestureState helper to consolidate clearing of ongoingTouches, moved, releasedCount, dragging, lastPinchDist, pinching, and draggingTimeout. Refactored handleTouchEnd to capture pre-reset state (wasDragging, wasNotMoved, elapsed, button) before calling reset, enabling proper event emission. Introduced handleTouchCancel handler that disables tracking and resets gesture state.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested labels

Typescript Lang

Poem

🐰 Hopping through the gesture maze,
State reset logic finds its place,
Cancels touch with gentle care,
Cleaner code floats through the air!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: centralizing gesture state reset logic in useTrackpadGesture hook.
Description check ✅ Passed The PR description addresses the issue and outlines changes clearly, though it lacks the detailed functional verification checklist from the template.
Linked Issues check ✅ Passed The PR fully implements the requirements from issue #281: introduces resetGestureState() helper, centralizes all gesture ref resets, handles draggingTimeout cleanup, and exposes onTouchCancel.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the refactoring objective in #281; no unrelated modifications are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/hooks/useTrackpadGesture.ts`:
- Around line 270-273: handleTouchCancel currently only resets local state via
setIsTracking and resetGestureState, but if a drag was active it never notifies
the remote side that the button was released; update handleTouchCancel to detect
an active drag/pressed state and send the equivalent "press: false" remote event
before clearing local state. Use the same helper the touchend/touchup flow uses
to send button events (the function that emits mouse/press events in this
module) so the remote button state is cleared, then call setIsTracking(false)
and resetGestureState().
- Line 281: The hook useTrackpadGesture now returns onTouchCancel but
TouchArea.tsx still only types and binds onTouchStart/onTouchMove/onTouchEnd;
update the TouchArea component to include the onTouchCancel prop in its props
interface and JSX event bindings (add onTouchCancel={props.onTouchCancel} or
equivalent) and ensure any internal handler references (e.g., handleTouchStart,
handleTouchMove, handleTouchEnd) are extended to accept/call the provided
onTouchCancel so touch-cancel events trigger the same reset/cleanup logic as end
events.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 664dfd07-be05-496f-8985-64bc5e15152b

📥 Commits

Reviewing files that changed from the base of the PR and between 1ae4791 and 8cd1d09.

📒 Files selected for processing (1)
  • src/hooks/useTrackpadGesture.ts

Comment on lines +270 to +273
const handleTouchCancel = () => {
setIsTracking(false)
resetGestureState()
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Touch-cancel can leave remote drag/button state stuck.

If cancellation happens during an active drag, state is reset locally but no press: false event is sent. That can leave the remote side thinking left button is still down.

🐛 Proposed fix
 const handleTouchCancel = () => {
+	const wasDragging = dragging.current
 	setIsTracking(false)
 	resetGestureState()
+	if (wasDragging) {
+		send({ type: "click", button: "left", press: false })
+	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleTouchCancel = () => {
setIsTracking(false)
resetGestureState()
}
const handleTouchCancel = () => {
const wasDragging = dragging.current
setIsTracking(false)
resetGestureState()
if (wasDragging) {
send({ type: "click", button: "left", press: false })
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useTrackpadGesture.ts` around lines 270 - 273, handleTouchCancel
currently only resets local state via setIsTracking and resetGestureState, but
if a drag was active it never notifies the remote side that the button was
released; update handleTouchCancel to detect an active drag/pressed state and
send the equivalent "press: false" remote event before clearing local state. Use
the same helper the touchend/touchup flow uses to send button events (the
function that emits mouse/press events in this module) so the remote button
state is cleared, then call setIsTracking(false) and resetGestureState().

onTouchStart: handleTouchStart,
onTouchMove: handleTouchMove,
onTouchEnd: handleTouchEnd,
onTouchCancel: handleTouchCancel,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

onTouchCancel exposure is not fully integrated in all consumers.

This hook now returns onTouchCancel, but src/components/Trackpad/TouchArea.tsx still types and binds only start/move/end handlers. In that path, cancel events will still bypass this reset logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/useTrackpadGesture.ts` at line 281, The hook useTrackpadGesture now
returns onTouchCancel but TouchArea.tsx still only types and binds
onTouchStart/onTouchMove/onTouchEnd; update the TouchArea component to include
the onTouchCancel prop in its props interface and JSX event bindings (add
onTouchCancel={props.onTouchCancel} or equivalent) and ensure any internal
handler references (e.g., handleTouchStart, handleTouchMove, handleTouchEnd) are
extended to accept/call the provided onTouchCancel so touch-cancel events
trigger the same reset/cleanup logic as end events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Enhanacement]: Centralize gesture state reset logic in useTrackpadGesture

2 participants