1import { StackNavigationProp } from '@react-navigation/stack'; 2import * as MediaLibrary from 'expo-media-library'; 3import React from 'react'; 4import { 5 FlatList, 6 ListRenderItem, 7 Platform, 8 StyleSheet, 9 Switch, 10 Text, 11 TouchableOpacity, 12 View, 13} from 'react-native'; 14 15import MonoText from '../../components/MonoText'; 16 17interface State { 18 includeSmartAlbums: boolean; 19 albums: MediaLibrary.Album[]; 20} 21 22type Props = { 23 navigation: StackNavigationProp<{ MediaLibrary: { album: MediaLibrary.Album } }>; 24}; 25 26export default class MediaAlbumsScreen extends React.Component<Props, State> { 27 static navigationOptions = { 28 title: 'MediaLibrary Albums', 29 }; 30 31 state: State = { 32 includeSmartAlbums: false, 33 albums: [], 34 }; 35 36 componentDidMount() { 37 this.fetchAlbums(this.state.includeSmartAlbums).then((albums) => this.setState({ albums })); 38 } 39 40 componentDidUpdate(_: Props, lastState: State) { 41 if (lastState.includeSmartAlbums !== this.state.includeSmartAlbums) { 42 this.fetchAlbums(this.state.includeSmartAlbums).then((albums) => this.setState({ albums })); 43 } 44 } 45 46 async fetchAlbums(includeSmartAlbums: boolean) { 47 try { 48 return await MediaLibrary.getAlbumsAsync({ 49 includeSmartAlbums, 50 }); 51 } catch (e) { 52 if (e.code === 'ERR_NO_ENOUGH_PERMISSIONS') { 53 return []; 54 } else { 55 throw e; 56 } 57 } 58 } 59 60 keyExtractor = (item: MediaLibrary.Album) => item.id; 61 62 openAlbum = (album: MediaLibrary.Album) => { 63 this.props.navigation.navigate('MediaLibrary', { album }); 64 }; 65 66 renderItem: ListRenderItem<MediaLibrary.Album> = ({ item }) => { 67 return ( 68 <TouchableOpacity style={styles.album} onPress={() => this.openAlbum(item)}> 69 <View style={styles.albumHeader}> 70 <Text>{item.title}</Text> 71 <Text>{item.assetCount}</Text> 72 </View> 73 <MonoText>{JSON.stringify(item, null, 2)}</MonoText> 74 </TouchableOpacity> 75 ); 76 }; 77 78 renderContent() { 79 const { albums } = this.state; 80 81 if (albums.length === 0) { 82 return ( 83 <View style={styles.noAlbums}> 84 <Text> 85 You don't have any media albums! You can create one from asset details screen. 86 </Text> 87 </View> 88 ); 89 } 90 91 return ( 92 <FlatList 93 data={albums} 94 numColumns={1} 95 keyExtractor={this.keyExtractor} 96 renderItem={this.renderItem} 97 /> 98 ); 99 } 100 101 renderSmartAlbumsToggle() { 102 return ( 103 <View style={styles.includeSmartAlbumsRow}> 104 <Text style={styles.includeSmartAlbumsTitle}>Include smart albums</Text> 105 <Switch 106 value={this.state.includeSmartAlbums} 107 onValueChange={() => 108 this.setState((state) => ({ includeSmartAlbums: !state.includeSmartAlbums })) 109 } 110 /> 111 </View> 112 ); 113 } 114 115 render() { 116 return ( 117 <View style={styles.fill}> 118 {Platform.OS === 'ios' && this.renderSmartAlbumsToggle()} 119 {this.renderContent()} 120 </View> 121 ); 122 } 123} 124 125const styles = StyleSheet.create({ 126 fill: { 127 flex: 1, 128 }, 129 includeSmartAlbumsRow: { 130 flexDirection: 'row', 131 alignItems: 'center', 132 paddingVertical: 6, 133 paddingHorizontal: 10, 134 borderBottomWidth: 1, 135 borderBottomColor: '#cccccc', 136 }, 137 includeSmartAlbumsTitle: { flex: 1, fontSize: 16 }, 138 album: { 139 flex: 1, 140 paddingVertical: 5, 141 paddingHorizontal: 10, 142 borderBottomWidth: StyleSheet.hairlineWidth, 143 borderBottomColor: 'gray', 144 }, 145 albumHeader: { 146 flexDirection: 'row', 147 alignItems: 'center', 148 justifyContent: 'space-between', 149 }, 150 noAlbums: { 151 flex: 1, 152 padding: 10, 153 alignItems: 'center', 154 justifyContent: 'center', 155 }, 156}); 157