Giter Club home page Giter Club logo

react-native-photos-framework's Introduction

react-native-photos-framework Build Status npm version Beerpay

Example project

NOTE: This is not a GUI-component, it's an API. The example project just shows off some of the the capabilities of this API.

Breaking Changes

react-native header imports have changed in v0.40, and that means breaking changes for all! Reference PR & Discussion. This library is updated to work with the new imports. Use version < 0.0.64 if your still < RN 0.40.

Description

Load photos/videos and more from CameraRoll and iCloud. Uses Apples photos framework.

  • Advanced options for loading and filtering.
  • Support for displaying both Images and Videos simply in your app.
  • Create, modify, delete photos, videos and albums.
  • Support for sending photos and videos to a server using Ajax.
  • Change-tracking. (eg. someone takes a new photo while your app is open, this library will provide you with events to refresh your collection so it will display the latest changes to the photo-library).

React Native comes with it's own CameraRoll library. This however uses ALAssetLibrary which is a deprecated API from Apple and can only load photos and videos stored on the users device. This is not what your user expects today. Most users photos live on iCloud and these won't show if you use ALAssetLibrary.

If you use this library (Photos framework) you can display the users local resources and the users iCloud resources.

Installation:

npm i react-native-photos-framework --save && react-native link react-native-photos-framework

NOTE: When running npm install this library will try to automatically add NSPhotoLibraryUsageDescription to your Info.plist. Check that it is there after the install or update it's value from the default: Using photo library to select pictures (Will not do anything if you have already defined this key in Info.plist)

Simple example:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, Text, View, Image} from 'react-native';
import RNPhotosFramework from 'react-native-photos-framework';

export default class AwesomeProject extends Component {

    constructor() {
      super();
      this.state = {
        images : []
      };
    }

    componentDidMount() {
        RNPhotosFramework.requestAuthorization().then((statusObj) => {
            if (statusObj.isAuthorized) {
                RNPhotosFramework.getAlbums({
                    type: 'smartAlbum',
                    subType: 'smartAlbumUserLibrary',
                    assetCount: 'exact',
                    fetchOptions: {
                        sortDescriptors: [
                            {
                                key: 'title',
                                ascending: true
                            }
                        ],
                        includeHiddenAssets: false,
                        includeAllBurstAssets: false
                    },
                    //When you say 'trackInsertsAndDeletes or trackChanges' for an albums query result,
                    //They will be cached and tracking will start.
                    //Call queryResult.stopTracking() to stop this. ex. on componentDidUnmount
                    trackInsertsAndDeletes: true,
                    trackChanges: false

                }).then((queryResult) => {
                    const album = queryResult.albums[0];
                    return album.getAssets({
                        //The fetch-options from the outer query will apply here, if we get
                        startIndex: 0,
                        endIndex: 10,
                        //When you say 'trackInsertsAndDeletes or trackAssetsChange' for an albums assets,
                        //They will be cached and tracking will start.
                        //Call album.stopTracking() to stop this. ex. on componentDidUnmount
                        trackInsertsAndDeletes: true,
                        trackChanges: false
                    }).then((response) => {
                        this.setState({
                          images : response.assets
                        });
                    });
                });
            }
        });
    }

    renderImage(asset, index) {
      return (
        <Image key={index} source={asset.image} style={{width : 100, height : 100}}></Image>
      );
    }

    render() {
        return (
            <View style={styles.container}>
                {this.state.images.map(this.renderImage.bind(this))}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF'
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5
    }
});

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

API-documentation:

Library (Top level):

Static methods:

authorizationStatus

  RNPhotosFramework.authorizationStatus().then(() => {
  });

Signature: RNPhotosFramework.authorizationStatus() : Promise<{status : string, isAuthorized : boolean}>. Fetches the current authorization-status. NOTE: You can receive the following statuses :

  • notDetermined //Before user has granted permission,
  • restricted //User is restricted by policy, cannot use Photos,
  • denied //User has denied permission,
  • authorized //User has granted permission

requestAuthorization

  RNPhotosFramework.requestAuthorization().then((statusObj) => {
    if(statusObj.isAuthorized) {
      ...start using the library.
    }
  });

Signature: RNPhotosFramework.requestAuthorization() : Promise<{status : string, isAuthorized : boolean}>. This will prompt the user to grant access to the user library at first start. If you do not call this method explicitly before using any of the other functions in this library, the grant-access-dialog will appear for the user automatically at the first function-call into the library. But only one function-call can automatically trigger this dialog, so if another call comes into Photos Framework before the user has granted you access, that function-call will fail. Therefore I urge you to call this method explicitly before you start using the rest of the library to not experience unexpected behaviour. NOTE: You do not have to first check the authorizationStatus before calling this. If the user has granted access before, this will just return authorized-status. NOTE: See available statuses in doc. about: authorizationStatus

Working with Content:

fetchOptions

fetchOptions is a query-object which can be sent both when fetching albums with getAlbums and when fetching assets with getAssets. Below you can see the available options for fetchOptions. You can also read Apple's documentation around PHFetchOptions here. (Many of the args map one-to-one with native data structures.)

Prop Default Type Description
mediaTypes (Only for getAssets) - array<string> Defines what mediaType the asset should be. Array combined with OR-operator. e.g. ['image', 'video'] will return both photos and videos. Converted in Native to PHAssetMediaType. Accepted values: image, video, audio, unknown
mediaSubTypes (Only for getAssets) - array<string> Defines what subtype the asset should be. Array combined with OR-operator. e.g. ['photoPanorama', 'photoHDR'] will return both panorama and HDR-assets. Converted in Native to PHAssetMediaSubtype. Accepted enum-values: none, photoPanorama, photoHDR, photoScreenshot, photoLive, videoStreamed, videoHighFrameRate, videoTimeLapse (mediaTypes and mediaSubTypes are combined with AND-operator)
sourceTypes (Only for getAssets) - array<string> Defines where the asset should come from originally. Array combined with OR-operator. Converted in Native to PHAssetSourceType. Accepted enum-values: none, userLibrary, cloudShared, itunesSynced. (not supported and ignored in iOS 8)
includeHiddenAssets false boolean A Boolean value that determines whether the fetch result includes assets marked as hidden.
includeAllBurstAssets false boolean A Boolean value that determines whether the fetch result includes all assets from burst photo sequences.
fetchLimit 0 number The maximum number of objects to include in the fetch result. Remember to not use this in the wrong way combined with startIndex and endIndex. 0 means unlimited.
sortDescriptors - array<{key : <string>, ascending : <boolean>}> Multiple sortDescriptors which decide how the result should be sorted.

Retrieving Assets (photos/videos/audio):

import RNPhotosFramework from 'react-native-photos-framework';

  RNPhotosFramework.getAssets({
    //Example props below. Many optional.
    // You can call this function multiple times providing startIndex and endIndex as
    // pagination.
    startIndex: 0,
    endIndex: 100,

    fetchOptions : {
      // Media types you wish to display. See table below for possible options. Where
      // is the image located? See table below for possible options.
      sourceTypes: ['userLibrary'],

      sortDescriptors : [
        {
          key: 'creationDate',
          ascending: true,
        }
      ]
    }
  }).then((response) => console.log(response.assets));
Props to getAssets
Prop Default Type Description
fetchOptions - object See above.
startIndex 0 number startIndex-offset for fetching
endIndex 0 number endIndex-offset stop for fetching
includeMetadata false boolean Include a lot of metadata about the asset (See below). You can also choose to get this metaData at a later point by calling asset.getMetadata() (See below)
includeResourcesMetadata false boolean Include metadata about the orginal resources that make up the asset. Like type and original filename. You can also choose to get this metaData at a later point by calling asset.getResourcesMetadata().
prepareForSizeDisplay - Rect(width, height) The size of the image you soon will display after running the query. This is highly optional and only there for optimizations of big lists. Prepares the images for display in Photos by using PHCachingImageManager
prepareScale 2.0 number The scale to prepare the image in.
assetDisplayStartToEnd false boolean Retrieves assets from the beginning of the library when set to true. Using this sorting option preserves the native order of assets as they are viewed in the Photos app.
assetDisplayBottomUp false boolean Used to arrange assets from the bottom to top of screen when scrolling up to view paginated results.

Example of asset response with includeMetadata : true

creationDate : 1466766146
duration : 17.647 (video)
width : 1920
height : 1080
isFavorite : false
isHidden : false
localIdentifier : "3D5E6260-2B63-472E-A38A-3B543E936E8C/L0/001"
location : Object
mediaSubTypes : null
mediaType : "video"
modificationDate : 1466766146
sourceType : "userLibrary"
uri : "photos://3D5E6260-2B63-472E-A38A-3B543E936E8C/L0/001"

(sourceType is not supported in iOS 8)

Retrieving albums and enumerating their assets:

  RNPhotosFramework.getAlbums({
    type: 'album',
    subType: 'any',
    assetCount: 'exact',
    fetchOptions: {
      sortDescriptors : [
        {
          key: 'title',
          ascending: true
        }
      ],
      includeHiddenAssets: false,
      includeAllBurstAssets: false
    },
    //When you say 'trackInsertsAndDeletes or trackChanges' for an albums query result,
    //They will be cached and tracking will start.
    //Call queryResult.stopTracking() to stop this. ex. on componentDidUnmount
    trackInsertsAndDeletes : true,
    trackChanges : false

  }).then((queryResult) => {
    const album = queryResult.albums[0];
    return album.getAssets({
      //The fetch-options from the outer query will apply here, if we get
      startIndex: 0,
      endIndex: 10,
      //When you say 'trackInsertsAndDeletes or trackAssetsChange' for an albums assets,
      //They will be cached and tracking will start.
      //Call album.stopTracking() to stop this. ex. on componentDidUnmount
      trackInsertsAndDeletes : true,
      trackChanges : false
    }).then((response) => {
      console.log(response.assets, 'The assets in the first album');
    });
  });
Props to getAlbums

Get albums allow to query the Photos Framework for asset-albums. Both User-created ones and Smart-albums. Note that Apple creates a lot of dynamic, so called Smart Albums, like : 'Recently added', 'Favourites' etc.

NOTE: There is also another method called getAlbumsMany. This could be considered a low-level-method of the API. It is constructed so that this library can build more accessible methods on top of one joint native-call: like getUserTopAlbums in pure JS. The getAlbumsMany-api can take multiple queries (array) and return an array.

NOTE about Apple Bug for album titles in iOS 10. The album.title property is suppose to be localized to your language out of the box. But this will only work if you have a language translation file included in your project. The native property is called localizedTitle. If you only see english names as titles for smart albums, eg. 'All Photos' even though you run on a different language iPhone, check this question out: http://stackoverflow.com/questions/42579544/ios-phassetcollection-localizedtitle-always-returning-english-name

Prop Default Type Description
fetchOptions - object See above.
assetFetchOptions - object Fetch options used when loading assets from album returned. You can choose to pass these fetchOptions here to affect previewAssets and assetCount in the album according to these options. Note: If you supply fetchOptions when later calling getAssets, those options will override these options.
type album string Defines what type of album/collection you wish to retrieve. Converted in Native to PHAssetCollectionType. Accepted enum-values: album, smartAlbum, moment
subType any string Defines what subType the album/collection you wish to retrieve should have. Converted in Native to PHAssetCollectionSubtype. Accepted enum-values: any, albumRegular, syncedEvent, syncedFaces, syncedAlbum, imported, albumMyPhotoStream, albumCloudShared, smartAlbumGeneric, smartAlbumPanoramas, smartAlbumVideos, smartAlbumFavorites, smartAlbumTimelapses, smartAlbumAllHidden, smartAlbumRecentlyAdded, smartAlbumBursts, smartAlbumSlomoVideos, smartAlbumUserLibrary, smartAlbumSelfPortraits, smartAlbumScreenshots
assetCount estimated string/enum You can choose to get estimated count of the collection or exact-count. Of course these have different performance-impacts. Returns -1 if the estimated count can't be fetched quickly. Remember that your of course fetchOptions affects this count.
previewAssets - number If you set this to a number, say 2, you will get the first two images from the album included in the album-response. This is so you can show a small preview-thumbnail for the album if you like to.
includeMetadata false boolean Include some meta data about the album. You can also choose to get this metaData at a later point by calling album.getMetadata (See below)
noCache false boolean If you set this flag to true. The result won't get cached or tracked for changes.
preCacheAssets false boolean If you set this property to true all assets of all albums your query returned will be cached and change-tracking will start.
trackInsertsAndDeletes false boolean If you set this to true. You will get called back on queryResult.onChange when a Insert or Delete happens. See observing changes below for more details.
trackChanges false boolean If you set this to true. You will get called back on queryResult.onChange when a Change happens to the query-result. See observing changes below for more details.

Working with Albums:

Static methods:

Base methods:

//Fetches albums for params. See above
RNPhotosFramework.getAlbums(params)
//Fetches many queries
//as SingleQueryResult : boolean. if true, will return response as one single response.
RNPhotosFramework.getAlbumsMany([params, params...], asSingleQueryResult);
//Prebuilt query for fetching the most typical albums:
//Camera-Roll, User-albums and user-shared-albums.
RNPhotosFramework.getAlbumsCommon(params)

createAlbum

  RNPhotosFramework.createAlbum('test-album').then((album) => {
    //You can now use the album like any other album:
    return album.getAssets().then((photos) => {});
  });

Signature: RNPhotosFramework.createAlbum(albumTitle) : Promise. There is also another multi-method you can use here: Signature: RNPhotosFramework.createAlbums(albumTitles) : Promise.

NOTE: Alums can have the same name. All resources in Photos are unique on their localIdentifier. You can use the below methods to tackle this:

getAlbumsByTitle

  RNPhotosFramework.getAlbumsByTitle('test-album').then((albums) => {});

Signature: RNPhotosFramework.getAlbumsByTitle(albumTitle) : Promise<array>. Many albums can have the same title. Returns all matching albums. There is also another multi-method you can use here: Signature: RNPhotosFramework.getAlbumsByTitles(albumTitles) : Promise<array>. Signature: RNPhotosFramework.getAlbumsWithParams({albumTitles, ...otherThingLikeFetchOptionsOrType/SubType}) : Promise<array>.

getAlbumByLocalIdentifier and getAlbumByLocalIdentifiers

  RNPhotosFramework.getAlbumByLocalIdentifier(localIdentifier).then((album) => {});

Signature: RNPhotosFramework.getAlbumByLocalIdentifier(localIdentifier) : Promise. All alums carry their localIdentifier on album.localIdentifier.

Album instance-methods:

addAssetToAlbum and addAssetsToAlbum

  album.addAssetToAlbum(asset).then((status) => {});

Signature: album.addAssetToAlbum(asset) : Promise. Add an asset/assets to an album. NOTE: Can only be called with assets that are stored in the library already. If you have a image that you want to save to the library see createAsset.

removeAssetFromAlbum and removeAssetsFromAlbum

  album.removeAssetFromAlbum(asset).then((status) => {});

Signature: album.removeAssetFromAlbum(asset) : Promise. Remove asset from album. NOTE: Can only be called with assets that are stored in the library already. If you have a image that you want to save to the library see createAsset.

updateTitle

  album.updateTitle(newTitle).then((status) => {});

Signature: album.updateTitle(string) : Promise. Change title on an album.

delete

  album.delete().then((status) => {});

Signature: album.delete() : Promise. Delete an album.

getMetadata

  album.getMetadata().then((mutatedAlbumWithMetadata) => {});

Fetch meta data for a specific album. You can also include metadata on all albums in the first getAlbum-call by explicitly setting option includeMetadata: true.

Working with Assets (Images/Photos):

When you retrieve assets from the API you will get back an Asset object. There is nothing special about this object. I've defined it as a class so that it can have some instance-methods.

All Assets. (Video/Image)

These are methods and options that apply to all kinds of assets. (NOTE: Creating new assets has it's own chapter down below).

Asset instance-methods:

setHidden

  asset.setHidden(hiddenBoolean).then((resultOfOperation) => {

  });

Hides or un-hides a specific asset. Will prompt the user when an asset is about to be hidden.

setFavorite

  asset.setFavorite(favoriteBoolean).then((resultOfOperation) => {

  });

Marks/Unmarks the asset as favorite.

setCreationDate

  asset.setCreationDate(jsDate).then((resultOfOperation) => {

  });

Updates the assets creationDate.

setLocation

  asset.setLocation({
    lat : Number //required,
    lng : Number //required,
    altitude : Number //optional, Altitue above sea-level
    heading : Number //optional, cource/heading from 0 (North) to 359.9.
    speed : Number //optional, speed in m/s.
    timeStamp : JSDate //optional, timestamp. Defaults to Now.
  }).then((resultOfOperation) => {

  });

Updates the assets location.

getMetadata

  asset.getMetadata().then((mutatedAssetWithMetadata) => {});

Fetch metadata for a specific asset. You can also include metadata on all assets in the first getAsset-call by explicitly setting option includeMetadata: true.

getResourcesMetadata

  asset.getResourcesMetadata().then((mutatedAssetWithResourcesMetadata) => {
    console.log(mutatedAssetWithResourcesMetadata.resourcesMetadata);
  });

Fetch resource-metadata for a specific asset, this includes original filename, type, uti (uniformTypeIdentifier) and localidentifier. You can also include resource-metadata on all assets in the first getAsset-call by explicitly setting option includeResourcesMetadata: true.

Update Asset metaData

NOTE: When updating metaData, there is two ways of dealing with the result of the update operation. Either your asset-collection updates automatically by using Change-Tracking (See below). This means that the updated asset will be replaced in your collection, but the asset you executed the change on will be unaffected. So calling setHidden(true) will still have isHidden : false, after your update, but it will be replaced with a new asset in your collection via Change-Tracking. (Remember to track changes with trackChanges : true when calling getAssets)

If you choose to NOT use Change-Tracking you can call refreshMetadata on the asset after your update-operation:

  asset.setHidden(hiddenBoolean).then((resultOfOperation) => {
      asset.refreshMetadata().then(() => {
          console.log('The JS-asset should now reflect your changes');
       });
  });

NOTE2: You can update multiple assets at once by calling

RNPhotosFramework.updateAssets({
  [assetOne.localIdentifier] : {
    //Will only update properties provided:
    hidden, favorite, creationDate, location
  },
  [assetTwo.localIdentifier] : {
    hidden, favorite, creationDate, location
  }
  ...etc
});

delete

  asset.delete().then((status) => {
  });

Delete asset.

Images/Photo-Assets

An Image/Photo-asset is fully compatible with RN's <Image source={asset.image}></Image>-tag. This includes all resizeModes. NOTE: Use the property .image on an asset for the <Image>-tag. Otherwise RN will freeze your asset object. And they are, right now at least, mutable.

Image-Asset instance-methods:

getImageMetadata

  asset.getImageMetadata().then((mutatedAssetWithImageMetadata) => {
    console.log(mutatedAssetWithResourcesMetadata.imageMetadata);
  });

Fetch image specific metadata for a specific image-asset, this includes formats and sizes.

withOptions for Images/Photos

withOptions define special rules and options when loading an asset. If you want to know more about how an asset is loaded. Read below on chapter About Asset-Loaders.

deliveryMode

Apple's Photo Framework will download images from iCloud on demand, and will generally be very smart about caching and loading resources quickly. You can however define how an Image should be loaded. We have 3 different options in PHImageRequestOptionsDeliveryMode:

PHImageRequestOptionsDeliveryModeOpportunistic = 0, // client may get several image results when the call is asynchronous or will get one result when the call is synchronous
PHImageRequestOptionsDeliveryModeHighQualityFormat = 1, // client will get one result only and it will be as asked or better than asked (sync requests are automatically processed this way regardless of the specified mode)
PHImageRequestOptionsDeliveryModeFastFormat = 2 // client will get one result only and it may be degraded

This library defaults to loading assets with PHImageRequestOptionsDeliveryModeHighQualityFormat. This can be considered to be the same as RN normally loads images. It will simply download the image in the size of your (iCloud-images are stored in multiple sizes, and Photos Framework will download the one closest to your target size) and display it.

But you can choose to use the other two deliveryMode's to. you do this by calling:

  const assetWithNewDeliveryMode = asset.withOptions({
      //one of opportunistic|highQuality|fast
      deliveryMode : 'opportunistic'
  });

If you choose to use opportunistic here you will see a low-res-version of the image displayed while the highQuality version of the resource is downloaded. NOTE: This library will call correct lifecycle callback's on your image-tag when this is used: the <Image onPartialLoad={//Low-res-callback} onLoad={//High-res-callback} onProgress={//downloadCallback}>

Video-Assets

Video assets can be played by using a special branch of the great library react-native-video. This branch adds the capability of loading Videos from Photos-framework and works as expected, but is otherwise the same as the orignal project. So you can play local or remote files as well and if you already use react-native-video for other content, you should just be able to replace the version.

NOTE: Let me and the react-native-video-guys know if you want this to go into thir master.

Install react-native-video:

npm install git://github.com/olofd/react-native-video.git#react-native-photos-framework --save && react-native link

or add : "react-native-video": "git://github.com/olofd/react-native-video.git#react-native-photos-framework" to your package.json and run npm install.

Displaying video

      <Video source={this.props.asset.video} //Use the asset.video-property.
        ref={(ref) => {
          this.player = ref
        }}
        resizeMode='cover'
        muted={false}
        paused={this.state.videoPaused}  
        style={styles.thumbVideo}/>

For more info on supported properties see: react-native-video

withOptions for Video-Asset.

withOptions define special rules and options when loading an asset. (Implemented in react-native-video)

Prop Default Type Description
deliveryMode 'automatic' string/enum Maps to native PHVideoRequestOptionsDeliveryMode (Apple's docs). Possible values : automatic, mediumQuality, highQuality, fast
version 'current' string/enum Maps to native PHVideoRequestOptionsVersion (Apple's docs). Possible values : current, original

withOptions example usage for video:

  const assetWithNewDeliveryMode = asset.withOptions({
      deliveryMode : 'mediumQuality'
  });

About Asset-Loaders:

NOTE about RN's concept of Image loaders:
RN has a plugin-like system for displaying Images/Photos.
This means that any library (like this library) can define it's own
ImageLoader. When RN later gets a request to display a <Image> it will query
all ImageLoaders loaded in the system and ask which loader can load a specific resource.
If the resource starts with `https://` for instance, RN's own network-image-loader will take care of loading that resource. While if the scheme of the resource is `asset-library://` another ImageLoader will load that Image.

This library defines it's own ImageLoader which can load images from iCloud. (RN actually already have a ImageLoader that can load iCloud images, but we define our own/extend their original loader so we can have some extra functionality on our loader. (See deliveryMode below)).
A ´uri´ that our loader can load is defined in scheme: `photos://` and localIdentifier eg: `9509A678-2A07-405F-B3C6-49FD806915CC/L0/001`
URI-example: photos://9509A678-2A07-405F-B3C6-49FD806915CC/L0/001

Creating Assets:

You can use this library to save images and videos to the users iCloud library. NOTE: Creating image-assets uses RN's ImageLoader-system behind the scenes and should therefore be able to accept/save any image/photo that you can display in RN.

Static methods:

createImageAsset

  RCTCameraRollRNPhotosFrameworkManager.createImageAsset(imageWithUriProp);

Signature: album.createImageAsset(params) : Promise. Create a image-asset

createVideoAsset

  RCTCameraRollRNPhotosFrameworkManager.createVideoAsset(videoWithUriProp);

Signature: album.createVideoAsset(params) : Promise. Create a image-asset

createAssets

  RCTCameraRollRNPhotosFrameworkManager.createAssets({
    images : [{ uri : 'https://some-uri-local-or-remote.jpg' }],
    videos : [{ uri : 'https://some-uri-local-or-remote.jpg' }]
    album : album //(OPTIONAL) some album that you want to add the asset to when it's been added to the library.
    includeMetadata : true //The result of this function call will return new assets. should this have metadata on them? See docs of getAssets for more info.
  });

Signature: album.createAssets(params) : Promise<array>. Base function for creating assets. Will return the successfully created new assets. If the function returns less Assets then you sent as input, the ones not returned did fail.

Sending assets to server using AJAX

This library implements the interface RCTURLRequestHandler. This means it supports sending assets as files with AJAX to your server of choice out of the box. You can send both Images and Videos with your ajax-library of choice. The simplest way of doing this is by doing it the good old way:

//Create a JS object with these props.
//The only thing required is the asset.uri and a name of the file.
const photo = {
    uri: asset.uri,
    type: 'image/jpeg',
    name: 'photo.jpg',
};

const body = new FormData();
body.append('photo', photo);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://your-server-url/upload');
xhr.send(body);

Ajax-Helper.

This library does however include a helper to abstract over a simple upload. This helper does promisify and help you to simply sending assets over the wire. It also loads the original filename of the assets and their mimeType before sending. You can supply your own modifyAssetData callback to change the name if you want to before sending. This helper operates over multiple Assets, so you always give it an array of Assets (Can contain only one item). It will upload the assets async in parallell and give you progress of the overall operation as well (For progressbars etc.).

This helper sits outside of the rest of the library to not bloat for people not wanting it, and needs to be required/imported seperatly. (See example below).

import {postAssets} from 'react-native-photos-framework/src/ajax-helper';
const ajaxPromise = postAssets(assets, {
     url: 'http://localhost:3000/upload',
     headers : {},
     onProgress: (progressPercentage, details) => {
         console.log('On Progress called', progressPercentage);
     },
     onComplete : (asset, status, responseText, xhr) => {
         console.log('Asset upload completed successfully');
     },
     onError : (asset, status, responseText, xhr) => {
         console.log('Asset upload failed');
     },
     onFinnished : (completedItems) => {
         console.log('Operation complete');
     },
     modifyAssetData : (postableAsset, asset) => {
         postableAsset.name = `${postableAsset.name}-special-name-maybe-guid.jpg`;
         return postableAsset;
     }
 }).then((result) => {
     console.log('Operation complete, promise resolved', result);
     return result;
 });

Change-Tracking/Observing library changes

You can register listeners for library-change-detection on different levels of the api.

Library-level

You can detect globally if the library changed by:

RNPhotosFramework.onLibraryChange(() => {
  console.log('Library Change');
});

No details provided

AlbumQueryResult-level

You can register a listener that receives updates when any of the albums that result contains changes (Not if their assets change, only the Albums get those messages, see below). You currently receive the following events: AlbumTitleChanged (More to come).

const unsubscribeFunc = albumsFetchResult.onChange((changeDetails, update) => {
    if(changeDetails.hasIncrementalChanges) {
      update((updatedFetchResult) => {
         this.setState({albumsFetchResult: updatedFetchResult});
      });
    } else {
      //Do full reload here..
    }
});

NOTE: If a change occures that affects one of the AlbumQueryResults albums that change will also be passed along to the album.

Album/Assets-level

To receive change-updates on an album's assets you need to supply at least one of these two arguments when calling getAssets on that album: trackInsertsAndDeletes : true or trackChanges : true (See Retrieving albums and enumerating their assets above)

On an album object you can do:

const unsubscribeFunc = album.onChange((changeDetails, update) => {
  if(changeDetails.hasIncrementalChanges) {
    //Important! Assets must be supplied in original fetch-order.
    update(this.state.assets, (updatedAssetArray) => {
      this.setState({
        assets : updatedAssetArray
      });
    }, 
    //If RNPF needs to retrive more assets to complete the change,
    //eg. a move happened that moved a previous out of array-index asset into your corrently loaded assets.
    //Here you can apply a param obj for options on how to load those assets. eg. ´includeMetadata : true´.
    {
      includeMetadata : true
    });
  }else {
    //Do full reload here..
  }
});

The update-function will apply the changes to your collection.

Call the unsubscribeFunc in order to unsubscribe from the onChange event.

componentDidUnmount: function () {
  unsubscribeFunc();
  album.stopTracking();
}

Support on Beerpay

Hey dude! Help me out for a couple of 🍻!

Beerpay Beerpay

react-native-photos-framework's People

Contributors

adbl avatar gre avatar justinsherwood avatar olofd avatar ralfnieuwenhuizen avatar rossmartin avatar samueljmurray avatar sjmueller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-photos-framework's Issues

api acess

This is not a GUI-component, it's an API

Any plans to make it available as an API?

No meta data returned when calling getAssets

On a fresh project:

RNPhotosFramework.getAssets({
        includeMetaData: true,
        startIndex: 0,
        endIndex: 100,
        fetchOptions : {
          mediaTypes: ['image'],
          sourceTypes: ['userLibrary'],
          sortDescriptors : [
            {
              key: 'creationDate',
              ascending: true,
            }
          ],
        }
      }).then((data) => {
        console.log('FETCHED DATA:',data);
      }, (e) => {
        console.log('ERROR:',e);
      })

Array of ImageAssets are returned, but no creationDate or modificationDate.
NSLog of params in getAssets on iOS native code(RNPFManager.m):

{
    assetDisplayStartToEnd = 1;
    endIndex = 100;
    fetchOptions =     {
        mediaTypes =         (
            image
        );
        sortDescriptors =         (
                        {
                ascending = 1;
                key = creationDate;
            }
        );
        sourceTypes =         (
            userLibrary
        );
    };
    includeMetaData = 1;
    startIndex = 0;
}

..but all the following RCTConvert calls seems to resolve to null, including this:

BOOL includeMetadata = [RCTConvert BOOL:params[@"includeMetadata"]];

My Objective C skills are limited so didn't manage to solve this. Hopefully my javascript call above is correct.
Tested on React Native 0.41.0 (and 0.43.1) using react-native-photos-framework 1.0.1

Asset delete issue - unreocgnized selector sent to instance

If you have an ImageAsset and call the delete function on it you'll receive unreocgnized selector sent to instance.

This is due to the problem with following code -

src/asset.js -

delete() {
  //return NativeApi.deleteAssets([this.localIdentifier]); // WRONG
  return NativeApi.deleteAssets([this]); // RIGHT
}

src/index.js

deleteAssets(assets) {
  return RNPFManager.deleteAssets(assets.map(asset => asset.localIdentifier));
}

If you call RNPhotosFramework.deleteAssets manually with an array of ImageAssets it will work but not if you call the delete function on an individual ImageAsset. I modified src/asset.js to the above and both calls work correctly. I can submit a PR if you would like.

Doesn't show hidden photos?

I'm seeing hidden photos showing up as blank instead of rendering. Is this some sort of permissions issue?

NSSortDescriptor displays unexpected assets when sortDescriptors are sorted by creationDate or modificationDate

I'm trying to list assets in my project in the same way the native photo app displays assets. (Most recent assets first including assets that have been modified)

When I sort assets by creationDate, edited photos do not appear at the top of the list. For example, a photo edited and exported using Adobe Lightroom for iOS appears next to the original photo instead at the top of the list since the createdDate remains the same. I would expect this newly created edited photo to be displayed at the top of my list, but it is still listed next to the original photo since the creationDate property did not change.

I've tried sorting by modificationDate, but this also leaves me with unexpected results since activities like favoriting or un-favoriting a photo changes the modificationDate and moves that asset to the top of the list, which doesn't happen in the native Photos app and is an unexpected behavior for sorting photos.

Just curious to know if you were aware of this issue and if you can think of a fix. This stackoverflow question discusses this issue and provides a possible solution by removing the sortDescriptors to achieve the same sorting as the native Photos app. I tried implementing this solution, which sort of worked, but the assets were sorted oldest to newest instead of my desired functionality of newest to oldest. Can you think of a way to implement this functinoality?

Cheers!

http://stackoverflow.com/questions/31696701/sorting-photos-exactly-like-native-photoapp-using-photokit

Feature Request: requestImageForAsset

Add the requestImageForAsset function of the UIImage component to allow your plugin to access the jpg version of heic images. HEIC is really making developers cry.

Unable to save video asset into album

I'm trying to save a video into a specific album, I use similar structure for the images and that works but the videos do not get saved into a album. This is on ios. I get the uri and the album but

if(Platform.OS === 'ios') {
        this.camera
          .capture({ mode: Camera.constants.CaptureMode.video })
          .then(
            (data) => {
              const album = this.state.albumUsed;
              return RNPhotosFramework.createAssets({
                album: album,
                videos: [{
                  uri: data.path
                }],
              })
            .then(() => console.log('Video taken and saved in a album'))})
          .catch((err) => console.log('Video taken error log:' + err));
        this.setState({
          isRecording: true,
        });

In the createasset code below

createAssets(params, onProgress) {
   const images = params.images;
   const videos = params.videos !== undefined ? params.videos.map(videoPropsResolver) : params.videos;
   let media = [];
   if (images && images.length) {
     media = media.concat(images.map(image => ({
       type: 'image',
       source: image
     })));
   }
   if (videos && videos.length) {
     media = media.concat(videos.map(video => ({
       type: 'video',
       source: video
     })));
   }

   const {
     args,
     unsubscribe
   } = this.withUniqueEventListener('onCreateAssetsProgress', {
       media: media,
       albumLocalIdentifier: params.album ?
         params.album.localIdentifier : undefined,
       includeMetadata: params.includeMetadata
     }, onProgress);
   return RNPFManager
     .createAssets(args)
     .then((result) => {
       unsubscribe && this.nativeEventEmitter.removeListener(unsubscribe);
       return result
         .assets
         .map(this.createJsAsset);
     });
 }

I get the media as

isAsset : true
isNetwork:false
type:undefined
uri:"assets-library://asset/asset.mov?id=A226D7D9-07FD-4583-B651-DA2EFBD585C4&ext=mov"

and videos as

isAsset:true
isNetwork:false
type:undefined
uri:"assets-library://asset/asset.mov?id=A226D7D9-07FD-4583-B651-DA2EFBD585C4&ext=mov"

then when runnnig result become com up with assets as empty

result
:
assets:Array(0)
length:0

Am I not using this correctly or should I rather be using RCTCameraRollRNPhotosFrameworkManager.createVideoAsset(videoWithUriProp); and then album.addAssetToAlbum(asset).then((status) => {}); ?

Sporadic Crash

Issue Description

This happens to 0.35% of users in my application. I obtained these statistics using AppSee.

Steps to Reproduce / Code Snippets / Screenshots

Error information:

iPhone 6s
iOS 11.3  Wi-Fi

Terminating app due to an uncaught exception 'RCTFatalException: Exception '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (key: title)' was thrown while invoking getAlbumsMany on target RNPFManager with params ( ( { assetCount = exact; fetchOptions = { includeAllBurstAssets = 0; includeHiddenAssets = 0; sortDescriptors = ( { ascending = 1; key = title; } ); }; previewAssets = 1; subType = any; trackChanges = 0; trackInsertsAndDeletes = 0; type = smartAlbum; }, { assetCount = exact; fetchOptions = { includeAllBurstAssets = 0; includeHiddenAssets = 0; sortDescriptors = ( { ascending = 1; key = title; } ); }; previewAssets = 1; subType = any; trackChanges = 0; trackInsertsAndDeletes = 0; type = album; } ), 8570, 8571 ) callstack: ( 0 CoreFoundation 0x0000000184d7eda4 <redacted> + 252 1 libobjc.A.dylib 0x0000000183f385ec objc_exception_throw + 56 2 CoreFoundation 0x0000000184d17750 _CFArgv + 0 3 CoreFoundation 0x0000000184c4cc6c <redacted> + 948 4 Finery 0x0000000104d89954 Finery + 563540 5 Finery 0x0000000104d890f0 Finery + 561392 6 Finery 0x0000000104d88c80 Finery + 560256 7 Finery 0x0000000104d887d4 Finery + 559060 8 Finery 0x0000000104d97a84 Finery + 621188 9 CoreFoundation 0x0000000184d86580 <redacted> + 144 10 CoreFoundation 0x0000000184c65748 <redacted> + 284 11 CoreFoundation 0x0000000184c6a56c <redacted> + 60 12 Finery 0x0000000104f60614 _ZN14RNWebGLContext27jsTypedArrayFreeDeallocatorEPvS0_ + 1601380 13 Finery 0x0000000104fa1450 RCTFBQuickPerformanceLoggerConfigureHooks + 109428 14 Finery 0x0000000104fa11b0 RCTFBQuickPerformanceLoggerConfigureHooks + 108756 15 libdispatch.dylib 0x0000000184670b24 <redacted> + 24 16 libdispatch.dylib 0x0000000184670ae4 <redacted> + 16 17 libdispatch.dylib 0x000000018467aa38 <redacted> + 608 18 libdispatch.dylib 0x000000018467b380 <redacted> + 336 19 libdispatch.dylib 0x000000018467bd4c <redacted> + 340 20 libdispatch.dylib 0x000000018468411c <redacted> + 668 21 libsystem_pthread.dylib 0x00000001849a3e70 _pthread_wqthread + 860 22 libsystem_pthread.dylib 0x00000001849a3b08 start_wqthread + 4 )', reason: 'Exception '*** -[__NSDictionaryM setObject:forKey:]: object cannot be nil (...'

captura de pantalla 2018-08-23 a la s 10 53 12 am



Environment

Base in this issue i'm pointing directly to this commit:
"react-native-photos-framework": "https://github.com/olofd/react-native-photos-framework.git#adaa91d8bd13e93cb18c5884d9fde27228a44ebb",

Environment:
  OS: macOS Sierra 10.12.6
  Node: 8.9.1
  Yarn: 1.3.2
  npm: 5.5.1
  Watchman: 4.7.0
  Xcode: Xcode 9.2 Build version 9C40b
  Android Studio: 3.1 AI-173.4819257

Packages: (wanted => installed)
  react: 16.0.0 => 16.0.0
  react-native: 0.51.0 => 0.51.0

How to get MimeType?

I tried using this library today however the asset does not return the MimeType. And neither is it in the extension. I need the mimeType to upload it without using the in-built ajaxHelper.

Accessing Screenshots album

I am trying to access system 'Screenshot' album (ios 10.3.3.) with the the RNPhotosFramework.getAlbumsByTitle(). It seams I can only acess albums under 'My Albums' heading. How can I acess 'Screenshots'?

CreateAssets(): Got memory pressure notification (critical)

Hi,

I try to upload 400 Pictures to the camera roll and after 5 seconds i got the following errors and the app crashed:

RNPhotosFramework.createAssets({
                images : images,
                album : album, 
                includeMetadata : false
            }).then((res) => {
                console.log('done');
            }).catch((err) => {
                console.log(error);
            });
[812:43385] Error: Timeout waiting for response from assetsd in -[PHChangeRequestHelper _generateUUIDIfNecessary:]
[812:43385] [PhotoKit] Timeout waiting for response from assetsd in -[PHChangeRequestHelper _generateUUIDIfNecessary:] (retries 3)
[812:43001] Got memory pressure notification (critical)
Message from debugger: Terminated due to memory issue

The pics are very big and the first 5 pics are uploaded to the camera roll.

Is there anything i can do to avoid that or improve the memory?

Many thanks!

Android?

Does this work for android as well?

Consider allowsCachingHighQualityImages=NO

https://developer.apple.com/reference/photos/phcachingimagemanager/1616959-allowscachinghighqualityimages?language=objc

What is the point in using the cache when displaying single images / few images?

I think it should it be set to NO.

There could be a point of using the cache and having allowsCachingHighQualityImages=YES, for a some view where images are prepared and cached beforehand.

Maybe having NO as default and an method to change it (globally, since it is shared)?

Assets in <Image> sometimes render a placeholder when the dimensions are "wrong"

Hi, I've noticed that sometimes, the size of my images affects if they're rendered at all. For example, giving an image {width: 100, height: 100} works fine, but {width: 75, height: 100} does not work. It renders a JPG placeholder instead. How can I go about fixing this? I noticed the prepareForSizeDisplay param but I am not sure if it will help or how to format it.

Thanks!

Deleting an asset from a smart album

Thank you for this awesome library. I am running into an issue deleting an asset from a smart album. I am trying to delete an image from the Screenshots album to be exact. I am getting back this error as a Promise rejection when calling:

album.removeAsset(myAsset)

I am getting back this error:

Error: The operation couldn’t be completed. (Cocoa error -1.)
    at createErrorFromErrorData (NativeModules.js:116)
    at NativeModules.js:79
    at MessageQueue.__invokeCallback (MessageQueue.js:290)
    at MessageQueue.js:127
    at guard (MessageQueue.js:46)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (MessageQueue.js:126)
    at debuggerWorker.js:71

I googled Cocoa error -1, but I am not sure I found anything helpful.

Any help would be appreciated. Thanks again!

ndefined symbols for architecture x86_64:

after installing and linking I get this error
Undefined symbols for architecture x86_64:
"OBJC_CLASS$_RCTSRWebSocket", referenced from:
objc-class-ref in libReact.a(RCTInspectorPackagerConnection.o)
"OBJC_CLASS$_RCTReconnectingWebSocket", referenced from:
objc-class-ref in libReact.a(RCTPackagerConnection.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Support for ImageLoader rendering different mime types

Hi there! If I save a .gif to iCloud, getAssets indeed returns a valid photos:// uri and a gif mimeType, which is great... but passing this uri into the Image component doesn't actually render a moving gif. I have confirmed that a network-based gif does render correctly. Is there something that needs to be modified in the image loader? Is there a workaround? Thanks!!

Fetch random photo(s)

Hi! Is there any (efficient) way of fetching X number of randomly chosen photos using this API?

prepareForSizeDisplay doesn't work (docs are incorrect)

The docs state that prepareForSizeDisplay takes Rect(width, height) but that's not a thing in JavaScript.

I tried supplying an Object instead but that also doesn't work.

Can the docs be updated with the correct information, because currently prepareForSizeDisplay doesn't seem to be usable.

Can't get this to work with <Video />

Hey! I'd love to use this for picking and showing videos, but I'm currently stuck.

I can use the API to get a list of video assets, but trying to use react-native-video (master or your fork) crashes my app.

Any help or tips would be amazing!! :)

P.S. I tried to get the example app in this repo running, but failed to do so

package.json

	"dependencies": {
		"react": "~15.4.0",
		"react-native": "0.41.2",
		"react-native-photos-framework": "^0.1.1",
		"react-native-video": "git://github.com/olofd/react-native-video.git#react-native-photos-framework",
		...
	}

App

import RNPhotosFramework from 'react-native-photos-framework'
import Video from 'react-native-video'

...

  async componentDidMount() {
    const status = await RNPhotosFramework.requestAuthorization()

    if (status.isAuthorized) {
      const {assets} = await RNPhotosFramework.getAssets({
        startIndex: 0,
        endIndex: 1,
        includeMetadata: true,
        fetchOptions : {
          mediaTypes: ['video'],
          sourceTypes: ['userLibrary', 'cloudShared', 'itunesSynced'],
        }
      })
      this.setState({videos: assets})
    }
  }

...
  render() {
...

            {this.state.videos.map((video, i) => {
              console.log(video.video) // THIS IS UNDEFINED
              // return <Image key={i} source={{uri: video.uri}} style={{width : 100, height : 100}}></Image> // THIS WORKS
              return <Video  //THIS CRASHES
                source={{uri: video.uri}}
                key={i}
                resizeMode='cover'
                muted={false}
              />
            })}

Here's the crash:

screen shot 2017-02-23 at 10 30 46 pm

build failed

⚠️ ld: object file (/Users/Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(PHAssetsService.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users/Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(RNPFFileDownloader.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users//Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(PHFetchOptionsService.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users//Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(RNPFImageLoader.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users//Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(PHChangeObserver.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users//Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(RNPFUrlRequestHandler.o)) was built for newer iOS version (10.0) than being linked (9.0)
⚠️ ld: object file (/Users//Documents/reactnative/gl/ios/build/glwork/Build/Intermediates/ArchiveIntermediates/gl/BuildProductsPath/Release-iphoneos/libRNPhotosFramework.a(RCTConvert+RNPhotosFramework.o)) was built for newer iOS version (10.0) than being linked (9.0)

❌ ld: symbol(s) not found for architecture arm64

❌ clang: error: linker command failed with exit code 1 (use -v to see invocation)

[21:05:27]: Exit status: 65

PHAssetCollectionSubtypeSmartAlbumLivePhotos Fail to Compile Issue

install the latest version 1.0.3
RN 0.43.3
xcode 8.2.1 8C1002

I have got this error

/.../node_modules/react-native-photos-framework/ios/RNPhotosFramework/RCTConvert+RNPhotosFramework.m:103:77: Use of undeclared identifier 'PHAssetCollectionSubtypeSmartAlbumLivePhotos'; did you mean 'PHAssetCollectionSubtypeSmartAlbumVideos'?

/.../node_modules/react-native-photos-framework/ios/RNPhotosFramework/RCTConvert+RNPhotosFramework.m:103:77: Use of undeclared identifier 'PHAssetCollectionSubtypeSmartAlbumLivePhotos'; did you mean 'PHAssetCollectionSubtypeSmartAlbumVideos'?

Error: Cannot find module 'plist'

When trying to install I'm getting this error during postinstall

Xcode v10.0
react-native v0.57.1

$ npm i --save react-native-photos-framework

> [email protected] postinstall /Users/tommy/Git/noisolation/FamilyFrame/node_modules/react-native-photos-framework
> node install.js

module.js:549
    throw err;
    ^

Error: Cannot find module 'plist'
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/tommy/Git/noisolation/FamilyFrame/node_modules/react-native-photos-framework/local-cli/link/ios/copyAssets.js:5:21)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] postinstall: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

Unable to install due to incorrect xcodeproj being picked up

My install kept failing with this error on [email protected]:

/Users/chris.rowley/rn-project/node_modules/react-native-photos-framework/install.js:23
    if (!plist.NSPhotoLibraryUsageDescription) {
              ^

TypeError: Cannot read property 'NSPhotoLibraryUsageDescription' of null
    at Object.<anonymous> (/Users/chris.rowley/rn-project/node_modules/react-native-photos-framework/install.js:23:15)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:427:7)
    at startup (bootstrap_node.js:151:9)
    at bootstrap_node.js:542:3

I've done some digging, and the issue seems to be that findProject in react-native-photos-framework/local-cli/core/config/ios/findProject.js takes the first *.pbxproj file it finds... In my case, that was

ios/build/Build/Products/Debug-iphonesimulator/rn-project/LinkingIOS/RCTLinking.xcodeproj

which has no INFOPLIST_FILE field... Removing the ios/build dir fixes the issue, but it'd be great if findProject could be more specific in the file it picks up?

Can’t run android after installing lib

After installing lib, I faced with the problem after runing android app, in result I have this error Could not find react-native-photos-framework’s native module. It seems it’s not linked correctly in your xcode-project.. How to resolve this issue? I want to use this lib only for ios, but for android - default CameraRoll from RN. Thanks for any help.
p.s. IOS works fine

RCTImageResizer.h problems

I have been using "react-native-image-resizer" in my project and after I added "react-native-photos-framwork' it won't link because of duplicated symbols.

It looks like you have included most of the ImageResizer code in your project. I have tried to comment out the resizer code and import like this #import <RCTImageResizer/RCTImageResizer.h>
but it seems there is a mismatch in the APIs.

What is the the bes way to move forward? What do you recommend?

Build fails using RN 0.45.1

I had an existing RN project using 0.43.3 and RNPhotosFramework worked fine. I updated to the latest (0.45.1) and now I cannot build my project unless I comment out line 3 on PHChangeObserver.m shown below.

I also created a new 0.45.1 project and it builds fine up until I add react-native-photos-framework and link it. Here are some screenshots of the issues -

screen shot 2017-06-19 at 6 51 18 pm
image

How to get video associated with live photo?

Hi

I am trying to get access to the video file that is associated with a live photo. How do I go about this? I've been trying to get a uri for the video file with no success.

Thanks in advance

Unable to resolve module `react/lib/ReactPropTypes`

I'm using RN 0.45.1 and the import ReactPropTypes from 'react/lib/ReactPropTypes' in src/index.js fails. It results in "Module does not exist in the module map..."

The PropTypes module is not used on src/index.js so you can safely comment it out. If PropTypes are needed you can use import ReactPropTypes from 'prop-types'.

Get full resolution image?

Thanks for a great library!

In our use case we first present photo thumbnails in a collection (user can keep scrolling to see all theirs photos), user picks one to preview and then send it. We want to make sure the max resolution image gets sent at that point.

After checking around in this library/RN and apple docs, I think I have understood the following:

  • The size of the Image will determine the targetSize to get from photos. In our case, since the thumbnails are small they get downloaded quickly while scrolling down, even without using the caching option. When going into preview a larger version version of the image gets downloaded, nice!
  • The high quality deliveryMode (which is default), will download a smaller than full resolution image, depending on the Image view component size.
  • Max resolution is downloaded with resizeMode=PHImageRequestOptionsResizeModeNone and targetSize= PHImageManagerMaximumSizewhich RCTImageLoaderRNPhotosFramework sets if size is CGSizeZero, but that is only the case for Image using capInsets (?? according to reloadImage in RCTImageView.m)

Could we add an option to withOptions to support this?

Seems to be missing the function from the readme getAlbumByLocalIdentifier

I got an error trying to use this function from the readme but it seems to not exist. I searched the Repo and was able to find the get by title but not getAlbumByLocalIdentifier. On another note this Repo looks wonderful as the native CameraRoll is a no go. I was building a native solution but after seeing this I am willing to try to help with this. Looks great. Getting ready to test some more.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.