1
- import React from " react"
2
- import PropTypes from " prop-types"
1
+ import React from ' react'
2
+ import PropTypes from ' prop-types'
3
3
import {
4
- View ,
5
- Image ,
6
- StyleSheet ,
7
- TouchableOpacity ,
8
- Platform
9
- } from " react-native"
10
- import ImagePicker from " react-native-image-picker"
11
- import ImageResizer from " react-native-image-resizer"
12
- import RNFS from " react-native-fs"
4
+ View ,
5
+ Image ,
6
+ StyleSheet ,
7
+ TouchableOpacity ,
8
+ Platform
9
+ } from ' react-native'
10
+ import ImagePicker from ' react-native-image-picker'
11
+ import ImageResizer from ' react-native-image-resizer'
12
+ import RNFS from ' react-native-fs'
13
13
14
14
export default class PhotoUpload extends React . Component {
15
- static propTypes = {
16
- containerStyle : PropTypes . object ,
17
- photoPickerTitle : PropTypes . string ,
18
- maxHeight : PropTypes . number ,
19
- maxWidth : PropTypes . number ,
20
- format : PropTypes . string ,
21
- quality : PropTypes . number ,
22
- onPhotoSelect : PropTypes . func , // returns the base64 string of uploaded photo
23
- onError : PropTypes . func , // if any error occur with response
24
- onTapCustomButton : PropTypes . func , // on tap custom button
25
- onStart : PropTypes . func , // when user starts (useful for loading, etc)
26
- onCancel : PropTypes . func , // when user cancel
27
- onResponse : PropTypes . func , // on response exists!
28
- onRender : PropTypes . func , // after render
29
- onResizedImageUri : PropTypes . func , // when image resized is ready
30
- imagePickerProps : PropTypes . object // react-native-image-picker props
31
- }
32
-
33
- state = {
34
- maxHeight : this . props . height || 600 ,
35
- maxWidth : this . props . width || 600 ,
36
- format : this . props . format || "JPEG" ,
37
- quality : this . props . quality || 100 ,
38
- buttonDisabled : false
39
- }
40
-
41
- options = {
42
- title : this . props . photoPickerTitle || "Select Photo" ,
43
- storageOptions : {
44
- skipBackup : true ,
45
- path : "images"
46
- } ,
47
- ...this . props . imagePickerProps
48
- }
49
-
50
- openImagePicker = ( ) => {
51
- this . setState ( { buttonDisabled : true } )
52
- if ( this . props . onStart ) this . props . onStart ( )
53
-
54
- // get image from image picker
55
- ImagePicker . showImagePicker ( this . options , async response => {
56
- this . setState ( { buttonDisabled : false } )
57
-
58
- let rotation = 0
59
- const { originalRotation } = response
60
-
61
- if ( this . props . onResponse ) this . props . onResponse ( response )
62
-
63
- if ( response . didCancel ) {
64
- console . log ( "User cancelled image picker" )
65
- if ( this . props . onCancel )
66
- this . props . onCancel ( "User cancelled image picker" )
67
- return
68
- } else if ( response . error ) {
69
- console . log ( "ImagePicker Error: " , response . error )
70
- if ( this . props . onError ) this . props . onError ( response . error )
71
- return
72
- } else if ( response . customButton ) {
73
- console . log (
74
- "User tapped custom button: " ,
75
- response . customButton
76
- )
77
- if ( this . props . onTapCustomButton )
78
- this . props . onTapCustomButton ( response . customButton )
79
- return
80
- }
81
-
82
- let { maxHeight, maxWidth, quality, format } = this . state
83
-
84
- //Determining rotation param
85
- if ( originalRotation === 90 ) {
86
- rotation = 90
87
- } else if ( originalRotation === 180 ) {
88
- //For a few images rotation is 180.
89
- rotation = - 180
90
- } else if ( originalRotation === 270 ) {
91
- //When taking images with the front camera (selfie), the rotation is 270.
92
- rotation = - 90
93
- }
94
- // resize image
95
- const resizedImageUri = await ImageResizer . createResizedImage (
96
- `data:image/jpeg;base64,${ response . data } ` ,
97
- maxHeight ,
98
- maxWidth ,
99
- format ,
100
- quality ,
101
- rotation
102
- )
103
-
104
- if ( this . props . onResizedImageUri )
105
- this . props . onResizedImageUri ( resizedImageUri )
106
-
107
- const filePath =
108
- Platform . OS === "android" && resizedImageUri . uri . replace
109
- ? resizedImageUri . uri . replace ( "file:/data" , "/data" )
110
- : resizedImageUri . uri
111
-
112
- // convert image back to base64 string
113
- const photoData = await RNFS . readFile ( filePath , "base64" )
114
- let source = { uri : resizedImageUri . uri }
115
- this . setState ( {
116
- avatarSource : source
117
- } )
118
-
119
- // handle photo in props functions as data string
120
- if ( this . props . onPhotoSelect ) this . props . onPhotoSelect ( photoData )
121
- } )
122
- }
123
-
124
- renderChildren = props => {
125
- return React . Children . map ( props . children , child => {
126
- if ( child && child . type === Image && this . state . avatarSource ) {
127
- return React . cloneElement ( child , {
128
- source : this . state . avatarSource
129
- } )
130
- } else return child
131
- } )
132
- }
133
-
134
- componentDidUpdate ( ) {
135
- if ( this . props . onAfterRender ) this . props . onAfterRender ( this . state )
136
- }
137
-
138
- render ( ) {
139
- return (
140
- < View style = { [ styles . container , this . props . containerStyle ] } >
141
- < TouchableOpacity
142
- onPress = { this . openImagePicker }
143
- disabled = { this . state . buttonDisabled }
144
- >
145
- { this . renderChildren ( this . props ) }
146
- </ TouchableOpacity >
147
- </ View >
148
- )
149
- }
150
- }
15
+ static propTypes = {
16
+ containerStyle : PropTypes . object ,
17
+ photoPickerTitle : PropTypes . string ,
18
+ maxHeight : PropTypes . number ,
19
+ maxWidth : PropTypes . number ,
20
+ format : PropTypes . string ,
21
+ quality : PropTypes . number ,
22
+ onPhotoSelect : PropTypes . func , // returns the base64 string of uploaded photo
23
+ onError : PropTypes . func , // if any error occur with response
24
+ onTapCustomButton : PropTypes . func , // on tap custom button
25
+ onStart : PropTypes . func , // when user starts (useful for loading, etc)
26
+ onCancel : PropTypes . func , // when user cancel
27
+ onResponse : PropTypes . func , // on response exists!
28
+ onRender : PropTypes . func , // after render
29
+ onResizedImageUri : PropTypes . func , // when image resized is ready
30
+ imagePickerProps : PropTypes . object // react-native-image-picker props
31
+ }
32
+
33
+ state = {
34
+ maxHeight : this . props . height || 600 ,
35
+ maxWidth : this . props . width || 600 ,
36
+ format : this . props . format || 'JPEG' ,
37
+ quality : this . props . quality || 100 ,
38
+ buttonDisabled : false
39
+ }
40
+
41
+ options = {
42
+ title : this . props . photoPickerTitle || 'Select Photo' ,
43
+ storageOptions : {
44
+ skipBackup : true ,
45
+ path : 'images'
46
+ } ,
47
+ ...this . props . imagePickerProps
48
+ }
49
+
50
+ openImagePicker = ( ) => {
51
+ this . setState ( { buttonDisabled : true } )
52
+ if ( this . props . onStart ) this . props . onStart ( )
53
+
54
+ // get image from image picker
55
+ ImagePicker . showImagePicker ( this . options , async response => {
56
+ this . setState ( { buttonDisabled : false } )
57
+
58
+ let rotation = 0
59
+ const { originalRotation } = response
60
+
61
+
62
+ if ( this . props . onResponse ) this . props . onResponse ( response )
63
+
64
+ if ( response . didCancel ) {
65
+ console . log ( 'User cancelled image picker' )
66
+ if ( this . props . onCancel ) this . props . onCancel ( 'User cancelled image picker' )
67
+ return
68
+ } else if ( response . error ) {
69
+ console . log ( 'ImagePicker Error: ' , response . error )
70
+ if ( this . props . onError ) this . props . onError ( response . error )
71
+ return
72
+ } else if ( response . customButton ) {
73
+ console . log ( 'User tapped custom button: ' , response . customButton )
74
+ if ( this . props . onTapCustomButton ) this . props . onTapCustomButton ( response . customButton )
75
+ return
76
+ }
77
+
78
+ let { maxHeight, maxWidth, quality, format } = this . state
79
+
80
+ //Determining rotation param
81
+ if ( originalRotation === 90 ) {
82
+ rotation = 90
83
+ } else if ( originalRotation === 180 ) {
84
+ //For a few images rotation is 180.
85
+ rotation = - 180
86
+ } else if ( originalRotation === 270 ) {
87
+ //When taking images with the front camera (selfie), the rotation is 270.
88
+ rotation = - 90
89
+ }
90
+ // resize image
91
+ const resizedImageUri = await ImageResizer . createResizedImage (
92
+ `data:image/jpeg;base64,${ response . data } ` ,
93
+ maxHeight ,
94
+ maxWidth ,
95
+ format ,
96
+ quality ,
97
+ rotation
98
+ )
99
+
100
+ if ( this . props . onResizedImageUri ) this . props . onResizedImageUri ( resizedImageUri )
101
+
102
+ const filePath = Platform . OS === 'android' && resizedImageUri . uri . replace
103
+ ? resizedImageUri . uri . replace ( 'file:/data' , '/data' )
104
+ : resizedImageUri . uri
105
+
106
+ // convert image back to base64 string
107
+ const photoData = await RNFS . readFile ( filePath , 'base64' )
108
+ let source = { uri : resizedImageUri . uri }
109
+ this . setState ( {
110
+ avatarSource : source
111
+ } )
112
+
113
+ // handle photo in props functions as data string
114
+ if ( this . props . onPhotoSelect ) this . props . onPhotoSelect ( photoData )
115
+ } )
116
+ }
117
+
118
+ renderChildren = props => {
119
+ return React . Children . map ( props . children , child => {
120
+ if ( child && child . type === Image && this . state . avatarSource ) {
121
+ return React . cloneElement ( child , {
122
+ source : this . state . avatarSource
123
+ } )
124
+ } else return child
125
+ } )
126
+ }
127
+
128
+ componentDidUpdate ( ) {
129
+ if ( this . props . onAfterRender ) this . props . onAfterRender ( this . state )
130
+ }
131
+
132
+ render ( ) {
133
+ return (
134
+ < View style = { [ this . props . containerStyle ] } >
135
+ < TouchableOpacity
136
+ onPress = { this . openImagePicker }
137
+ disabled = { this . state . buttonDisabled }
138
+ >
139
+ { this . renderChildren ( this . props ) }
140
+ </ TouchableOpacity >
141
+ </ View >
142
+ )
143
+ }
144
+ }
0 commit comments