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