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