1- import React from " react"
2- import PropTypes from " prop-types"
1+ import React from ' react'
2+ import PropTypes from ' prop-types'
33import {
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'
1313
1414export 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