@@ -5,6 +5,8 @@ import * as React from 'react';
55import { StyleSheet , View } from 'react-native' ;
66
77import { createIntegration } from './integrations/factory' ;
8+ import { ReactNativeTracing } from './tracing' ;
9+ import { ACTION_TOUCH_OP } from './tracing/operations' ;
810
911export type TouchEventBoundaryProps = {
1012 /**
@@ -49,7 +51,7 @@ const DEFAULT_BREADCRUMB_CATEGORY = 'touch';
4951const DEFAULT_BREADCRUMB_TYPE = 'user' ;
5052const DEFAULT_MAX_COMPONENT_TREE_SIZE = 20 ;
5153
52- const PROP_KEY = 'sentry-label' ;
54+ const SENTRY_LABEL_PROP_KEY = 'sentry-label' ;
5355
5456interface ElementInstance {
5557 elementType ?: {
@@ -64,6 +66,7 @@ interface ElementInstance {
6466 * Boundary to log breadcrumbs for interaction events.
6567 */
6668class TouchEventBoundary extends React . Component < TouchEventBoundaryProps > {
69+
6770 public static displayName : string = '__Sentry.TouchEventBoundary' ;
6871 public static defaultProps : Partial < TouchEventBoundaryProps > = {
6972 breadcrumbCategory : DEFAULT_BREADCRUMB_CATEGORY ,
@@ -74,11 +77,17 @@ class TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {
7477
7578 public readonly name : string = 'TouchEventBoundary' ;
7679
80+ private _tracingIntegration : ReactNativeTracing | null = null ;
81+
7782 /**
7883 * Registers the TouchEventBoundary as a Sentry Integration.
7984 */
8085 public componentDidMount ( ) : void {
81- getCurrentHub ( ) . getClient ( ) ?. addIntegration ?.( createIntegration ( this . name ) ) ;
86+ const client = getCurrentHub ( ) . getClient ( ) ;
87+ client ?. addIntegration ?.( createIntegration ( this . name ) ) ;
88+ if ( ! this . _tracingIntegration && client ) {
89+ this . _tracingIntegration = client . getIntegration ( ReactNativeTracing ) ;
90+ }
8291 }
8392
8493 /**
@@ -147,77 +156,84 @@ class TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {
147156 */
148157 // eslint-disable-next-line complexity
149158 private _onTouchStart ( e : { _targetInst ?: ElementInstance } ) : void {
150- if ( e . _targetInst ) {
151- let currentInst : ElementInstance | undefined = e . _targetInst ;
152-
153- let activeLabel : string | undefined ;
154- let activeDisplayName : string | undefined ;
155- const componentTreeNames : string [ ] = [ ] ;
156-
157- while (
158- currentInst &&
159- // maxComponentTreeSize will always be defined as we have a defaultProps. But ts needs a check so this is here.
160- this . props . maxComponentTreeSize &&
161- componentTreeNames . length < this . props . maxComponentTreeSize
159+ if ( ! e . _targetInst ) {
160+ return ;
161+ }
162+
163+ let currentInst : ElementInstance | undefined = e . _targetInst ;
164+
165+ let activeLabel : string | undefined ;
166+ let activeDisplayName : string | undefined ;
167+ const componentTreeNames : string [ ] = [ ] ;
168+
169+ while (
170+ currentInst &&
171+ // maxComponentTreeSize will always be defined as we have a defaultProps. But ts needs a check so this is here.
172+ this . props . maxComponentTreeSize &&
173+ componentTreeNames . length < this . props . maxComponentTreeSize
174+ ) {
175+ if (
176+ // If the loop gets to the boundary itself, break.
177+ currentInst . elementType ?. displayName ===
178+ TouchEventBoundary . displayName
162179 ) {
163- if (
164- // If the loop gets to the boundary itself, break.
165- currentInst . elementType ?. displayName ===
166- TouchEventBoundary . displayName
167- ) {
168- break ;
180+ break ;
181+ }
182+
183+ const props = currentInst . memoizedProps ;
184+ const sentryLabel =
185+ typeof props ?. [ SENTRY_LABEL_PROP_KEY ] !== 'undefined'
186+ ? `${ props [ SENTRY_LABEL_PROP_KEY ] } `
187+ : undefined ;
188+
189+ // For some reason type narrowing doesn't work as expected with indexing when checking it all in one go in
190+ // the "check-label" if sentence, so we have to assign it to a variable here first
191+ let labelValue ;
192+ if ( typeof this . props . labelName === 'string' )
193+ labelValue = props ?. [ this . props . labelName ] ;
194+
195+ // Check the label first
196+ if ( sentryLabel && ! this . _isNameIgnored ( sentryLabel ) ) {
197+ if ( ! activeLabel ) {
198+ activeLabel = sentryLabel ;
199+ }
200+ componentTreeNames . push ( sentryLabel ) ;
201+ } else if (
202+ typeof labelValue === 'string' &&
203+ ! this . _isNameIgnored ( labelValue )
204+ ) {
205+ if ( ! activeLabel ) {
206+ activeLabel = labelValue ;
169207 }
208+ componentTreeNames . push ( labelValue ) ;
209+ } else if ( currentInst . elementType ) {
210+ const { elementType } = currentInst ;
170211
171- const props = currentInst . memoizedProps ;
172- const label =
173- typeof props ?. [ PROP_KEY ] !== 'undefined'
174- ? `${ props [ PROP_KEY ] } `
175- : undefined ;
176-
177- // For some reason type narrowing doesn't work as expected with indexing when checking it all in one go in
178- // the "check-label" if sentence, so we have to assign it to a variable here first
179- let labelValue ;
180- if ( typeof this . props . labelName === 'string' )
181- labelValue = props ?. [ this . props . labelName ] ;
182-
183- // Check the label first
184- if ( label && ! this . _isNameIgnored ( label ) ) {
185- if ( ! activeLabel ) {
186- activeLabel = label ;
187- }
188- componentTreeNames . push ( label ) ;
189- } else if (
190- typeof labelValue === 'string' &&
191- ! this . _isNameIgnored ( labelValue )
212+ if (
213+ elementType . displayName &&
214+ ! this . _isNameIgnored ( elementType . displayName )
192215 ) {
193- if ( ! activeLabel ) {
194- activeLabel = labelValue ;
195- }
196- componentTreeNames . push ( labelValue ) ;
197- } else if ( currentInst . elementType ) {
198- const { elementType } = currentInst ;
199-
200- if (
201- elementType . displayName &&
202- ! this . _isNameIgnored ( elementType . displayName )
203- ) {
204- // Check display name
205- if ( ! activeDisplayName ) {
206- activeDisplayName = elementType . displayName ;
207- }
208- componentTreeNames . push ( elementType . displayName ) ;
216+ // Check display name
217+ if ( ! activeDisplayName ) {
218+ activeDisplayName = elementType . displayName ;
209219 }
220+ componentTreeNames . push ( elementType . displayName ) ;
210221 }
211-
212- currentInst = currentInst . return ;
213222 }
214223
215- const finalLabel = activeLabel ?? activeDisplayName ;
224+ currentInst = currentInst . return ;
225+ }
216226
217- if ( componentTreeNames . length > 0 || finalLabel ) {
218- this . _logTouchEvent ( componentTreeNames , finalLabel ) ;
219- }
227+ const finalLabel = activeLabel ?? activeDisplayName ;
228+
229+ if ( componentTreeNames . length > 0 || finalLabel ) {
230+ this . _logTouchEvent ( componentTreeNames , finalLabel ) ;
220231 }
232+
233+ this . _tracingIntegration ?. startUserInteractionTransaction ( {
234+ elementId : activeLabel ,
235+ op : ACTION_TOUCH_OP ,
236+ } ) ;
221237 }
222238}
223239
0 commit comments