Skip to content

feat(feedback): implement shake gesture detection#7579

Merged
antonis merged 23 commits intomainfrom
antonis/feedback-shake
Mar 11, 2026
Merged

feat(feedback): implement shake gesture detection#7579
antonis merged 23 commits intomainfrom
antonis/feedback-shake

Conversation

@antonis
Copy link
Contributor

@antonis antonis commented Mar 3, 2026

📜 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

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 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

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
  • (SPM) Add package traits for UI framework opt-out and macOS CLI sample by philprime in #7578
  • Use full flamegraph for metrickit app hangs by noahsmartin in #7185

Bug Fixes 🐛

  • Capture instance and class method [NSApplication \_crashOnException] exceptions by denrase in #7510
  • Capture transactions during launch profiling window by philipphofmann in #7602

Internal Changes 🔧

Deps

  • Bump fastlane-plugin-sentry from 2.1.1 to 2.2.0 by dependabot in #7626
  • Bump mikepenz/action-junit-report from 6.3.0 to 6.3.1 by dependabot in #7630
  • Bump actions/setup-node from 6.2.0 to 6.3.0 by dependabot in #7627
  • Bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.23.0 to 2.23.2 by dependabot in #7628
  • Bump getsentry/craft from 2.23.0 to 2.23.2 by dependabot in #7629
  • Bump ruby/setup-ruby from 1.288.0 to 1.290.0 by dependabot in #7631

Samples

  • Restructure iOS-SwiftUI-Widgets sample by philprime in #7658
  • Restructure iOS15-SwiftUI sample by philprime in #7657
  • Restructure watchOS-Swift sample by philprime in #7614
  • Restructure visionOS-Swift sample by philprime in #7616
  • Restructure visionOS-SwiftUI-SPM sample by philprime in #7615

Other

  • (ci) Adds a Nightly Job with unit tests for less frequent devices by itaybre in #7632
  • (test-samples) Restructure SwiftUITestSample and SwiftUICrashTest by philprime in #7612
  • Fix watchOS tests and add them to nightly job by itaybre in #7633
  • Add crash when SentryInitializeForGettingSubclassesNotCalled is… by noahsmartin in #7637
  • Fix flaky HangTracker deallocated test by noahsmartin in #7639

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

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

Generated by 🚫 dangerJS against 2934db5

@codecov
Copy link

codecov bot commented Mar 3, 2026

Codecov Report

❌ Patch coverage is 69.81132% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.327%. Comparing base (8d00197) to head (2934db5).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...Feedback/SentryUserFeedbackIntegrationDriver.swift 36.842% 12 Missing ⚠️
...ntegrations/UserFeedback/SentryShakeDetector.swift 88.235% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #7579       +/-   ##
=============================================
- Coverage   86.173%   85.327%   -0.846%     
=============================================
  Files          483       484        +1     
  Lines        28785     28837       +52     
  Branches     12504     12532       +28     
=============================================
- Hits         24805     24606      -199     
- Misses        3927      4184      +257     
+ Partials        53        47        -6     
Files with missing lines Coverage Δ
...ntegrations/UserFeedback/SentryShakeDetector.swift 88.235% <88.235%> (ø)
...Feedback/SentryUserFeedbackIntegrationDriver.swift 19.090% <36.842%> (+3.873%) ⬆️

... and 12 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8d00197...2934db5. Read the comment docs.

antonis and others added 5 commits March 4, 2026 11:27
…it targets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…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 <noreply@anthropic.com>
Use monotonic clock (CACurrentMediaTime) instead of NSDate,
atomic_bool for thread-safe enabled flag, bridged notification
constant, and unconditional cleanup in deinit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@antonis antonis marked this pull request as ready for review March 4, 2026 13:12
@antonis antonis requested a review from alwx March 4, 2026 13:15
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.
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.
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 <noreply@anthropic.com>
@antonis 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.
The class is a static utility not meant to be subclassed.
Regenerate API snapshot accordingly.
@antonis antonis marked this pull request as ready for review March 5, 2026 14:18
@antonis antonis requested a review from itaybre March 5, 2026 14:18
antonis added 2 commits March 9, 2026 09:49
Always call SentryShakeDetector.disable() in deinit instead
of tracking whether this instance enabled it.
Copy link

@cursor 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.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Shake in early-return path permanently blocks future shakes
    • showForm(screenshot:) now early-returns when no presenter exists, preventing displayingForm from being set true when presentation cannot occur.

Create PR

Or push these changes by commenting:

@cursor push 3846cd567d
Preview (3846cd567d)
diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift
--- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift
+++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift
@@ -120,11 +120,14 @@
 @available(iOSApplicationExtension, unavailable)
 private extension SentryUserFeedbackIntegrationDriver {
     func showForm(screenshot: UIImage?) {
+        guard let presenter else {
+            return
+        }
         let form = SentryUserFeedbackFormController(config: configuration, delegate: self, screenshot: screenshot)
         form.presentationController?.delegate = self
         widget?.rootVC.setWidget(visible: false, animated: configuration.animations)
         displayingForm = true
-        presenter?.present(form, animated: configuration.animations) {
+        presenter.present(form, animated: configuration.animations) {
             self.configuration.onFormOpen?()
         }
     }
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

@antonis antonis requested a review from itaybre March 9, 2026 09:19
antonis added 3 commits March 9, 2026 16:28
Add SDK debug logs to swizzling steps in SentryShakeDetector
and to shake gesture handling in the integration driver.
Guard showForm early if presenter is nil so displayingForm
does not permanently block future shake and screenshot triggers.
@antonis antonis requested a review from philprime March 9, 2026 16:09
Copy link
Member

@philprime philprime left a comment

Choose a reason for hiding this comment

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

LGTM

…IWindow

Co-authored-by: Philip Niedertscheider <phil.niedertscheider@sentry.io>
@antonis antonis added the ready-to-merge Use this label to trigger all PR workflows label Mar 9, 2026
@sentry
Copy link

sentry bot commented Mar 9, 2026

Sentry Build Distribution

App Version Configuration
App 9.6.0 (1) Release

The one-shot screenshot observer is wasted in the early-return
path where no presenter exists yet. Keep only the persistent
shake observer there.
@sentry
Copy link

sentry bot commented Mar 9, 2026

Sentry Build Distribution

App Version Configuration
App 9.6.0 (1) Release

@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 3756.94 ms 3778.96 ms 22.02 ms
Size 24.14 KiB 1.12 MiB 1.10 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
93d7fdf 1225.77 ms 1259.79 ms 34.02 ms
3bff9ff 1217.72 ms 1246.43 ms 28.71 ms
62d9cf0 1228.72 ms 1258.29 ms 29.57 ms
c796e6d 1226.33 ms 1247.33 ms 21.00 ms
c58a1c5 1229.49 ms 1251.19 ms 21.70 ms
26ae2f8 1221.61 ms 1250.76 ms 29.14 ms
d064999 1218.36 ms 1250.08 ms 31.72 ms
3f47e70 1210.67 ms 1233.44 ms 22.76 ms
d427374 1226.81 ms 1257.74 ms 30.94 ms
3b01aaf 1194.98 ms 1210.36 ms 15.38 ms

App size

Revision Plain With Sentry Diff
93d7fdf 24.14 KiB 1.11 MiB 1.08 MiB
3bff9ff 24.14 KiB 1.11 MiB 1.09 MiB
62d9cf0 24.14 KiB 1.09 MiB 1.07 MiB
c796e6d 24.14 KiB 1.11 MiB 1.09 MiB
c58a1c5 24.14 KiB 1.11 MiB 1.09 MiB
26ae2f8 24.14 KiB 1.11 MiB 1.09 MiB
d064999 24.14 KiB 1.12 MiB 1.09 MiB
3f47e70 24.14 KiB 1.12 MiB 1.09 MiB
d427374 24.14 KiB 1.09 MiB 1.07 MiB
3b01aaf 24.14 KiB 1.06 MiB 1.04 MiB

Previous results on branch: antonis/feedback-shake

Startup times

Revision Plain With Sentry Diff
b98b32a 1222.73 ms 1262.50 ms 39.77 ms

App size

Revision Plain With Sentry Diff
b98b32a 24.14 KiB 1.12 MiB 1.10 MiB

@sentry
Copy link

sentry bot commented Mar 11, 2026

Sentry Build Distribution

App Version Configuration
App 9.6.0 (1) Release

Copy link

@cursor 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.

@antonis antonis merged commit 37f7dff into main Mar 11, 2026
207 of 209 checks passed
@antonis antonis deleted the antonis/feedback-shake branch March 11, 2026 09:55
antonis added a commit to getsentry/sentry-docs that referenced this pull request Mar 12, 2026
…16791)

## DESCRIBE YOUR PR

Document the now-functional `useShakeGesture` option for Apple/Cocoa
user feedback, based on
[sentry-cocoa#7579](getsentry/sentry-cocoa#7579).

- Add "Shake to Report" section to the user feedback setup page with a
Swift example
- Update `useShakeGesture` config description to note it's iOS-only
(no-op on macOS, tvOS, watchOS, visionOS)

## IS YOUR CHANGE URGENT?

Help us prioritize incoming PRs by letting us know when the change needs
to go live.
- [ ] Urgent deadline (GA date, etc.):
- [ ] Other deadline:
- [x] None: Not urgent, can wait up to 1 week+

⚠️ Should be merged after
getsentry/sentry-cocoa#7579 is released

## SLA

- Teamwork makes the dream work, so please add a reviewer to your PRs.
- Please give the docs team up to 1 week to review your PR unless you've
added an urgent due date to it.
Thanks in advance for your help!

## PRE-MERGE CHECKLIST

*Make sure you've checked the following before merging your changes:*

- [ ] Checked Vercel preview for correctness, including links
- [ ] PR was reviewed and approved by any necessary SMEs (subject matter
experts)
- [ ] PR was reviewed and approved by a member of the [Sentry docs
team](https://github.com/orgs/getsentry/teams/docs)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Use this label to trigger all PR workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(feedback): implement shake gesture detection

4 participants