@@ -5,6 +5,8 @@ import * as React from 'react';
5
5
import { StyleSheet , View } from 'react-native' ;
6
6
7
7
import { createIntegration } from './integrations/factory' ;
8
+ import { ReactNativeTracing } from './tracing' ;
9
+ import { UI_ACTION_TOUCH } from './tracing/ops' ;
8
10
9
11
export type TouchEventBoundaryProps = {
10
12
/**
@@ -49,7 +51,7 @@ const DEFAULT_BREADCRUMB_CATEGORY = 'touch';
49
51
const DEFAULT_BREADCRUMB_TYPE = 'user' ;
50
52
const DEFAULT_MAX_COMPONENT_TREE_SIZE = 20 ;
51
53
52
- const PROP_KEY = 'sentry-label' ;
54
+ const SENTRY_LABEL_PROP_KEY = 'sentry-label' ;
53
55
54
56
interface ElementInstance {
55
57
elementType ?: {
@@ -64,6 +66,7 @@ interface ElementInstance {
64
66
* Boundary to log breadcrumbs for interaction events.
65
67
*/
66
68
class TouchEventBoundary extends React . Component < TouchEventBoundaryProps > {
69
+
67
70
public static displayName : string = '__Sentry.TouchEventBoundary' ;
68
71
public static defaultProps : Partial < TouchEventBoundaryProps > = {
69
72
breadcrumbCategory : DEFAULT_BREADCRUMB_CATEGORY ,
@@ -74,11 +77,17 @@ class TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {
74
77
75
78
public readonly name : string = 'TouchEventBoundary' ;
76
79
80
+ private _tracingIntegration : ReactNativeTracing | null = null ;
81
+
77
82
/**
78
83
* Registers the TouchEventBoundary as a Sentry Integration.
79
84
*/
80
85
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
+ }
82
91
}
83
92
84
93
/**
@@ -147,77 +156,84 @@ class TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {
147
156
*/
148
157
// eslint-disable-next-line complexity
149
158
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
162
179
) {
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 ;
169
207
}
208
+ componentTreeNames . push ( labelValue ) ;
209
+ } else if ( currentInst . elementType ) {
210
+ const { elementType } = currentInst ;
170
211
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 )
192
215
) {
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 ;
209
219
}
220
+ componentTreeNames . push ( elementType . displayName ) ;
210
221
}
211
-
212
- currentInst = currentInst . return ;
213
222
}
214
223
215
- const finalLabel = activeLabel ?? activeDisplayName ;
224
+ currentInst = currentInst . return ;
225
+ }
216
226
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 ) ;
220
231
}
232
+
233
+ this . _tracingIntegration ?. startUserInteractionTransaction ( {
234
+ elementId : activeLabel ,
235
+ op : UI_ACTION_TOUCH ,
236
+ } ) ;
221
237
}
222
238
}
223
239
0 commit comments