react-native/Libraries/CameraRoll/CameraRoll.js

245 lines
6.6 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
const PropTypes = require('prop-types');
const {checkPropTypes} = PropTypes;
const RCTCameraRollManager = require('NativeModules').CameraRollManager;
const createStrictShapeTypeChecker = require('createStrictShapeTypeChecker');
const invariant = require('fbjs/lib/invariant');
const GROUP_TYPES_OPTIONS = {
Album: 'Album',
All: 'All',
Event: 'Event',
Faces: 'Faces',
Library: 'Library',
PhotoStream: 'PhotoStream',
SavedPhotos: 'SavedPhotos', // default
};
const ASSET_TYPE_OPTIONS = {
All: 'All',
Videos: 'Videos',
Photos: 'Photos',
};
type GetPhotosParams = {
first: number,
after?: string,
groupTypes?: $Keys<typeof GROUP_TYPES_OPTIONS>,
groupName?: string,
assetType?: $Keys<typeof ASSET_TYPE_OPTIONS>,
mimeTypes?: Array<string>,
};
/**
* Shape of the param arg for the `getPhotos` function.
*/
const getPhotosParamChecker = createStrictShapeTypeChecker({
/**
* The number of photos wanted in reverse order of the photo application
* (i.e. most recent first for SavedPhotos).
*/
first: PropTypes.number.isRequired,
/**
* A cursor that matches `page_info { end_cursor }` returned from a previous
* call to `getPhotos`
*/
after: PropTypes.string,
/**
* Specifies which group types to filter the results to.
*/
groupTypes: PropTypes.oneOf(Object.keys(GROUP_TYPES_OPTIONS)),
/**
* Specifies filter on group names, like 'Recent Photos' or custom album
* titles.
*/
groupName: PropTypes.string,
/**
* Specifies filter on asset type
*/
assetType: PropTypes.oneOf(Object.keys(ASSET_TYPE_OPTIONS)),
/**
* Filter by mimetype (e.g. image/jpeg).
*/
mimeTypes: PropTypes.arrayOf(PropTypes.string),
});
type GetPhotosReturn = Promise<{
edges: Array<{
node: {
type: string,
group_name: string,
image: {
uri: string,
height: number,
width: number,
isStored?: boolean,
playableDuration: number,
},
timestamp: number,
location?: {
latitude?: number,
longitude?: number,
altitude?: number,
heading?: number,
speed?: number,
},
},
}>,
page_info: {
has_next_page: boolean,
start_cursor?: string,
end_cursor?: string,
},
}>;
/**
* Shape of the return value of the `getPhotos` function.
*/
const getPhotosReturnChecker = createStrictShapeTypeChecker({
edges: PropTypes.arrayOf(
/* $FlowFixMe(>=0.66.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.66 was deployed. To see the error delete this
* comment and run Flow. */
createStrictShapeTypeChecker({
node: createStrictShapeTypeChecker({
type: PropTypes.string.isRequired,
group_name: PropTypes.string.isRequired,
image: createStrictShapeTypeChecker({
uri: PropTypes.string.isRequired,
height: PropTypes.number.isRequired,
width: PropTypes.number.isRequired,
isStored: PropTypes.bool,
playableDuration: PropTypes.number.isRequired,
}).isRequired,
timestamp: PropTypes.number.isRequired,
location: createStrictShapeTypeChecker({
latitude: PropTypes.number,
longitude: PropTypes.number,
altitude: PropTypes.number,
heading: PropTypes.number,
speed: PropTypes.number,
}),
}).isRequired,
}),
).isRequired,
page_info: createStrictShapeTypeChecker({
has_next_page: PropTypes.bool.isRequired,
start_cursor: PropTypes.string,
end_cursor: PropTypes.string,
}).isRequired,
});
/**
* `CameraRoll` provides access to the local camera roll or photo library.
*
* See https://facebook.github.io/react-native/docs/cameraroll.html
*/
class CameraRoll {
static GroupTypesOptions: Object = GROUP_TYPES_OPTIONS;
static AssetTypeOptions: Object = ASSET_TYPE_OPTIONS;
/**
* `CameraRoll.saveImageWithTag()` is deprecated. Use `CameraRoll.saveToCameraRoll()` instead.
*/
static saveImageWithTag(tag: string): Promise<string> {
console.warn(
'`CameraRoll.saveImageWithTag()` is deprecated. Use `CameraRoll.saveToCameraRoll()` instead.',
);
return this.saveToCameraRoll(tag, 'photo');
}
static deletePhotos(photos: Array<string>) {
return RCTCameraRollManager.deletePhotos(photos);
}
/**
* Saves the photo or video to the camera roll or photo library.
*
* See https://facebook.github.io/react-native/docs/cameraroll.html#savetocameraroll
*/
static saveToCameraRoll(
tag: string,
type?: 'photo' | 'video',
): Promise<string> {
invariant(
typeof tag === 'string',
'CameraRoll.saveToCameraRoll must be a valid string.',
);
invariant(
type === 'photo' || type === 'video' || type === undefined,
`The second argument to saveToCameraRoll must be 'photo' or 'video'. You passed ${type ||
'unknown'}`,
);
let mediaType = 'photo';
if (type) {
mediaType = type;
} else if (['mov', 'mp4'].indexOf(tag.split('.').slice(-1)[0]) >= 0) {
mediaType = 'video';
}
return RCTCameraRollManager.saveToCameraRoll(tag, mediaType);
}
/**
* Returns a Promise with photo identifier objects from the local camera
* roll of the device matching shape defined by `getPhotosReturnChecker`.
*
* See https://facebook.github.io/react-native/docs/cameraroll.html#getphotos
*/
static getPhotos(params: GetPhotosParams): GetPhotosReturn {
if (__DEV__) {
checkPropTypes(
{params: getPhotosParamChecker},
{params},
'params',
'CameraRoll.getPhotos',
);
}
if (arguments.length > 1) {
console.warn(
'CameraRoll.getPhotos(tag, success, error) is deprecated. Use the returned Promise instead',
);
let successCallback = arguments[1];
if (__DEV__) {
const callback = arguments[1];
successCallback = response => {
checkPropTypes(
{response: getPhotosReturnChecker},
{response},
'response',
'CameraRoll.getPhotos callback',
);
callback(response);
};
}
const errorCallback = arguments[2] || (() => {});
RCTCameraRollManager.getPhotos(params).then(
successCallback,
errorCallback,
);
}
// TODO: Add the __DEV__ check back in to verify the Promise result
return RCTCameraRollManager.getPhotos(params);
}
}
module.exports = CameraRoll;