https://github.com/rescript-react-native/cameraroll
ReScript bindings for @react-native-community/cameraroll
https://github.com/rescript-react-native/cameraroll
camera-roll photo-gallery react react-native rescript rescript-react rescript-react-native saving-photos
Last synced: 8 months ago
JSON representation
ReScript bindings for @react-native-community/cameraroll
- Host: GitHub
- URL: https://github.com/rescript-react-native/cameraroll
- Owner: rescript-react-native
- License: mit
- Created: 2020-03-30T19:01:12.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2023-02-09T03:18:01.000Z (almost 3 years ago)
- Last Synced: 2025-04-13T12:08:56.010Z (8 months ago)
- Topics: camera-roll, photo-gallery, react, react-native, rescript, rescript-react, rescript-react-native, saving-photos
- Language: ReScript
- Homepage:
- Size: 1.02 MB
- Stars: 2
- Watchers: 3
- Forks: 1
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# `@rescript-react-native/cameraroll`
[](https://github.com/rescript-react-native/cameraroll/actions)
[](https://www.npmjs.com/@rescript-react-native/cameraroll)
[](https://forum.rescript-lang.org/)
[ReScript](https://rescript-lang.org) bindings for
[`@react-native-community/cameraroll`](https://github.com/react-native-cameraroll/react-native-cameraroll).
Exposed as `ReactNativeCameraRoll` module.
`@rescript-react-native/cameraroll` X.y.\* means it's compatible with
`@react-native-community/cameraroll` X.y.\*
## Installation
When
[`@react-native-community/cameraroll`](https://github.com/react-native-cameraroll/react-native-cameraroll)
is properly installed & configured by following their installation instructions,
you can install the bindings:
```console
npm install @rescript-react-native/cameraroll
# or
yarn add @rescript-react-native/cameraroll
```
`@rescript-react-native/cameraroll` should be added to `bs-dependencies` in your
`bsconfig.json`:
```diff
{
//...
"bs-dependencies": [
"@rescript/react",
"rescript-react-native",
// ...
+ "@rescript-react-native/cameraroll"
],
//...
}
```
## Methods
### `save`
Allows saving photos and videos to the Camera Roll or Photo Gallery, similar to
[`saveToCameraRoll`](#savetocameraroll).
The function will return the URI for the saved file as a string wrapped in a
Promise.
```rescript
save: string => Js.Promise.t(string)
```
### `saveWithOptions`
Allows saving photos and videos to the Camera Roll or Photo Gallery, similar to
[`saveToCameraRoll`](#savetocameraroll), however, a particular album may be
specified in a `saveOptions` object.
The function will return the URI for the saved file as a string wrapped in a
Promise.
```rescript
saveWithOptions: (string, saveOptions) => Js.Promise.t(string)
```
### `saveToCameraRoll`
Allows saving photos and videos to the Camera Roll or Photo Gallery. File to be
saved is specified as a tag (of type `string`) which can be
- on Android, a local image or video URI, such as "file:///sdcard/img.png"
- on iOS, a local video URI or any image URI (local, remote asset-library, or
base64 data URIs)
Media type (photo or video) will be automatically inferred; any file will be
inferred to be a photo, unless the file extension is `mov` or `mp4`, then it
will be inferred to be a video.
The function will return the URI for the saved file as a string wrapped in a
Promise.
```rescript
saveToCameraRoll: string => Js.Promise.t(string)
```
### `saveToCameraRollWithType`
Allows saving photos and videos to the Camera Roll, where the tag will be
specified as above, overriding the automatically determined type by specifying
one of the polymorphic variants `` `photo `` or `` `video ``.
The function will return the URI for the saved file as a string wrapped in a
Promise.
```rescript
saveToCameraRollWithType: (string, [ | #photo | #video]) => Js.Promise.t(string)
```
### `deletePhotos`
To request deletion of photos (as `array(string)`) from the Camera Roll. Returns
`bool` wrapped in a Promise. The Promise will be rejected if deletion does not
succeed; on _Android_ that would imply a system error whereas on _iOS_ the user
may have cancelled the request to delete.
On _Android_, the uri must be a local image or video URI, such as
"file:///sdcard/img.png".
On _iOS_, the uri can be any image URI (including local, remote asset-library
and base64 data URIs) or a local video file URI. The user will be presented with
a dialog box that showing the asset(s) and asked for confirmation. This cannot
be bypassed as per Apple Developer guidelines.
```rescript
deletePhotos: array(string) => Js.Promise.t(bool)
```
### `getAlbums`
Returns a list of albums wrapped in a Promise.
```rescript
getAlbums: unit => Js.Promise.t(array(album))
```
### `getAlbumsWithParams`
Returns a list of albums of type specified in a `getAlbumsParams` object,
wrapped in a Promise.
```rescript
getAlbums: getAlbumsParams => Js.Promise.t(array(album))
```
### `getPhotos`
Allows searching for photos or videos matching given parameters.
Takes as argument `getPhotosParams` and returns a `photoIdentifiersPage` object
wrapped in a Promise. `edges` key of the `photoIdentifiersPage` object would be
of type `array(photoIdentifier)`, where each `photoIdentifier` object would
contain details of each photo or video matching parameters provided in the
`getPhotosParam` object.
```rescript
getPhotos: getPhotosParams => Js.Promise.t(photoIdentifiersPage)
```
## Types
### `album`
```rescript
type album = {
title: string,
count: int
};
```
### `getAlbumsParams`;
can be constructed with the constructor of the same name
```rescript
getAlbumsParams:
(
~assetType: [
| #All
| #Photos
| #Videos
]
) =>
getAlbumsParams
```
### `getPhotosParams`
can be constructed with the constructor of the same name
- `first` takes an integer which specifies the number of files for which details
will be returned. Files will match in reverse order (i.e. most recent first)
- `after` takes a string which should be obtained from `photoIdentifiersPage`
returned in a previous `getPhotos` call, under the `end_cursor` key contained
in turn under the `page_info` key.
```rescript
getPhotosParams:
(
~first: int,
~after: string=?,
~groupTypes: [
| #Album
| #All
| #Event
| #Faces
| #Library
| #PhotoStream
| #SavedPhotos
]
=?,
~groupName: string=?,
~assetType: [ | #All | #Videos | #Photos]=?,
~mimeTypes: array(string)=?,
~fromTime: float=?,
~toTime: float=?,
~include_: array(string)=?,
unit
) => getPhotosParams
```
### `image`
```rescript
type image = {
filename: Js.Nullable.t(string),
uri: string,
height: Js.Nullable.t(float),
width: Js.Nullable.t(float),
fileSize: Js.Nullable.t(float),
playableDuration: Js.Nullable.t(float),
}
```
### `location`
```rescript
type location = {
latitude: Js.Nullable.t(float),
longitude: Js.Nullable.t(float),
altitude: Js.Nullable.t(float),
heading: Js.Nullable.t(float),
speed: Js.Nullable.t(float),
};
```
### `node`
```rescript
type node = {
\"type": string,
\"group_name": string,
image,
timestamp: float,
location: Js.Nullable.t(location),
}
```
### `pageInfo`
```rescript
type pageInfo = {
\"has_next_page": bool,
\"start_cursor": Js.Nullable.t(string),
\"end_curson": Js.Nullable.t(string),
};
```
### `photoIdentifiersPage`
```rescript
type photoIdentifiersPage = {
edges: array(photoIdentifier),
\"page_info",
}
```
### `photoIdentifier`
```rescript
type photoIdentifier = {node}
```
### `saveOptions`
can be constructed with the constructor of the same name
```rescript
saveOptions:
(
~_type: [
| #auto
| #photo
| #video
],
~album: string
) =>
saveOptions
```
## Example
```rescript
open ReactNative;
open ReactNativeCameraRoll;
let windowWidth = Dimensions.get(`window)##width;
let windowHeight = Dimensions.get(`window)##height;
type state = {
tag: string,
path: option(string),
photos: array(photoIdentifier),
};
type action =
| SetTag(string)
| SetPath(string)
| SetPhotos(array(photoIdentifier));
let styles = Style.(
StyleSheet.create({
"container":
style(
~flex=1.,
~flexDirection=`column,
~alignItems=`center,
~justifyContent=`spaceBetween,
(),
),
"getPhotosExample":
style(
~height=(0.25 *. windowHeight)->dp,
~justifyContent=`spaceBetween,
(),
),
"saveToCameraRollExample":
style(
~width=(0.8 *. windowWidth)->dp,
~height=(0.6 *. windowHeight)->dp,
~margin=(0.1 *. windowWidth)->dp,
~justifyContent=`spaceAround,
(),
),
"image":
style(
~width=(0.8 *. windowWidth)->dp,
~height=(0.56 *. windowWidth)->dp,
(),
),
"imageContainer":
style(
~width=(0.8 *. windowWidth)->dp,
~height=(0.56 *. windowWidth)->dp,
~borderWidth=1.,
~justifyContent=`center,
(),
),
"text": style(~textAlign=`center, ()),
"textInput":
style(
~textAlign=`center,
~borderRadius=8.,
~padding=4.->dp,
~borderWidth=1.,
~backgroundColor=Color.linen,
(),
),
"thumbnail":
style(
~width=(0.21 *. windowHeight)->dp,
~height=(0.15 *. windowHeight)->dp,
(),
),
"thumbnails":
style(
~height=(0.15 *. windowHeight)->dp,
(),
),
})
);
let styledText = s => {
s->React.string ;
};
let thumbnails = photos => {
{photos
->Belt.Array.mapWithIndex((i, s) =>
)
->React.array}
;
};
let inputBox = (tag, dispatch) => {
dispatch(SetTag(s))}
/>;
};
[@react.component]
let make = () => {
let (state, dispatch) =
React.useReducer(
(state, action) =>
switch (action) {
| SetTag(uri) => {...state, tag: uri}
| SetPath(uri) => {...state, path: Some(uri)}
| SetPhotos(a) => {...state, photos: a}
},
{
tag: "https://images.unsplash.com/photo-1520453803296-c39eabe2dab4",
path: None,
photos: [||],
},
);
let getPhotos = () => {
Js.Promise.(
getPhotos(
getPhotosParams(
~first=20,
~assetType=`Photos,
~groupTypes=`All,
(),
),
)
|> then_(r => resolve(dispatch(SetPhotos(r.edges))))
|> catch(err => resolve(Js.Console.warn(err)))
|> ignore
);
};
let savePhoto = uri => {
Js.Promise.(
saveToCameraRoll(uri)
|> then_(r => resolve(dispatch(SetPath(r))))
|> catch(err => resolve(Js.Console.warn(err)))
|> ignore
);
};
{switch (state.path) {
| None =>
// default view, before a photo is saved to the Camera Roll or Photo Library
{styledText("Press the Save Photo button")}
{styledText("below to load photo")}
| Some(p) =>
// Once a photo is saved to the Camera Roll or Photo Library, it will be displayed in this view
}}
{styledText("Enter a path for a photo to save,")}
{styledText("or try the example given below")}
// TextInput box to try other photo sources
{inputBox(state.tag, dispatch)}
// An attempt will be made to save the photo file specified in the TextInput box to the Camera Roll or Photo Library once the button below is pressed
savePhoto(state.tag)}
title={js|Save a Photo|js}
/>
{styledText("Saved photo will appear in the Camera Roll")}
// An attempt will be made to get the most recent 20 photos from the Camera Roll or Photo Library
getPhotos()} title={js|Open CameraRoll|js} />
{thumbnails(state.photos)}
;
};
```
---
## Changelog
Check the [changelog](./CHANGELOG.md) for more informations about recent
releases.
---
## Contribute
Read the
[contribution guidelines](https://github.com/rescript-react-native/.github/blob/master/CONTRIBUTING.md)
before contributing.
## Code of Conduct
We want this community to be friendly and respectful to each other. Please read
[our full code of conduct](https://github.com/rescript-react-native/.github/blob/master/CODE_OF_CONDUCT.md)
so that you can understand what actions will and will not be tolerated.