import React from 'react'; import * as MediaLibrary from 'expo-media-library'; import * as Permissions from 'expo-permissions'; import { ActivityIndicator, Button as RNButton, Dimensions, View, Text, StyleSheet, FlatList, RefreshControl, ListRenderItem, } from 'react-native'; import { NavigationEvents, NavigationScreenProps, NavigationScreenConfig } from 'react-navigation'; import Colors from '../../constants/Colors'; import MediaLibraryCell from './MediaLibraryCell'; import Button from '../../components/Button'; import HeadingText from '../../components/HeadingText'; const COLUMNS = 3; const PAGE_SIZE = COLUMNS * 10; const WINDOW_SIZE = Dimensions.get('window'); const mediaTypeStates: { [key in MediaLibrary.MediaTypeValue]: MediaLibrary.MediaTypeValue } = { [MediaLibrary.MediaType.unknown]: MediaLibrary.MediaType.photo, [MediaLibrary.MediaType.photo]: MediaLibrary.MediaType.video, [MediaLibrary.MediaType.video]: MediaLibrary.MediaType.audio, [MediaLibrary.MediaType.audio]: MediaLibrary.MediaType.unknown, }; const sortByStates: { [key in MediaLibrary.SortByKey]: MediaLibrary.SortByKey } = { [MediaLibrary.SortBy.default]: MediaLibrary.SortBy.creationTime, [MediaLibrary.SortBy.creationTime]: MediaLibrary.SortBy.modificationTime, [MediaLibrary.SortBy.modificationTime]: MediaLibrary.SortBy.mediaType, [MediaLibrary.SortBy.mediaType]: MediaLibrary.SortBy.width, [MediaLibrary.SortBy.width]: MediaLibrary.SortBy.height, [MediaLibrary.SortBy.height]: MediaLibrary.SortBy.duration, [MediaLibrary.SortBy.duration]: MediaLibrary.SortBy.default, }; interface State { assets: MediaLibrary.Asset[]; endCursor?: string; hasNextPage?: boolean; permission?: Permissions.PermissionStatus; refreshing: boolean; mediaType: MediaLibrary.MediaTypeValue; sortBy: MediaLibrary.SortByKey; } export default class MediaLibraryScreen extends React.Component { static navigationOptions: NavigationScreenConfig<{}> = ({ navigation }) => { const goToAlbums = () => navigation.navigate('MediaAlbums'); const clearAlbumSelection = () => navigation.setParams({ album: null }); const { params } = navigation.state; const isAlbumSet = params && params.album; return { title: 'MediaLibrary', headerRight: ( ), }; } readonly state: State = { assets: [], refreshing: true, mediaType: MediaLibrary.MediaType.photo, sortBy: MediaLibrary.SortBy.default, }; isLoadingAssets = false; libraryChangeSubscription?: { remove: () => void }; componentDidFocus = async () => { const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL); this.setState({ permission: status, assets: [], endCursor: undefined, hasNextPage: undefined }); this.loadMoreAssets(); if (this.libraryChangeSubscription) { this.libraryChangeSubscription.remove(); } this.libraryChangeSubscription = MediaLibrary.addListener(() => { this.loadMoreAssets([]); }); } componentWillUnmount() { this.libraryChangeSubscription!.remove(); this.libraryChangeSubscription = undefined; } getAlbum() { const { params } = this.props.navigation.state; return params && params.album; } async loadMoreAssets(currentAssets = this.state.assets, cursor = this.state.endCursor) { if ( this.isLoadingAssets || (cursor === this.state.endCursor && this.state.hasNextPage === false) ) { return; } const { state } = this; const album = this.getAlbum(); this.isLoadingAssets = true; const { assets, endCursor, hasNextPage } = await MediaLibrary.getAssetsAsync({ first: PAGE_SIZE, after: cursor, mediaType: state.mediaType, sortBy: state.sortBy, album: album && album.id, }); const lastAsset = currentAssets[currentAssets.length - 1]; if (!lastAsset || lastAsset.id === cursor) { this.setState({ assets: ([] as MediaLibrary.Asset[]).concat(currentAssets, assets), endCursor, hasNextPage, refreshing: false, }); } this.isLoadingAssets = false; } refresh = (refreshingFlag = true) => { this.setState( { assets: [], endCursor: undefined, hasNextPage: undefined, refreshing: refreshingFlag }, () => { this.loadMoreAssets(); } ); } toggleMediaType = () => { const mediaType = mediaTypeStates[this.state.mediaType]; this.setState({ mediaType }); this.refresh(false); } toggleSortBy = () => { const sortBy = sortByStates[this.state.sortBy]; this.setState({ sortBy }); this.refresh(false); } keyExtractor = (item: MediaLibrary.Asset) => item.id; onEndReached = () => { this.loadMoreAssets(); } onCellPress = (asset: MediaLibrary.Asset) => { this.props.navigation.navigate('MediaDetails', { asset, album: this.getAlbum(), onGoBack: this.refresh, }); } renderRowItem: ListRenderItem = ({ item }) => { return ( ); } renderHeader = () => { const album = this.getAlbum(); return ( {album ? `Album: ${album.title}` : 'All albums'}