UNPKG

react-native-photoeditorsdk

Version:

A React Native module for PhotoEditor SDK. Integrate the photo editor into your own HTML5, iOS or Android app - in minutes!

198 lines (184 loc) 7.55 kB
import { Component } from 'react'; import { Image, NativeModules, Platform } from 'react-native'; import { Configuration } from './configuration'; const { RNPhotoEditorSDK } = NativeModules; function resolveStaticAsset(assetSource, extractURI = true) { const resolvedSource = Image.resolveAssetSource(assetSource); const source = (resolvedSource != null) ? resolvedSource : assetSource; if (extractURI) { return (source == null) ? null : ((source.uri != null) ? source.uri : source); } return source } function getNestedObject(nestedObject, pathArray) { return pathArray.reduce((obj, key) => (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObject); } function resolveNestedAsset(nestedObject, pathArray) { let asset = getNestedObject(nestedObject, pathArray); // Resolve `asset` if it is a number (opaque type returned by require('./foo.png')) if (asset && typeof asset === 'number') { let key = pathArray.pop(); let obj = getNestedObject(nestedObject, pathArray); obj[key] = resolveStaticAsset(asset); } } function resolveStaticAssets(configuration) { let videoClipCategories = getNestedObject(configuration, ["composition", "categories"]); if (videoClipCategories) { for (let category of videoClipCategories) { resolveNestedAsset(category, ["thumbnailURI"]); let videoClips = getNestedObject(category, ["items"]); if (videoClips) { for (let videoClip of videoClips) { resolveNestedAsset(videoClip, ["thumbnailURI"]); resolveNestedAsset(videoClip, ["videoURI"]); } } } } let audioClipCategories = getNestedObject(configuration, ["audio", "categories"]); if (audioClipCategories) { for (let category of audioClipCategories) { resolveNestedAsset(category, ["thumbnailURI"]); let audioClips = getNestedObject(category, ["items"]); if (audioClips) { for (let audioClip of audioClips) { resolveNestedAsset(audioClip, ["thumbnailURI"]); resolveNestedAsset(audioClip, ["audioURI"]); } } } } let filterCategories = getNestedObject(configuration, ["filter", "categories"]); if (filterCategories) { for (let category of filterCategories) { resolveNestedAsset(category, ["thumbnailURI"]); let filters = getNestedObject(category, ["items"]); if (filters) { for (let filter of filters) { resolveNestedAsset(filter, ["lutURI"]); } } } } let stickerCategories = getNestedObject(configuration, ["sticker", "categories"]); if (stickerCategories) { for (let category of stickerCategories) { resolveNestedAsset(category, ["thumbnailURI"]); let stickers = getNestedObject(category, ["items"]); if (stickers) { for (let sticker of stickers) { resolveNestedAsset(sticker, ["thumbnailURI"]); resolveNestedAsset(sticker, ["stickerURI"]); } } } } let fonts = getNestedObject(configuration, ["text", "fonts"]); if (fonts) { for (let font of fonts) { resolveNestedAsset(font, ["fontURI"]); } } let overlays = getNestedObject(configuration, ["overlay", "items"]); if (overlays) { for (let overlay of overlays) { resolveNestedAsset(overlay, ["thumbnailURI"]); resolveNestedAsset(overlay, ["overlayURI"]); } } let frames = getNestedObject(configuration, ["frame", "items"]); if (frames) { for (let frame of frames) { resolveNestedAsset(frame, ["thumbnailURI"]); resolveNestedAsset(frame, ["imageGroups", "top", "startURI"]); resolveNestedAsset(frame, ["imageGroups", "top", "midURI"]); resolveNestedAsset(frame, ["imageGroups", "top", "endURI"]); resolveNestedAsset(frame, ["imageGroups", "left", "startURI"]); resolveNestedAsset(frame, ["imageGroups", "left", "midURI"]); resolveNestedAsset(frame, ["imageGroups", "left", "endURI"]); resolveNestedAsset(frame, ["imageGroups", "right", "startURI"]); resolveNestedAsset(frame, ["imageGroups", "right", "midURI"]); resolveNestedAsset(frame, ["imageGroups", "right", "endURI"]); resolveNestedAsset(frame, ["imageGroups", "bottom", "startURI"]); resolveNestedAsset(frame, ["imageGroups", "bottom", "midURI"]); resolveNestedAsset(frame, ["imageGroups", "bottom", "endURI"]); } } let watermark = getNestedObject(configuration, ["watermark"]); if (watermark) { resolveNestedAsset(watermark, ["watermarkURI"]); } } class PESDK { /** * Modally present a photo editor. * @note EXIF meta data is only preserved in the edited image if and only if the source * image is loaded from a local `file://` resource. * * @param {string | {uri: string} | number} image The source of the image to be edited. * Can be either an URI (local, remote, data resource, or any other registered scheme for the * React Native image loader), an object with a member `uri`, or an asset reference which can * be optained by, e.g., `require('./image.png')` as `number`. If this parameter is `null`, * the `serialization` parameter must not be `null` and it must contain an embedded source image. * @param {Configuration} configuration The configuration used to initialize the editor. * @param {object} serialization The serialization used to initialize the editor. This * restores a previous state of the editor by re-applying all modifications to the loaded * image. * * @return {Promise<PhotoEditorResult | null>} Returns a `PhotoEditorResult` or `null` if the editor * is dismissed without exporting the edited image. */ static openEditor(image = null, configuration = null, serialization = null) { resolveStaticAssets(configuration) const source = resolveStaticAsset(image, Platform.OS == 'android'); if (Platform.OS == 'android') { return RNPhotoEditorSDK.present(source, configuration, serialization != null ? JSON.stringify(serialization) : null); } else { return RNPhotoEditorSDK.present(source, configuration, serialization); } } /** * Unlock PhotoEditor SDK with a license. * * @param {string | object} license The license used to unlock the SDK. Can be either an URI * pointing to a local `file://` resource that contains the license, the license as a string, * or the license as an object which can be optained by, e.g., `require('./pesdk_license')` * where the required license files must be named `./pesdk_license.ios.json` for the iOS license * and `./pesdk_license.android.json` for the Android license file in order to get automatically * resolved by the packager. */ static unlockWithLicense(license) { return RNPhotoEditorSDK.unlockWithLicense(JSON.stringify(license)); } } class PhotoEditorModal extends Component { state = { visible: false } static getDerivedStateFromProps = (props, state) => { const { image, configuration, serialization, onExport, onCancel, onError } = props; if (props.visible && !state.visible) { PESDK.openEditor(image, configuration, serialization).then(result => { if (result !== null) { onExport(result); } else { if (onCancel) { onCancel(); } } }).catch((error) => { if (onError) { onError(error); } }); } return ({ visible: props.visible }) } render() { return null; } } export * from './configuration'; export { PESDK, PhotoEditorModal };