react-native-camera-roll-gallery
Version:
An easy and simple to use React Native component to render a custom layout for CameraRoll photos (next update will have videos) and displayed on a custom interactive image viewer for manipulation. Includes animations and support for both iOS and Android.
306 lines (285 loc) • 10.9 kB
JavaScript
import React from "react";
import PropTypes from "prop-types";
import {
Text,
Modal,
Platform,
StyleSheet,
SafeAreaView,
View
} from "react-native";
import CameraRollBrowser from "./CameraRollBrowser";
import ImageViewer from "./ImageViewer";
export default class CameraRollGallery extends React.PureComponent {
static propTypes = {
enableCameraRoll: PropTypes.bool,
onGetData: PropTypes.func,
itemCount: PropTypes.number,
imagesPerRow: PropTypes.number,
initialNumToRender: PropTypes.number,
removeClippedSubviews: PropTypes.bool,
cameraRollFlatListProps: PropTypes.object,
catchGetPhotosError: PropTypes.func,
groupTypes: PropTypes.oneOf([
"Album",
"All",
"Event",
"Faces",
"Library",
"PhotoStream",
"SavedPhotos",
]),
assetType: PropTypes.oneOf([
"Photos",
"Videos",
"All",
]),
imageMargin: PropTypes.number,
containerWidth: PropTypes.number,
backgroundColor: PropTypes.string,
emptyText: PropTypes.string,
emptyTextStyle: Text.propTypes.style,
loader: PropTypes.node,
cameraRollListHeader: PropTypes.func,
cameraRollListFooter: PropTypes.func,
imageContainerStyle: PropTypes.object,
renderIndividualHeader: PropTypes.func,
renderIndividualFooter: PropTypes.func,
loaderColor: PropTypes.string,
permissionDialogTitle: PropTypes.string,
permissionDialogMessage: PropTypes.string,
pendingAuthorizedView: PropTypes.oneOfType([
PropTypes.node,
// PropTypes.func
]),
notAuthorizedView: PropTypes.oneOfType([
PropTypes.node,
// PropTypes.func
]),
imagePageComponent: PropTypes.func,
errorPageComponent: PropTypes.func,
pagesFlatListProps: PropTypes.object,
pageMargin: PropTypes.number,
sensitivePageScroll: PropTypes.bool,
onPageSelected: PropTypes.func,
onPageScrollStateChanged: PropTypes.func,
onPageScroll: PropTypes.func,
pageScrollViewStyle: PropTypes.object,
onPageSingleTapConfirmed: PropTypes.func,
onPageLongPress: PropTypes.func,
renderPageHeader: PropTypes.func,
renderPageFooter: PropTypes.func,
onDoubleTapConfirmed: PropTypes.func,
onDoubleTapStartReached: PropTypes.func,
onDoubleTapEndReached: PropTypes.func,
onPinchTransforming: PropTypes.func,
onPinchStartReached: PropTypes.func,
onPinchEndReached: PropTypes.func,
enableScale: PropTypes.bool,
enableTranslate: PropTypes.bool,
resizeMode: PropTypes.string,
enableResistance: PropTypes.bool,
resistantStrHorizontal: PropTypes.oneOfType([
PropTypes.func,
PropTypes.number,
PropTypes.string
]),
resistantStrVertical: PropTypes.oneOfType([
PropTypes.func,
PropTypes.number,
PropTypes.string
]),
onViewTransformed: PropTypes.func,
onTransformGestureReleased: PropTypes.func,
onSwipeUpReleased: PropTypes.func,
onSwipeDownReleased: PropTypes.func,
maxScale: PropTypes.bool,
maxOverScrollDistance: PropTypes.number,
enableVerticalExit: PropTypes.bool,
enableModal: PropTypes.bool,
onEndReached: PropTypes.func,
onEndReachedThreshold: PropTypes.number,
keyExtractor: PropTypes.func,
}
static defaultProps = {
enableCameraRoll: true,
itemCount: 100,
imagesPerRow: 3,
initialNumToRender: 6,
removeClippedSubviews: true,
groupTypes: "All",
assetType: "Photos",
imageMargin: 5,
backgroundColor: "white",
emptyText: "No photos.",
loaderColor: "lightblue",
imageContainerStyle: {},
sensitivePageScroll: false,
enableVerticalExit: true,
enableModal: false,
onEndReachedThreshold: 0.8,
permissionDialogTitle: "Read Storage Permission",
permissionDialogMessage: "Needs access to your photos " +
"so you can use these awesome services.",
}
constructor(props) {
super(props);
this.state = {
resolvedData: [],
displayImageViewer: false,
galleryInitialIndex: 0,
galleryIndex: 0,
imageId: undefined,
loadingMore: false,
noMore: false,
totalCount: 0
};
}
openImageViewer = async (imageId, index) => {
await this.setState({ displayImageViewer: true, imageId, galleryInitialIndex: index });
}
closeImageViewer = () => {
this.setState({ displayImageViewer: false, imageId: undefined });
}
onChangePhoto = (imageId, galleryIndex) => {
this.setState({
imageId,
galleryIndex
});
}
getMoreData = () => {
if (!this.state.noMore) {
this._cameraRollBrowser.fetch(true);
}
}
setMainState = (newState) => {
this.setState(newState);
}
setAssets = (data) => {
this.setState({
resolvedData: this.state.resolvedData.concat(data)
});
}
render() {
let Injectant;
const injectantProps = {};
if (this.props.enableModal) {
Injectant = Modal;
injectantProps.visible = this.state.displayImageViewer &&
this.state.imageId ? true : false;
injectantProps.transparent = true;
injectantProps.animationType = Platform.OS === "ios" ? "none" : "fade";
injectantProps.hardwareAccelerated = true;
injectantProps.onRequestClose = this.closeImageViewer;
} else {
Injectant = View;
}
return (
<View style={styles.container}
{...this.props}>
<CameraRollBrowser
ref={(component) => {
this._cameraRollBrowser = component;
}}
enableCameraRoll={this.props.enableCameraRoll}
onGetData={this.props.onGetData}
itemCount={this.props.itemCount}
images={this.state.resolvedData}
imagesPerRow={this.props.imagesPerRow}
initialNumToRender={this.props.initialNumToRender}
removeClippedSubviews={this.props.removeClippedSubviews}
cameraRollFlatListProps={this.props.cameraRollFlatListProps}
catchGetPhotosError={this.props.catchGetPhotosError}
groupTypes={this.props.groupTypes}
assetType={this.props.assetType}
imageMargin={this.props.imageMargin}
containerWidth={this.props.containerWidth}
backgroundColor={this.props.backgroundColor}
emptyText={this.props.emptyText}
emptyTextStyle={this.props.emptyTextStyle}
loader={this.props.loader}
cameraRollListHeader={this.props.cameraRollListHeader}
cameraRollListFooter={this.props.cameraRollListFooter}
imageContainerStyle={this.props.imageContainerStyle}
renderIndividualHeader={this.props.renderIndividualHeader}
renderIndividualFooter={this.props.renderIndividualFooter}
onEndReached={this.props.onEndReached}
onEndReachedThreshold={this.props.onEndReachedThreshold}
keyExtractor={this.props.keyExtractor}
openImageViewer={this.openImageViewer}
displayImageViewer={this.state.displayImageViewer}
displayedImageId={this.state.imageId}
loaderColor={this.props.loaderColor}
permissionDialogTitle={this.props.permissionDialogTitle}
permissionDialogMessage={this.props.permissionDialogMessage}
pendingAuthorizedView={this.props.pendingAuthorizedView}
notAuthorizedView={this.props.notAuthorizedView}
setMainState={this.setMainState}
setAssets={this.setAssets}
totalCount={this.state.totalCount}
loadingMore={this.state.loadingMore}
noMore={this.state.noMore}
/>
{this.state.displayImageViewer &&
this.state.imageId &&
(
<SafeAreaView>
<Injectant
{...injectantProps}>
<ImageViewer
images={this.state.resolvedData}
imageId={this.state.imageId}
galleryInitialIndex={this.state.galleryInitialIndex}
galleryIndex={this.state.galleryIndex}
onClose={this.closeImageViewer}
onChangePhoto={this.onChangePhoto}
displayImageViewer={this.state.displayImageViewer}
imagePageComponent={this.props.imagePageComponent}
errorPageComponent={this.props.errorPageComponent}
pagesFlatListProps={this.props.pagesFlatListProps}
pageMargin={this.props.pageMargin}
sensitivePageScroll={this.props.sensitivePageScroll}
onPageSelected={this.props.onPageSelected}
onPageScrollStateChanged={this.props.onPageScrollStateChanged}
onPageScroll={this.props.onPageScroll}
pageScrollViewStyle={this.props.pageScrollViewStyle}
onPageSingleTapConfirmed={this.props.onPageSingleTapConfirmed}
onPageLongPress={this.props.onPageLongPress}
renderPageHeader={this.props.renderPageHeader}
renderPageFooter={this.props.renderPageFooter}
onDoubleTapConfirmed={this.props.onDoubleTapConfirmed}
onDoubleTapStartReached={this.props.onDoubleTapStartReached}
onDoubleTapEndReached={this.props.onDoubleTapEndReached}
onPinchTransforming={this.props.onPinchTransforming}
onPinchStartReached={this.props.onPinchStartReached}
onPinchEndReached={this.props.onPinchEndReached}
enableScale={this.props.enableScale}
enableTranslate={this.props.enableTranslate}
resizeMode={this.props.resizeMode}
enableResistance={this.props.enableResistance}
resistantStrHorizontal={this.props.resistantStrHorizontal}
resistantStrVertical={this.props.resistantStrVertical}
onViewTransformed={this.props.onViewTransformed}
onTransformGestureReleased={this.props.onTransformGestureReleased}
onSwipeUpReleased={this.props.onSwipeUpReleased}
onSwipeDownReleased={this.props.onSwipeDownReleased}
maxScale={this.props.maxScale}
maxOverScrollDistance={this.props.maxOverScrollDistance}
enableVerticalExit={this.props.enableVerticalExit}
enableModal={this.props.enableModal}
getMoreData={this.getMoreData}
onEndReached={this.props.onEndReached}
onEndReachedThreshold={this.props.onEndReachedThreshold}
/>
</Injectant>
</SafeAreaView>
)}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});