mirror of
https://github.com/status-im/react-native.git
synced 2025-01-16 20:44:10 +00:00
3c806652cf
Summary: The XHRExample file had been forked between iOS and Android for various reasons that are no longer valid, making maintenance unnecessarily difficult. New features demos had in fact been added in separate files to avoid further duplication. This change continues on that same trajectory and splits the entire example file into multiple files. This makes them much easier to handle. We also get rid of the iOS/Android fork. **Test plan:** Run UIExplorer app, specifically the XHR examples, on both iOS and Android. Closes https://github.com/facebook/react-native/pull/11901 Differential Revision: D4419882 Pulled By: ericvicenti fbshipit-source-id: ec12836dfa8e1b9259b92a7510914857a8db58d5
282 lines
7.0 KiB
JavaScript
282 lines
7.0 KiB
JavaScript
/**
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*
|
|
* The examples provided by Facebook are for non-commercial testing and
|
|
* evaluation purposes only.
|
|
*
|
|
* Facebook reserves all rights not expressly granted.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* @flow
|
|
*/
|
|
'use strict';
|
|
|
|
const React = require('react');
|
|
const ReactNative = require('react-native');
|
|
const {
|
|
Alert,
|
|
CameraRoll,
|
|
Image,
|
|
ImageEditor,
|
|
Linking,
|
|
Platform,
|
|
StyleSheet,
|
|
Text,
|
|
TextInput,
|
|
TouchableHighlight,
|
|
View,
|
|
} = ReactNative;
|
|
|
|
const PAGE_SIZE = 20;
|
|
|
|
class XHRExampleFormData extends React.Component {
|
|
state: Object = {
|
|
isUploading: false,
|
|
uploadProgress: null,
|
|
randomPhoto: null,
|
|
textParams: [],
|
|
};
|
|
|
|
_isMounted: boolean = true;
|
|
|
|
constructor(props: Object) {
|
|
super(props);
|
|
this._fetchRandomPhoto();
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this._isMounted = false;
|
|
}
|
|
|
|
_fetchRandomPhoto = () => {
|
|
CameraRoll.getPhotos(
|
|
{first: PAGE_SIZE}
|
|
).then(
|
|
(data) => {
|
|
if (!this._isMounted) {
|
|
return;
|
|
}
|
|
var edges = data.edges;
|
|
var edge = edges[Math.floor(Math.random() * edges.length)];
|
|
var randomPhoto = edge && edge.node && edge.node.image;
|
|
if (randomPhoto) {
|
|
let {width, height} = randomPhoto;
|
|
width *= 0.25;
|
|
height *= 0.25;
|
|
ImageEditor.cropImage(
|
|
randomPhoto.uri,
|
|
{offset: {x: 0, y: 0}, size: {width, height}},
|
|
(uri) => this.setState({randomPhoto: {uri}}),
|
|
(error) => undefined
|
|
);
|
|
}
|
|
},
|
|
(error) => undefined
|
|
);
|
|
};
|
|
|
|
_addTextParam = () => {
|
|
var textParams = this.state.textParams;
|
|
textParams.push({name: '', value: ''});
|
|
this.setState({textParams});
|
|
};
|
|
|
|
_onTextParamNameChange(index, text) {
|
|
var textParams = this.state.textParams;
|
|
textParams[index].name = text;
|
|
this.setState({textParams});
|
|
}
|
|
|
|
_onTextParamValueChange(index, text) {
|
|
var textParams = this.state.textParams;
|
|
textParams[index].value = text;
|
|
this.setState({textParams});
|
|
}
|
|
|
|
_upload = () => {
|
|
var xhr = new XMLHttpRequest();
|
|
xhr.open('POST', 'http://posttestserver.com/post.php');
|
|
xhr.onload = () => {
|
|
this.setState({isUploading: false});
|
|
if (xhr.status !== 200) {
|
|
Alert.alert(
|
|
'Upload failed',
|
|
'Expected HTTP 200 OK response, got ' + xhr.status
|
|
);
|
|
return;
|
|
}
|
|
if (!xhr.responseText) {
|
|
Alert.alert(
|
|
'Upload failed',
|
|
'No response payload.'
|
|
);
|
|
return;
|
|
}
|
|
var index = xhr.responseText.indexOf('http://www.posttestserver.com/');
|
|
if (index === -1) {
|
|
Alert.alert(
|
|
'Upload failed',
|
|
'Invalid response payload.'
|
|
);
|
|
return;
|
|
}
|
|
var url = xhr.responseText.slice(index).split('\n')[0];
|
|
console.log('Upload successful: ' + url);
|
|
Linking.openURL(url);
|
|
};
|
|
var formdata = new FormData();
|
|
if (this.state.randomPhoto) {
|
|
formdata.append('image', {
|
|
...this.state.randomPhoto,
|
|
type: 'image/jpg',
|
|
name: 'image.jpg',
|
|
});
|
|
}
|
|
this.state.textParams.forEach(
|
|
(param) => formdata.append(param.name, param.value)
|
|
);
|
|
xhr.upload.onprogress = (event) => {
|
|
if (event.lengthComputable) {
|
|
this.setState({uploadProgress: event.loaded / event.total});
|
|
}
|
|
};
|
|
|
|
xhr.send(formdata);
|
|
this.setState({isUploading: true});
|
|
};
|
|
|
|
render() {
|
|
var image = null;
|
|
if (this.state.randomPhoto) {
|
|
image = (
|
|
<Image
|
|
source={this.state.randomPhoto}
|
|
style={styles.randomPhoto}
|
|
/>
|
|
);
|
|
}
|
|
var textItems = this.state.textParams.map((item, index) => (
|
|
<View style={styles.paramRow}>
|
|
<TextInput
|
|
autoCapitalize="none"
|
|
autoCorrect={false}
|
|
onChangeText={this._onTextParamNameChange.bind(this, index)}
|
|
placeholder="name..."
|
|
style={styles.textInput}
|
|
/>
|
|
<Text style={styles.equalSign}>=</Text>
|
|
<TextInput
|
|
autoCapitalize="none"
|
|
autoCorrect={false}
|
|
onChangeText={this._onTextParamValueChange.bind(this, index)}
|
|
placeholder="value..."
|
|
style={styles.textInput}
|
|
/>
|
|
</View>
|
|
));
|
|
var uploadButtonLabel = this.state.isUploading ? 'Uploading...' : 'Upload';
|
|
var uploadProgress = this.state.uploadProgress;
|
|
if (uploadProgress !== null) {
|
|
uploadButtonLabel += ' ' + Math.round(uploadProgress * 100) + '%';
|
|
}
|
|
var uploadButton = (
|
|
<View style={styles.uploadButtonBox}>
|
|
<Text style={styles.uploadButtonLabel}>{uploadButtonLabel}</Text>
|
|
</View>
|
|
);
|
|
if (!this.state.isUploading) {
|
|
uploadButton = (
|
|
<TouchableHighlight onPress={this._upload}>
|
|
{uploadButton}
|
|
</TouchableHighlight>
|
|
);
|
|
}
|
|
return (
|
|
<View>
|
|
<View style={styles.paramRow}>
|
|
<Text style={styles.photoLabel}>
|
|
Random photo from your library
|
|
(<Text style={styles.textButton} onPress={this._fetchRandomPhoto}>
|
|
update
|
|
</Text>)
|
|
</Text>
|
|
{image}
|
|
</View>
|
|
{textItems}
|
|
<View>
|
|
<Text
|
|
style={[styles.textButton, styles.addTextParamButton]}
|
|
onPress={this._addTextParam}>
|
|
Add a text param
|
|
</Text>
|
|
</View>
|
|
<View style={styles.uploadButton}>
|
|
{uploadButton}
|
|
</View>
|
|
</View>
|
|
);
|
|
}
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
paramRow: {
|
|
flexDirection: 'row',
|
|
paddingVertical: 8,
|
|
alignItems: 'center',
|
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
borderBottomColor: 'grey',
|
|
},
|
|
photoLabel: {
|
|
flex: 1,
|
|
},
|
|
randomPhoto: {
|
|
width: 50,
|
|
height: 50,
|
|
},
|
|
textButton: {
|
|
color: 'blue',
|
|
},
|
|
addTextParamButton: {
|
|
marginTop: 8,
|
|
},
|
|
textInput: {
|
|
flex: 1,
|
|
borderRadius: 3,
|
|
borderColor: 'grey',
|
|
borderWidth: 1,
|
|
height: Platform.OS === 'android' ? 50 : 30,
|
|
paddingLeft: 8,
|
|
},
|
|
equalSign: {
|
|
paddingHorizontal: 4,
|
|
},
|
|
uploadButton: {
|
|
marginTop: 16,
|
|
},
|
|
uploadButtonBox: {
|
|
flex: 1,
|
|
paddingVertical: 12,
|
|
alignItems: 'center',
|
|
backgroundColor: 'blue',
|
|
borderRadius: 4,
|
|
},
|
|
uploadButtonLabel: {
|
|
color: 'white',
|
|
fontSize: 16,
|
|
fontWeight: '500',
|
|
},
|
|
});
|
|
|
|
module.exports = XHRExampleFormData;
|