1import { LinearGradient } from 'expo-linear-gradient'; 2import * as MediaLibrary from 'expo-media-library'; 3import { Platform } from 'expo-modules-core'; 4import React from 'react'; 5import { Dimensions, Image, ScrollView, StyleSheet, Text, View } from 'react-native'; 6import { captureRef as takeSnapshotAsync, captureScreen } from 'react-native-view-shot'; 7 8import Button from '../components/Button'; 9 10// Source: https://codepen.io/zessx/pen/rDEAl <3 11const gradientColors = ['#90dffe', '#38a3d1']; 12 13interface State { 14 image?: string; 15 screenUri?: string; 16} 17 18export default class ViewShotScreen extends React.Component<object, State> { 19 static navigationOptions = { 20 title: 'ViewShot', 21 }; 22 23 readonly state: State = {}; 24 view?: View; 25 26 handleRef = (ref: View) => { 27 this.view = ref; 28 }; 29 30 handlePress = async () => { 31 try { 32 const image = await takeSnapshotAsync(this.view!, { 33 format: 'png', 34 quality: 0.5, 35 result: 'data-uri', 36 }); 37 this.setState({ image }); 38 } catch (e) { 39 console.error(e); 40 } 41 }; 42 43 handleScreenCapturePress = async () => { 44 if (Platform.OS === 'web') { 45 try { 46 const screenUri = await takeSnapshotAsync(undefined as unknown as number, { 47 format: 'jpg', 48 quality: 0.8, 49 result: 'data-uri', 50 }); 51 this.setState({ screenUri }); 52 } catch (e) { 53 console.error(e); 54 } 55 return; 56 } 57 const uri = await captureScreen({ 58 format: 'jpg', 59 quality: 0.8, 60 }); 61 this.setState({ screenUri: uri }); 62 }; 63 64 handleAddToMediaLibraryPress = async () => { 65 const uri = this.state.screenUri; 66 67 if (uri) { 68 const { status } = await MediaLibrary.requestPermissionsAsync(); 69 70 if (status === 'granted') { 71 await MediaLibrary.createAssetAsync(uri); 72 alert('Successfully added captured screen to media library'); 73 } else { 74 alert('Media library permissions not granted'); 75 } 76 } 77 }; 78 79 render() { 80 const imageSource = { uri: this.state.image }; 81 return ( 82 <ScrollView contentContainerStyle={{ alignItems: 'center' }}> 83 <View style={styles.snapshotContainer} ref={this.handleRef} collapsable={false}> 84 <LinearGradient 85 colors={gradientColors} 86 style={styles.gradient} 87 start={[0, 0]} 88 end={[0, 1]}> 89 <Image style={styles.snapshot} source={imageSource} /> 90 <Text style={styles.text}>Snapshot will show above</Text> 91 </LinearGradient> 92 </View> 93 <Button style={styles.button} onPress={this.handlePress} title="TAKE THE (SNAP)SHOT!" /> 94 <Button 95 style={styles.button} 96 onPress={this.handleScreenCapturePress} 97 title="Capture whole screen" 98 /> 99 <Image 100 style={{ 101 width: Dimensions.get('window').width, 102 height: Dimensions.get('window').height, 103 borderColor: '#f00', 104 borderWidth: 10, 105 }} 106 source={{ uri: this.state.screenUri }} 107 /> 108 <Button 109 style={styles.button} 110 disabled={!this.state.screenUri} 111 onPress={this.handleAddToMediaLibraryPress} 112 title="Add to media library" 113 /> 114 </ScrollView> 115 ); 116 } 117} 118 119const styles = StyleSheet.create({ 120 snapshotContainer: { 121 height: 200, 122 alignSelf: 'stretch', 123 alignItems: 'stretch', 124 justifyContent: 'space-around', 125 }, 126 gradient: { 127 flex: 1, 128 alignItems: 'center', 129 }, 130 snapshot: { 131 width: 150, 132 height: 150, 133 }, 134 text: { 135 margin: 10, 136 color: '#fff', 137 fontWeight: '700', 138 }, 139 button: { 140 margin: 15, 141 }, 142}); 143