Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(feedback): implement shake gesture detection#7579

Open
antonis wants to merge 14 commits intomainfrom
antonis/feedback-shake
Open

feat(feedback): implement shake gesture detection#7579
antonis wants to merge 14 commits intomainfrom
antonis/feedback-shake

Conversation

Copy link
Contributor

antonis commented Mar 3, 2026 *
edited
Loading

Description

Implements shake gesture detection for the user feedback form. When useShakeGesture is enabled in SentryUserFeedbackConfiguration, shaking the device opens the feedback form.

The implementation swizzles UIWindow.motionEnded:withEvent: using class_addMethod + method_setImplementation to safely intercept shake events without modifying UIResponder's inherited implementation. A cooldown of 1 second prevents duplicate triggers.

Note: this is exposed to be used on React Native too getsentry/sentry-react-native#5754

Motivation and Context

The useShakeGesture property already existed in SentryUserFeedbackConfiguration but was never wired up. This PR implements the feature. The implementation is placed here (sentry-cocoa) rather than in each SDK separately so it can be reused by all SDKs that embed the feedback UI (React Native, Flutter, .NET MAUI, Unity).

How did you test it?

  • Tested in a sample iOS app (release build) -- shaking the device opens the feedback form
  • Debug builds: shake triggers the React Native dev menu (expected; RCTDevMenu also swizzles the same method)
  • Unit tests added for SentryShakeDetector

Checklist

  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed. docs(apple): Add shake-to-report section and note iOS-only support sentry-docs#16791
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.

Closes #7597

sentry[bot] reacted with hooray emoji
The useShakeGesture configuration property existed but was not implemented.
This adds SentryShakeDetector which swizzles UIWindow.motionEnded:withEvent:
to detect shake gestures and wires it into SentryUserFeedbackIntegrationDriver.

Co-Authored-By: Claude Opus 4.6
Copy link
Contributor

github-actions bot commented Mar 3, 2026 *
edited
Loading

Semver Impact of This PR

Minor (new features)

Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features

  • (feedback) Implement shake gesture detection by antonis in #7579

This preview updates automatically when you update the PR.

Copy link
Contributor

github-actions bot commented Mar 3, 2026 *
edited
Loading

Messages
Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by dangerJS against f0cd795

Copy link

codecov bot commented Mar 3, 2026 *
edited
Loading

Codecov Report

Patch coverage is 75.00000% with 11 lines in your changes missing coverage. Please review.
Project coverage is 85.005%. Comparing base (b7dbc42) to head (f0cd795).
All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...Feedback/SentryUserFeedbackIntegrationDriver.swift 40.000% 9 Missing
...ntegrations/UserFeedback/SentryShakeDetector.swift 93.103% 2 Missing
Additional details and impacted files

@@ Coverage Diff @@
## main #7579 +/- ##
=============================================
- Coverage 85.288% 85.005% -0.284%
=============================================
Files 483 484 +1
Lines 28747 28791 +44
Branches 12486 12505 +19
=============================================
- Hits 24518 24474 -44
- Misses 4182 4268 +86
- Partials 47 49 +2
Files with missing lines Coverage D
...ntegrations/UserFeedback/SentryShakeDetector.swift 93.103% <93.103%> (o)
...Feedback/SentryUserFeedbackIntegrationDriver.swift 18.691% <40.000%> (+3.474%)

... and 11 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
D = absolute (impact), o = not affected, ? = missing data
Powered by Codecov. Last update b7dbc42...f0cd795. Read the comment docs.

antonis and others added 5 commits March 4, 2026 11:27
...non-iOS

The @interface declaration was wrapped in #if TARGET_OS_IOS, causing a
compile error on macOS/tvOS/watchOS where the @implementation in the
#else block could not find the interface. The class is now declared on
all platforms with the methods documented as no-ops on non-iOS.

Co-Authored-By: Claude Sonnet 4.6
Use monotonic clock (CACurrentMediaTime) instead of NSDate,
atomic_bool for thread-safe enabled flag, bridged notification
constant, and unconditional cleanup in deinit.
antonis marked this pull request as ready for review March 4, 2026 13:12
antonis requested review from itaybre, noahsmartin, philipphofmann and philprime as code owners March 4, 2026 13:12
github-actions bot mentioned this pull request Mar 4, 2026
7 tasks
antonis requested a review from alwx March 4, 2026 13:15
cursor bot reviewed Mar 4, 2026
antonis added 2 commits March 4, 2026 14:26
Track whether this driver instance enabled shake detection and
only call disable in deinit if it did. Prevents an old driver's
deallocation from disabling shake detection that a new driver
already re-enabled during SDK restart.
cursor bot reviewed Mar 4, 2026
Copy link

cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

The init early-returns when there are no connected scenes (SwiftUI
apps). Move observeScreenshots and observeShakeGesture calls before
the return so shake detection works in SwiftUI apps.
static void
sentry_motionEnded(UIWindow *self, SEL _cmd, UIEventSubtype motion, UIEvent *event)
{
if (atomic_load_explicit(&_shakeDetectionEnabled, memory_order_acquire)
Copy link

lucas-zimerman Mar 4, 2026

Choose a reason for hiding this comment

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

Q: does this run on every shake after calling disable?

Copy link
Contributor Author

antonis Mar 5, 2026 *
edited
Loading

Choose a reason for hiding this comment

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

Yes, after disable, sentry_motionEnded still runs on every motionEnded:withEvent:, but it's a single atomic bool check that returns immediately. The swizzle is intentionally never removed (un-swizzling is unsafe with multiple swizzlers).

antonis added a commit to getsentry/sentry-docs that referenced this pull request Mar 5, 2026
Add a "Shake to Report" section to the user feedback setup page and update
the `useShakeGesture` config description to note it's iOS-only.

Ref: getsentry/sentry-cocoa#7579

Co-Authored-By: Claude
itaybre reviewed Mar 5, 2026
* Swizzling is performed at most once regardless of how many times @c +enable is called.
* On non-iOS platforms (macOS, tvOS, watchOS), these methods are no-ops.
*/
@interface SentryShakeDetector : NSObject
Copy link
Contributor

itaybre Mar 5, 2026

Choose a reason for hiding this comment

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

m: Any reason in particular to make it in ObjC?

I don't see anything that couldn't be done in Swift here

Copy link
Contributor Author

antonis Mar 5, 2026

Choose a reason for hiding this comment

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

Not really other than initially implementing on the RN side and moving it here I'll convert to draft and move this to Swift. thank you for the feedback

Copy link
Contributor Author

antonis Mar 5, 2026

Choose a reason for hiding this comment

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

Refactored with 3c24378


#else

NSNotificationName const SentryShakeDetectedNotification = @"SentryShakeDetected";
Copy link
Contributor

itaybre Mar 5, 2026

Choose a reason for hiding this comment

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

m: You can place this outside the #if TARGET_OS_IOS preprocessor directive to avoid declaring it twice

antonis reacted with thumbs up emoji
Copy link
Contributor Author

antonis Mar 5, 2026

Choose a reason for hiding this comment

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

Tackled with the refactoring 3c24378

#import
#import

#if TARGET_OS_IOS
Copy link
Contributor

itaybre Mar 5, 2026

Choose a reason for hiding this comment

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

h: iPad also supports shake gestures too

antonis reacted with thumbs up emoji
Copy link
Contributor Author

antonis Mar 5, 2026

Choose a reason for hiding this comment

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

Tackled with the refactoring 3c24378

}

@objc func handleShakeGesture() {
guard !displayingForm else { return }
Copy link
Contributor

itaybre Mar 5, 2026

Choose a reason for hiding this comment

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

h: on iPad there may be several windows, and I am not sure if all of them get the shake gesture or not.
Will this present the feedback form on all of them?

antonis reacted with thumbs up emoji
Copy link
Contributor Author

antonis Mar 5, 2026

Choose a reason for hiding this comment

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

Tackled with the refactoring 3c24378

antonis marked this pull request as draft March 5, 2026 12:49
antonis added 3 commits March 5, 2026 14:35
Replaces the ObjC implementation with a Swift class while
maintaining full ObjC compatibility via @objc annotations.
The class name remains SentryShakeDetector in ObjC, preserving
compatibility with sentry-react-native.
antonis added 2 commits March 5, 2026 14:58
Make SentryShakeDetector an open class to match the ObjC API
and regenerate sdk_api.json with Xcode 16.4.
The class is a static utility not meant to be subclassed.
Regenerate API snapshot accordingly.
antonis marked this pull request as ready for review March 5, 2026 14:18
antonis requested a review from itaybre March 5, 2026 14:18
itaybre reviewed Mar 5, 2026
deinit {
customButton?.removeTarget(self, action: #selector(showForm(sender:)), for: .touchUpInside)
if didEnableShakeDetection {
SentryShakeDetector.disable()
Copy link
Contributor

itaybre Mar 5, 2026

Choose a reason for hiding this comment

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

l: I think if it safe to always call disable

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

Reviewers

itaybre itaybre left review comments

cursor[bot] cursor[bot] left review comments

philipphofmann Awaiting requested review from philipphofmann philipphofmann is a code owner

philprime Awaiting requested review from philprime philprime is a code owner

noahsmartin Awaiting requested review from noahsmartin noahsmartin is a code owner

alwx Awaiting requested review from alwx

+1 more reviewer

lucas-zimerman lucas-zimerman left review comments

Reviewers whose approvals may not affect merge requirements

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

feat(feedback): implement shake gesture detection

3 participants