1import FontAwesome from '@expo/vector-icons/build/FontAwesome'; 2import { Image } from 'expo-image'; 3import * as MediaLibrary from 'expo-media-library'; 4import React from 'react'; 5import { StyleProp, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native'; 6 7export default class MediaLibraryCell extends React.Component<{ 8 asset: MediaLibrary.Asset; 9 onPress: (asset: MediaLibrary.Asset) => void; 10 style?: StyleProp<ViewStyle>; 11}> { 12 onPress = () => { 13 const { asset } = this.props; 14 this.props.onPress(asset); 15 }; 16 17 getAssetData(asset: MediaLibrary.Asset) { 18 switch (asset.mediaType) { 19 case MediaLibrary.MediaType.photo: 20 return { 21 icon: 'photo', 22 description: `${asset.width}x${asset.height}`, 23 preview: <Image style={styles.preview} source={{ uri: asset.uri }} resizeMode="cover" />, 24 }; 25 case MediaLibrary.MediaType.video: 26 return { 27 icon: 'video-camera', 28 description: `${Math.round(asset.duration)}s`, 29 preview: <Image style={styles.preview} source={{ uri: asset.uri }} resizeMode="cover" />, 30 }; 31 case MediaLibrary.MediaType.audio: 32 return { 33 icon: 'music', 34 description: `${Math.round(asset.duration)}s`, 35 preview: ( 36 <View style={[styles.preview, styles.audioPreview]}> 37 <Text>Audio</Text> 38 </View> 39 ), 40 }; 41 default: 42 return null; 43 } 44 } 45 46 render() { 47 const { asset, style } = this.props; 48 const data = this.getAssetData(asset); 49 50 return ( 51 <TouchableOpacity style={[styles.container, style]} onPress={this.onPress}> 52 {data && data.preview} 53 {data && ( 54 <View style={styles.cellFooter}> 55 <FontAwesome name={data.icon as any} size={12} color="white" /> 56 <Text style={styles.description}>{data.description}</Text> 57 </View> 58 )} 59 </TouchableOpacity> 60 ); 61 } 62} 63 64const styles = StyleSheet.create({ 65 container: { 66 aspectRatio: 1, 67 padding: 1, 68 }, 69 preview: { 70 flex: 1, 71 }, 72 audioPreview: { 73 flexDirection: 'row', 74 alignItems: 'center', 75 justifyContent: 'center', 76 }, 77 cellFooter: { 78 height: 18, 79 paddingHorizontal: 5, 80 flexDirection: 'row', 81 alignItems: 'center', 82 backgroundColor: 'rgba(0, 0, 0, 0.5)', 83 position: 'absolute', 84 left: 1, 85 right: 1, 86 bottom: 1, 87 }, 88 description: { 89 paddingHorizontal: 5, 90 fontSize: 12, 91 color: 'white', 92 }, 93}); 94