Skip to content

feat(feedback): Show feedback widget on device shake#5754

Draft
antonis wants to merge 22 commits intomainfrom
antonis/feedback-shake-native
Draft

feat(feedback): Show feedback widget on device shake#5754
antonis wants to merge 22 commits intomainfrom
antonis/feedback-shake-native

Conversation

@antonis
Copy link
Contributor

@antonis antonis commented Mar 3, 2026

📢 Type of change

  • New feature

📜 Description

Implements shake-to-report for the feedback widget and delegates shake detection to the implementations in the native SDKs:

The RNSentry.mm now imports <Sentry/SentryShakeDetector.h> and uses SentryShakeDetectedNotification instead of the RN-specific ones. On Android, RNSentryModuleImpl uses io.sentry.android.core.SentryShakeDetector.

💡 Motivation and Context

Users have requested a way to trigger the feedback widget by shaking the device, without the need for a visible button. This is a common UX pattern for in-app feedback

Fixes #4735

This PR depends on the two native SDK PRs above merging first.

💚 How did you test it?

  • All existing tests pass: yarn build, yarn test, yarn lint, yarn circularDepCheck
  • Shake-to-report works end-to-end on iOS release build (tested in previous PR on this branch)

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

Merge the native SDK PRs, update the Cocoa/Java dependency versions in the RN SDK, then merge this PR.

antonis and others added 21 commits February 26, 2026 16:57
Implement device shake detection to trigger the feedback widget.
No permissions are required on either platform:
- iOS: Uses UIKit's motionEnded:withEvent: via UIWindow swizzle
- Android: Uses SensorManager accelerometer (TYPE_ACCELEROMETER)

Public API:
- showFeedbackOnShake() / hideFeedbackOnShake() imperative APIs
- feedbackIntegration({ enableShakeToReport: true }) declarative option

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion.sendEvent:

The previous implementation swizzled UIWindow.motionEnded:withEvent: which was
intercepted by React Native's dev menu before our handler could fire. Switching
to UIApplication.sendEvent: intercepts events before the responder chain, so
shake events are detected even when RN dev menu or another responder consumes
the motion event without calling super.

Added a 1-second cooldown to prevent double-firing since both motionBegan and
motionEnded trigger UIEventSubtypeMotionShake.
…wizzle

UIApplication.sendEvent: is not invoked by the iOS simulator for the
simulated shake (Cmd+Ctrl+Z); it goes directly through
UIWindow.motionEnded:withEvent: instead.

React Native's dev menu swizzles UIWindow.motionEnded:withEvent: at bridge
load time. Because we swizzle from startObserving (triggered by
componentDidMount via NativeEventEmitter.addListener), our swizzle always
runs after RN's — making sentry_motionEnded the outermost layer that calls
through to RN's dev-menu handler via the stored original IMP.

This approach works on both real devices and the iOS simulator.
Without FeedbackWidgetProvider rendered in the tree, componentDidMount
never fires, startShakeListener is never called, and the native swizzle
is never set up — so shake-to-report has no effect despite
enableShakeToReport: true being configured on the integration.
Instead of relying on startObserving (which fires for any event type on the
module's first listener), mirror the Android approach: override addListener
and explicitly call [RNSentryShakeDetector enable] when the shake event is
subscribed to. This ensures the UIWindow swizzle is set up reliably
regardless of listener ordering or TurboModule event-emitter behaviour.
Without this import SentryDefines.h is never included, SENTRY_HAS_UIKIT
evaluates to 0, and the entire shake detector implementation is compiled
out leaving only the no-op stubs. All other files in the module that use
SENTRY_HAS_UIKIT (RNSentryOnDrawReporter.m, RNSentryDependencyContainer.m,
etc.) include @import Sentry for exactly this reason.
@import Sentry caused a startup crash. Replace both the module import
and SENTRY_HAS_UIKIT guard with TARGET_OS_IOS which has identical
semantics for shake detection (iOS only) and needs no external import.
…eport

On iOS with New Architecture (TurboModules), NativeEventEmitter.addListener
does not dispatch to native addListener:, so the UIWindow swizzle for shake
detection was never enabled.

Adds explicit enableShakeDetection/disableShakeDetection RCT_EXPORT_METHODs
on iOS and no-op stubs on Android. JS startShakeListener now calls
enableShakeDetection directly after subscribing to the event, bypassing
the unreliable NativeEventEmitter → native dispatch path on iOS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UIWindow inherits motionEnded:withEvent: from UIResponder and may not
have its own implementation. Using method_setImplementation directly on
the inherited Method would modify UIResponder, affecting all subclasses
and causing a doesNotRecognizeSelector crash.

Fix by calling class_addMethod first to ensure UIWindow has its own
method before replacing the IMP. Also prevent duplicate NSNotification
observers on component remount, and clean up debug logging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… native SDKs

Remove the RN-specific shake detector implementations and delegate to
SentryShakeDetector (iOS: sentry-cocoa, Android: sentry-android-core)
so the implementation is shared with other SDKs that have feedback UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Fails
🚫 Pull request is not ready for merge, please add the "ready-to-merge" label to the pull request
🚫 Please consider adding a changelog entry for the next release.
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- Show feedback widget on device shake ([#5754](https://github.com/getsentry/sentry-react-native/pull/5754))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against daf949d

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

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


  • feat(feedback): Show feedback widget on device shake by antonis in #5754
  • Feat(Expo): Add expo constants on event context. by lucas-zimerman in #5748
  • chore(deps): update JavaScript SDK to v10.42.0 by github-actions in #5753
  • feat(core): Capture dynamic route params as span attributes by antonis in #5750
  • chore(deps): bump brace-expansion from 1.1.11 to 1.1.12 by dependabot in #5751
  • chore(deps): bump minimatch to fix ReDoS vulnerabilities and tmp to ^0.2.4 by antonis in #5749
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.21.7 to 2.23.1 by dependabot in #5738
  • chore(deps): update Wizard to v6.12.0 by github-actions in #5747
  • chore(deps): update JavaScript SDK to v10.41.0 by github-actions in #5744
  • chore(deps): bump tar to ^7.5.8 by antonis in #5703
  • chore(deps): bump js-yaml to fix prototype pollution in merge by antonis in #5709
  • chore(deps): bump ajv to fix ReDoS in $data option by antonis in #5710
  • chore(deps): update CLI to v3.2.3 by github-actions in #5743
  • Fixes the issue with unit mismatch in adjustTransactionDuration by alwx in #5740
  • Handle inactive state for spans by alwx in #5742
  • chore(deps): bump actions/github-script from 7 to 8 by dependabot in #5737
  • chore(deps): bump actions/upload-artifact from 6 to 7 by dependabot in #5739
  • chore(deps): bump futureware-tech/simulator-action from 4 to 5 by dependabot in #5735
  • chore(deps): bump actions/download-artifact from 7 to 8 by dependabot in #5736
  • chore(deps): bump path-to-regexp to 0.1.12 by antonis in #5706
  • fix(ios): resolve relative SOURCEMAP_FILE against project root in Xcode build script by antonis in #5730
  • test(metro): Add type tests for SentryExpoConfigOptions.getDefaultConfig by antonis in #5733
  • chore(deps): bump axios to ^1.13.5 by antonis in #5708
  • chore(deps): bump on-headers to ^1.1.0 by antonis in #5704

Plus 6 more


🤖 This preview updates automatically when you update the PR.

Copy link
Contributor Author

@antonis antonis left a comment

Choose a reason for hiding this comment

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

Marking as blocked till the native PRs are merged

@antonis antonis changed the title refactor(feedback): delegate shake detection to native SDKs feat(feedback): Show feedback widget on device shake Mar 4, 2026
@antonis antonis changed the base branch from antonis/feedback-shake to main March 4, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show Report Feedback on Shake

1 participant