@@ -3,7 +3,6 @@ import { captureFeedback, getCurrentScope, lastEventId, logger } from '@sentry/c
3
3
import * as React from 'react' ;
4
4
import type { KeyboardTypeOptions } from 'react-native' ;
5
5
import {
6
- Alert ,
7
6
Image ,
8
7
Keyboard ,
9
8
KeyboardAvoidingView ,
@@ -17,12 +16,13 @@ import {
17
16
View
18
17
} from 'react-native' ;
19
18
19
+ import { isWeb , notWeb } from '../utils/environment' ;
20
20
import { NATIVE } from '../wrapper' ;
21
21
import { sentryLogo } from './branding' ;
22
22
import { defaultConfiguration } from './defaults' ;
23
23
import defaultStyles from './FeedbackWidget.styles' ;
24
24
import type { FeedbackGeneralConfiguration , FeedbackTextConfiguration , FeedbackWidgetProps , FeedbackWidgetState , FeedbackWidgetStyles , ImagePickerConfiguration } from './FeedbackWidget.types' ;
25
- import { isValidEmail } from './utils' ;
25
+ import { base64ToUint8Array , feedbackAlertDialog , isValidEmail } from './utils' ;
26
26
27
27
/**
28
28
* @beta
@@ -75,12 +75,12 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
75
75
const trimmedDescription = description ?. trim ( ) ;
76
76
77
77
if ( ( this . props . isNameRequired && ! trimmedName ) || ( this . props . isEmailRequired && ! trimmedEmail ) || ! trimmedDescription ) {
78
- Alert . alert ( text . errorTitle , text . formError ) ;
78
+ feedbackAlertDialog ( text . errorTitle , text . formError ) ;
79
79
return ;
80
80
}
81
81
82
82
if ( this . props . shouldValidateEmail && ( this . props . isEmailRequired || trimmedEmail . length > 0 ) && ! isValidEmail ( trimmedEmail ) ) {
83
- Alert . alert ( text . errorTitle , text . emailError ) ;
83
+ feedbackAlertDialog ( text . errorTitle , text . emailError ) ;
84
84
return ;
85
85
}
86
86
@@ -107,13 +107,13 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
107
107
}
108
108
captureFeedback ( userFeedback , attachments ? { attachments } : undefined ) ;
109
109
onSubmitSuccess ( { name : trimmedName , email : trimmedEmail , message : trimmedDescription , attachments : attachments } ) ;
110
- Alert . alert ( text . successMessageText ) ;
110
+ feedbackAlertDialog ( text . successMessageText , '' ) ;
111
111
onFormSubmitted ( ) ;
112
112
this . _didSubmitForm = true ;
113
113
} catch ( error ) {
114
114
const errorString = `Feedback form submission failed: ${ error } ` ;
115
115
onSubmitError ( new Error ( errorString ) ) ;
116
- Alert . alert ( text . errorTitle , text . genericError ) ;
116
+ feedbackAlertDialog ( text . errorTitle , text . genericError ) ;
117
117
logger . error ( `Feedback form submission failed: ${ error } ` ) ;
118
118
}
119
119
} ;
@@ -124,15 +124,15 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
124
124
if ( imagePickerConfiguration . imagePicker ) {
125
125
const launchImageLibrary = imagePickerConfiguration . imagePicker . launchImageLibraryAsync
126
126
// expo-image-picker library is available
127
- ? ( ) => imagePickerConfiguration . imagePicker . launchImageLibraryAsync ( { mediaTypes : [ 'images' ] } )
127
+ ? ( ) => imagePickerConfiguration . imagePicker . launchImageLibraryAsync ( { mediaTypes : [ 'images' ] , base64 : isWeb ( ) } )
128
128
// react-native-image-picker library is available
129
129
: imagePickerConfiguration . imagePicker . launchImageLibrary
130
- ? ( ) => imagePickerConfiguration . imagePicker . launchImageLibrary ( { mediaType : 'photo' } )
130
+ ? ( ) => imagePickerConfiguration . imagePicker . launchImageLibrary ( { mediaType : 'photo' , includeBase64 : isWeb ( ) } )
131
131
: null ;
132
132
if ( ! launchImageLibrary ) {
133
133
logger . warn ( 'No compatible image picker library found. Please provide a valid image picker library.' ) ;
134
134
if ( __DEV__ ) {
135
- Alert . alert (
135
+ feedbackAlertDialog (
136
136
'Development note' ,
137
137
'No compatible image picker library found. Please provide a compatible version of `expo-image-picker` or `react-native-image-picker`.' ,
138
138
) ;
@@ -142,18 +142,29 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
142
142
143
143
const result = await launchImageLibrary ( ) ;
144
144
if ( result . assets && result . assets . length > 0 ) {
145
- const filename = result . assets [ 0 ] . fileName ;
146
- const imageUri = result . assets [ 0 ] . uri ;
147
- NATIVE . getDataFromUri ( imageUri ) . then ( ( data ) => {
145
+ if ( isWeb ( ) ) {
146
+ const filename = result . assets [ 0 ] . fileName ;
147
+ const imageUri = result . assets [ 0 ] . uri ;
148
+ const base64 = result . assets [ 0 ] . base64 ;
149
+ const data = base64ToUint8Array ( base64 ) ;
148
150
if ( data != null ) {
149
151
this . setState ( { filename, attachment : data , attachmentUri : imageUri } ) ;
150
152
} else {
151
- logger . error ( 'Failed to read image data from uri:' , imageUri ) ;
153
+ logger . error ( 'Failed to read image data on the web' ) ;
152
154
}
153
- } )
154
- . catch ( ( error ) => {
155
+ } else {
156
+ const filename = result . assets [ 0 ] . fileName ;
157
+ const imageUri = result . assets [ 0 ] . uri ;
158
+ NATIVE . getDataFromUri ( imageUri ) . then ( ( data ) => {
159
+ if ( data != null ) {
160
+ this . setState ( { filename, attachment : data , attachmentUri : imageUri } ) ;
161
+ } else {
162
+ logger . error ( 'Failed to read image data from uri:' , imageUri ) ;
163
+ }
164
+ } ) . catch ( ( error ) => {
155
165
logger . error ( 'Failed to read image data from uri:' , imageUri , 'error: ' , error ) ;
156
166
} ) ;
167
+ }
157
168
}
158
169
} else {
159
170
// Defaulting to the onAddScreenshot callback
@@ -215,9 +226,10 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
215
226
< KeyboardAvoidingView
216
227
behavior = { Platform . OS === 'ios' ? 'padding' : 'height' }
217
228
style = { [ styles . container , { padding : 0 } ] }
229
+ enabled = { notWeb ( ) }
218
230
>
219
231
< ScrollView bounces = { false } >
220
- < TouchableWithoutFeedback onPress = { Keyboard . dismiss } >
232
+ < TouchableWithoutFeedback onPress = { notWeb ( ) ? Keyboard . dismiss : undefined } >
221
233
< View style = { styles . container } >
222
234
< View style = { styles . titleContainer } >
223
235
< Text style = { styles . title } > { text . formTitle } </ Text >
0 commit comments