/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format * @flow strict-local */ 'use strict'; var React = require('react'); var createReactClass = require('create-react-class'); var ReactNative = require('react-native'); var { ActivityIndicator, Image, Platform, StyleSheet, Text, View, ImageBackground, } = ReactNative; var base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg=='; var ImageCapInsetsExample = require('./ImageCapInsetsExample'); const IMAGE_PREFETCH_URL = 'http://origami.design/public/images/bird-logo.png?r=1&t=' + Date.now(); var prefetchTask = Image.prefetch(IMAGE_PREFETCH_URL); /* $FlowFixMe(>=0.63.0 site=react_native_fb) This comment suppresses an error * found when Flow v0.63 was deployed. To see the error delete this comment and * run Flow. */ var NetworkImageCallbackExample = createReactClass({ displayName: 'NetworkImageCallbackExample', getInitialState: function() { return { events: [], startLoadPrefetched: false, mountTime: new Date(), }; }, UNSAFE_componentWillMount() { this.setState({mountTime: new Date()}); }, render: function() { var {mountTime} = this.state; return ( this._loadEventFired(`✔ onLoadStart (+${new Date() - mountTime}ms)`) } onLoad={event => { if (event.nativeEvent.source) { const url = event.nativeEvent.source.url; this._loadEventFired( `✔ onLoad (+${new Date() - mountTime}ms) for URL ${url}`, ); } else { this._loadEventFired(`✔ onLoad (+${new Date() - mountTime}ms)`); } }} onLoadEnd={() => { this._loadEventFired(`✔ onLoadEnd (+${new Date() - mountTime}ms)`); this.setState({startLoadPrefetched: true}, () => { prefetchTask.then( () => { this._loadEventFired( `✔ Prefetch OK (+${new Date() - mountTime}ms)`, ); Image.queryCache([IMAGE_PREFETCH_URL]).then((map) => { var result = map.get(IMAGE_PREFETCH_URL); if (result) { this._loadEventFired( `✔ queryCache "${result}" (+${new Date() - mountTime}ms)`, ); } else { this._loadEventFired( `✘ queryCache (+${new Date() - mountTime}ms)`, ); } }); }, error => { this._loadEventFired( `✘ Prefetch failed (+${new Date() - mountTime}ms)`, ); }, ); }); }} /> {this.state.startLoadPrefetched ? ( this._loadEventFired( `✔ (prefetched) onLoadStart (+${new Date() - mountTime}ms)`, ) } onLoad={event => { // Currently this image source feature is only available on iOS. if (event.nativeEvent.source) { const url = event.nativeEvent.source.url; this._loadEventFired( `✔ (prefetched) onLoad (+${new Date() - mountTime}ms) for URL ${url}`, ); } else { this._loadEventFired( `✔ (prefetched) onLoad (+${new Date() - mountTime}ms)`, ); } }} onLoadEnd={() => this._loadEventFired( `✔ (prefetched) onLoadEnd (+${new Date() - mountTime}ms)`, ) } /> ) : null} {this.state.events.join('\n')} ); }, _loadEventFired(event) { this.setState(state => { return (state.events = [...state.events, event]); }); }, }); var NetworkImageExample = createReactClass({ getInitialState: function() { return { error: false, loading: false, progress: 0, }; }, render: function() { var loader = this.state.loading ? ( {this.state.progress}% ) : null; return this.state.error ? ( {this.state.error} ) : ( this.setState({loading: true})} onError={e => this.setState({error: e.nativeEvent.error, loading: false}) } onProgress={e => this.setState({ progress: Math.round( (100 * e.nativeEvent.loaded) / e.nativeEvent.total, ), }) } onLoad={() => this.setState({loading: false, error: false})}> {loader} ); }, }); var ImageSizeExample = createReactClass({ getInitialState: function() { return { width: 0, height: 0, }; }, componentDidMount: function() { Image.getSize(this.props.source.uri, (width, height) => { this.setState({width, height}); }); }, render: function() { return ( Actual dimensions:{'\n'} Width: {this.state.width}, Height: {this.state.height} ); }, }); var MultipleSourcesExample = createReactClass({ getInitialState: function() { return { width: 30, height: 30, }; }, render: function() { return ( Decrease image size Increase image size Container image size: {this.state.width}x{this.state.height}{' '} ); }, increaseImageSize: function() { if (this.state.width >= 100) { return; } this.setState({ width: this.state.width + 10, height: this.state.height + 10, }); }, decreaseImageSize: function() { if (this.state.width <= 10) { return; } this.setState({ width: this.state.width - 10, height: this.state.height - 10, }); }, }); exports.displayName = (undefined: ?string); exports.framework = 'React'; exports.title = ''; exports.description = 'Base component for displaying different types of images.'; exports.examples = [ { title: 'Plain Network Image', description: 'If the `source` prop `uri` property is prefixed with ' + '"http", then it will be downloaded from the network.', render: function() { return ; }, }, { title: 'Plain Static Image', description: 'Static assets should be placed in the source code tree, and ' + 'required in the same way as JavaScript modules.', render: function() { return ( ); }, }, { title: 'Image Loading Events', render: function() { return ( ); }, }, { title: 'Error Handler', render: function() { return ( ); }, platform: 'ios', }, { title: 'Image Download Progress', render: function() { return ( ); }, platform: 'ios', }, { title: 'defaultSource', description: 'Show a placeholder image when a network image is loading', render: function() { return ( ); }, platform: 'ios', }, { title: 'Cache Policy', description: 'First image has never been loaded before and is instructed not to load unless in cache.' + 'Placeholder image from above will stay. Second image is the same but forced to load regardless of' + ' local cache state.', render: function() { return ( ); }, platform: 'ios', }, { title: 'Border Color', render: function() { return ( ); }, }, { title: 'Border Width', render: function() { return ( ); }, }, { title: 'Border Radius', render: function() { return ( ); }, }, { title: 'Background Color', render: function() { return ( ); }, }, { title: 'Opacity', render: function() { return ( ); }, }, { title: 'Nesting content inside component', render: function() { return ( React ); }, }, { title: 'Nesting content inside component', render: function() { return ( React ); }, }, { title: 'Tint Color', description: 'The `tintColor` style prop changes all the non-alpha ' + 'pixels to the tint color.', render: function() { return ( It also works with downloaded images: ); }, }, { title: 'Resize Mode', description: 'The `resizeMode` style prop controls how the image is ' + 'rendered within the frame.', render: function() { return ( {[smallImage, fullImage].map((image, index) => { return ( Contain Cover Stretch Repeat Center ); })} ); }, }, { title: 'Animated GIF', render: function() { return ( ); }, platform: 'ios', }, { title: 'Base64 image', render: function() { return ( ); }, platform: 'ios', }, { title: 'Cap Insets', description: 'When the image is resized, the corners of the size specified ' + 'by capInsets will stay a fixed size, but the center content and ' + 'borders of the image will be stretched. This is useful for creating ' + 'resizable rounded buttons, shadows, and other resizable assets.', render: function() { return ; }, platform: 'ios', }, { title: 'Image Size', render: function() { return ; }, }, { title: 'MultipleSourcesExample', description: 'The `source` prop allows passing in an array of uris, so that native to choose which image ' + 'to diplay based on the size of the of the target image', render: function() { return ; }, }, { title: 'Legacy local image', description: 'Images shipped with the native bundle, but not managed ' + 'by the JS packager', render: function() { return ; }, }, { title: 'Bundled images', description: 'Images shipped in a separate native bundle', render: function() { return ( ); }, platform: 'ios', }, { title: 'Blur Radius', render: function() { return ( ); }, }, ]; var fullImage = { uri: 'https://facebook.github.io/react-native/img/opengraph.png', }; var smallImage = { uri: 'https://facebook.github.io/react-native/img/favicon.png', }; var styles = StyleSheet.create({ base: { width: 38, height: 38, }, progress: { flex: 1, alignItems: 'center', flexDirection: 'row', width: 100, }, leftMargin: { marginLeft: 10, }, background: { backgroundColor: '#222222', }, sectionText: { marginVertical: 6, }, nestedText: { marginLeft: 12, marginTop: 20, backgroundColor: 'transparent', color: 'white', }, resizeMode: { width: 90, height: 60, borderWidth: 0.5, borderColor: 'black', }, resizeModeText: { fontSize: 11, marginBottom: 3, }, icon: { width: 15, height: 15, }, horizontal: { flexDirection: 'row', }, gif: { flex: 1, height: 200, }, base64: { flex: 1, height: 50, resizeMode: 'contain', }, touchableText: { fontWeight: '500', color: 'blue', }, });