import MaterialIcons from '@expo/vector-icons/build/MaterialIcons'; import * as FileSystem from 'expo-file-system'; import * as MediaLibrary from 'expo-media-library'; import * as Permissions from 'expo-permissions'; import React from 'react'; import { ScrollView, StyleSheet, Text, TouchableOpacity, TouchableOpacityProps, View, Platform, } from 'react-native'; import Photo from './Photo'; const PHOTOS_DIR = FileSystem.documentDirectory + 'photos'; interface State { selected: string[]; } function useLoadedPhotos() { const [photos, setPhotos] = React.useState([]); React.useEffect(() => { let isMounted = true; if (Platform.OS !== 'web') { FileSystem.readDirectoryAsync(PHOTOS_DIR).then(photos => { if (isMounted) { setPhotos(photos); } }); } return () => { isMounted = false; }; }, []); return photos; } export default function GalleryScreen(props: TouchableOpacityProps & { photos?: string[] }) { const photos = useLoadedPhotos(); return ; } class LoadedGalleryScreen extends React.Component< TouchableOpacityProps & { photos: string[] }, State > { readonly state: State = { selected: [], }; toggleSelection = (uri: string, isSelected: boolean) => { this.setState(({ selected }) => { if (isSelected) { selected.push(uri); } else { selected = selected.filter(item => item !== uri); } return { selected }; }); }; saveToGallery = async () => { const photos = this.state.selected; if (photos.length > 0) { const { status } = await Permissions.askAsync(Permissions.MEDIA_LIBRARY); if (status !== 'granted') { throw new Error('Denied MEDIA_LIBRARY permissions!'); } const promises = photos.map(photoUri => { return MediaLibrary.createAssetAsync(photoUri); }); await Promise.all(promises); alert("Successfully saved photos to user's gallery!"); } else { alert('No photos to save!'); } }; renderPhoto = (fileName: string) => ( ); render() { return ( Save selected to gallery {this.props.photos.map(this.renderPhoto)} ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'white', }, navbar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', backgroundColor: '#4630EB', }, pictures: { flex: 1, flexWrap: 'wrap', flexDirection: 'row', justifyContent: 'space-around', paddingVertical: 8, }, button: { padding: 20, }, whiteText: { color: 'white', }, });