diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index b43bf86b5..000000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -README.md diff --git a/.prettierrc b/.prettierrc index 635e22152..1d4c3eff7 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,9 +1,8 @@ { + "requirePragma": true, "singleQuote": true, "trailingComma": "all", "bracketSpacing": false, "jsxBracketSameLine": true, - "overrides": [ - {"files": ["*.js"], "options": {"parser": "flow", "requirePragma": true}} - ] -} + "parser": "flow" +} \ No newline at end of file diff --git a/README.md b/README.md index bb3c9670b..72392ae8c 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ Returns a Promise with photo identifier objects from the local camera roll of th | params | object | Yes | Expects a params with the shape described below. | * `first` : {number} : The number of photos wanted in reverse order of the photo application (i.e. most recent first for SavedPhotos). Required. -* `after` : {string} : A cursor that matches `page_info { end_cursor }` returned from a previous call to `getPhotos`. Note that using this will reduce performance slightly on iOS. An alternative is just using the `fromTime` and `toTime` filters, which have no such impact. +* `after` : {string} : A cursor that matches `page_info { end_cursor }` returned from a previous call to `getPhotos`. * `groupTypes` : {string} : Specifies which group types to filter the results to. Valid values are: * `Album` * `All` // default @@ -165,13 +165,9 @@ Returns a Promise with photo identifier objects from the local camera roll of th * `All` * `Videos` * `Photos` // default -* `mimeTypes` : {Array} : Filter by mimetype (e.g. image/jpeg). Note that using this will reduce performance slightly on iOS. -* `fromTime` : {number} : Filter by creation time with a timestamp in milliseconds. This time is exclusive, so we'll select all photos with `timestamp > fromTime`. -* `toTime` : {number} : Filter by creation time with a timestamp in milliseconds. This time is inclusive, so we'll select all photos with `timestamp <= toTime`. -* `include` : {Array} : Whether to include some fields that are slower to fetch - * `filename` : Ensures `image.filename` is available in each node. This has a large performance impact on iOS. - * `fileSize` : Ensures `image.fileSize` is available in each node. This has a large performance impact on iOS. - * `location`: Ensures `location` is available in each node. This has a large performance impact on Android. +* `mimeTypes` : {Array} : Filter by mimetype (e.g. image/jpeg). +* `fromTime` : {timestamp} : Filter from date added. +* `toTime` : {timestamp} : Filter to date added. Returns a Promise which when resolved will be of the following shape: @@ -181,14 +177,14 @@ Returns a Promise which when resolved will be of the following shape: * `group_name`: {string} * `image`: {object} : An object with the following shape: * `uri`: {string} - * `filename`: {string | null} : Only set if the `include` parameter contains `filename`. + * `filename`: {string} * `height`: {number} * `width`: {number} - * `fileSize`: {number | null} : Only set if the `include` parameter contains `fileSize`. + * `fileSize`: {number} * `isStored`: {boolean} * `playableDuration`: {number} - * `timestamp`: {number} : Timestamp in seconds. - * `location`: {object | null} : Only set if the `include` parameter contains `location`. An object with the following shape: + * `timestamp`: {number} + * `location`: {object} : An object with the following shape: * `latitude`: {number} * `longitude`: {number} * `altitude`: {number} @@ -237,10 +233,8 @@ render() { ); } -``` - +``` --- - ### `deletePhotos()` ```javascript diff --git a/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java b/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java index 76f2bc437..b2f537367 100644 --- a/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java +++ b/android/src/main/java/com/reactnativecommunity/cameraroll/CameraRollModule.java @@ -47,11 +47,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.channels.FileChannel; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.HashMap; -import java.util.Set; import javax.annotation.Nullable; @@ -74,10 +72,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { private static final String ASSET_TYPE_VIDEOS = "Videos"; private static final String ASSET_TYPE_ALL = "All"; - private static final String INCLUDE_FILENAME = "filename"; - private static final String INCLUDE_FILE_SIZE = "fileSize"; - private static final String INCLUDE_LOCATION = "location"; - private static final String[] PROJECTION = { Images.Media._ID, Images.Media.MIME_TYPE, @@ -253,7 +247,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { ReadableArray mimeTypes = params.hasKey("mimeTypes") ? params.getArray("mimeTypes") : null; - ReadableArray include = params.hasKey("include") ? params.getArray("include") : null; new GetMediaTask( getReactApplicationContext(), @@ -264,7 +257,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { assetType, fromTime, toTime, - include, promise) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -279,7 +271,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { private final String mAssetType; private final long mFromTime; private final long mToTime; - private final Set mInclude; private GetMediaTask( ReactContext context, @@ -290,7 +281,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { String assetType, long fromTime, long toTime, - @Nullable ReadableArray include, Promise promise) { super(context); mContext = context; @@ -302,24 +292,6 @@ public class CameraRollModule extends ReactContextBaseJavaModule { mAssetType = assetType; mFromTime = fromTime; mToTime = toTime; - mInclude = createSetFromIncludeArray(include); - } - - private static Set createSetFromIncludeArray(@Nullable ReadableArray includeArray) { - Set includeSet = new HashSet<>(); - - if (includeArray == null) { - return includeSet; - } - - for (int i = 0; i < includeArray.size(); i++) { - @Nullable String includeItem = includeArray.getString(i); - if (includeItem != null) { - includeSet.add(includeItem); - } - } - - return includeSet; } @Override @@ -390,7 +362,7 @@ public class CameraRollModule extends ReactContextBaseJavaModule { mPromise.reject(ERROR_UNABLE_TO_LOAD, "Could not get media"); } else { try { - putEdges(resolver, media, response, mFirst, mInclude); + putEdges(resolver, media, response, mFirst); putPageInfo(media, response, mFirst, !TextUtils.isEmpty(mAfter) ? Integer.parseInt(mAfter) : 0); } finally { media.close(); @@ -491,10 +463,10 @@ public class CameraRollModule extends ReactContextBaseJavaModule { ContentResolver resolver, Cursor media, WritableMap response, - int limit, - Set include) { + int limit) { WritableArray edges = new WritableNativeArray(); media.moveToFirst(); + int idIndex = media.getColumnIndex(Images.Media._ID); int mimeTypeIndex = media.getColumnIndex(Images.Media.MIME_TYPE); int groupNameIndex = media.getColumnIndex(Images.Media.BUCKET_DISPLAY_NAME); int dateTakenIndex = media.getColumnIndex(Images.Media.DATE_TAKEN); @@ -503,19 +475,14 @@ public class CameraRollModule extends ReactContextBaseJavaModule { int sizeIndex = media.getColumnIndex(MediaStore.MediaColumns.SIZE); int dataIndex = media.getColumnIndex(MediaStore.MediaColumns.DATA); - boolean includeLocation = include.contains(INCLUDE_LOCATION); - boolean includeFilename = include.contains(INCLUDE_FILENAME); - boolean includeFileSize = include.contains(INCLUDE_FILE_SIZE); - for (int i = 0; i < limit && !media.isAfterLast(); i++) { WritableMap edge = new WritableNativeMap(); WritableMap node = new WritableNativeMap(); boolean imageInfoSuccess = - putImageInfo(resolver, media, node, widthIndex, heightIndex, sizeIndex, dataIndex, - mimeTypeIndex, includeFilename, includeFileSize); + putImageInfo(resolver, media, node, idIndex, widthIndex, heightIndex, sizeIndex, dataIndex, mimeTypeIndex); if (imageInfoSuccess) { putBasicNodeInfo(media, node, mimeTypeIndex, groupNameIndex, dateTakenIndex); - putLocationInfo(media, node, dataIndex, includeLocation); + putLocationInfo(media, node, dataIndex); edge.putMap("node", node); edges.pushMap(edge); @@ -544,18 +511,22 @@ public class CameraRollModule extends ReactContextBaseJavaModule { ContentResolver resolver, Cursor media, WritableMap node, + int idIndex, int widthIndex, int heightIndex, int sizeIndex, int dataIndex, - int mimeTypeIndex, - boolean includeFilename, - boolean includeFileSize) { + int mimeTypeIndex) { WritableMap image = new WritableNativeMap(); Uri photoUri = Uri.parse("file://" + media.getString(dataIndex)); + File file = new File(media.getString(dataIndex)); + String strFileName = file.getName(); image.putString("uri", photoUri.toString()); + image.putString("filename", strFileName); float width = media.getInt(widthIndex); float height = media.getInt(heightIndex); + long fileSize = media.getLong(sizeIndex); + String mimeType = media.getString(mimeTypeIndex); if (mimeType != null @@ -614,21 +585,7 @@ public class CameraRollModule extends ReactContextBaseJavaModule { } image.putDouble("width", width); image.putDouble("height", height); - - if (includeFilename) { - File file = new File(media.getString(dataIndex)); - String strFileName = file.getName(); - image.putString("filename", strFileName); - } else { - image.putNull("filename"); - } - - if (includeFileSize) { - image.putDouble("fileSize", media.getLong(sizeIndex)); - } else { - image.putNull("fileSize"); - } - + image.putDouble("fileSize", fileSize); node.putMap("image", image); return true; @@ -637,13 +594,7 @@ public class CameraRollModule extends ReactContextBaseJavaModule { private static void putLocationInfo( Cursor media, WritableMap node, - int dataIndex, - boolean includeLocation) { - if (!includeLocation) { - node.putNull("location"); - return; - } - + int dataIndex) { try { // location details are no longer indexed for privacy reasons using string Media.LATITUDE, Media.LONGITUDE // we manually obtain location metadata using ExifInterface#getLatLong(float[]). diff --git a/example/App.js b/example/App.js new file mode 100644 index 000000000..e0944c799 --- /dev/null +++ b/example/App.js @@ -0,0 +1,32 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ +import React, {Component} from 'react'; +import {StyleSheet, View} from 'react-native'; +import CameraRollExample from './js/CameraRollExample'; + +type Props = {}; +export default class App extends Component { + render() { + return ( + + + + ); + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, +}); diff --git a/example/App.tsx b/example/App.tsx deleted file mode 100644 index 1d655c8c3..000000000 --- a/example/App.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ -import React, {Component} from 'react'; -import ExampleContainer from './js/ExampleContainer'; - -export default class App extends Component { - render() { - return ; - } -} diff --git a/example/index.js b/example/index.js index 4b5be70bc..f62137809 100644 --- a/example/index.js +++ b/example/index.js @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * * @format + * @flow */ import {AppRegistry} from 'react-native'; import App from './App'; diff --git a/example/js/CameraRollExample.js b/example/js/CameraRollExample.js index 02c88ae9b..acbc980d3 100644 --- a/example/js/CameraRollExample.js +++ b/example/js/CameraRollExample.js @@ -57,7 +57,7 @@ export default class CameraRollExample extends React.Component { render() { return ( - + { onPress={this.loadAsset.bind(this, asset)}> - + {asset.node.image.uri} {locationStr} {asset.node.group_name} @@ -135,6 +135,7 @@ export default class CameraRollExample extends React.Component { const styles = StyleSheet.create({ header: { + marginTop: 44, padding: 20, width: Dimensions.get('window').width, }, @@ -149,7 +150,7 @@ const styles = StyleSheet.create({ image: { margin: 4, }, - flex1: { + info: { flex: 1, }, }); diff --git a/example/js/ExampleContainer.tsx b/example/js/ExampleContainer.tsx deleted file mode 100644 index 1a42ed56f..000000000 --- a/example/js/ExampleContainer.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import * as React from 'react'; -import { - SafeAreaView, - StyleSheet, - View, - Button, - Modal, - TouchableWithoutFeedback, -} from 'react-native'; -// @ts-ignore: CameraRollExample has no typings in same folder -import CameraRollExample from './CameraRollExample'; -import GetPhotosPerformanceExample from './GetPhotosPerformanceExample'; - -interface Props {} - -interface State { - showChangeExampleModal: boolean; - currentExampleIndex: number; -} - -interface Example { - label: string; - Component: React.ComponentType; -} - -const examples: Example[] = [ - { - label: 'CameraRollExample', - Component: CameraRollExample, - }, - { - label: 'GetPhotosPerformanceExample', - Component: GetPhotosPerformanceExample, - }, -]; - -/** - * Container for displaying and switching between multiple examples. - * - * Shows a button which opens up a Modal to switch between examples, as well - * as the current example itself. - */ -export default class ExamplesContainer extends React.Component { - state: State = {showChangeExampleModal: false, currentExampleIndex: 0}; - - render() { - const {currentExampleIndex} = this.state; - return ( - -