diff --git a/Makefile b/Makefile
index 1c2d013db..a4acdf9a8 100644
--- a/Makefile
+++ b/Makefile
@@ -61,9 +61,6 @@ clean: ## Cleans dependencies, previous builds and temp files
@echo Cleanup finished
post-install:
- @# Need to copy custom ImagePickerModule.java that implements correct permission checks for android
- @rm node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java
- @cp ./native_modules/ImagePickerModule.java node_modules/react-native-image-picker/android/src/main/java/com/imagepicker
@# Need to copy custom RNDocumentPicker.m that implements direct access to the document picker in iOS
@cp ./native_modules/RNDocumentPicker.m node_modules/react-native-document-picker/ios/RNDocumentPicker/RNDocumentPicker.m
diff --git a/app/components/attachment_button.js b/app/components/attachment_button.js
index 49eb0ff37..44024a573 100644
--- a/app/components/attachment_button.js
+++ b/app/components/attachment_button.js
@@ -42,11 +42,17 @@ export default class AttachmentButton extends PureComponent {
intl: intlShape.isRequired,
};
- attachFileFromCamera = async () => {
+ attachPhotoFromCamera = () => {
+ return this.attachFileFromCamera('photo');
+ };
+
+ attachFileFromCamera = async (mediaType) => {
const {formatMessage} = this.context.intl;
const options = {
- quality: 1.0,
+ quality: 1,
+ videoQuality: 'high',
noData: true,
+ mediaType,
storageOptions: {
cameraRoll: true,
waitUntilSaved: true,
@@ -84,7 +90,7 @@ export default class AttachmentButton extends PureComponent {
attachFileFromLibrary = () => {
const {formatMessage} = this.context.intl;
const options = {
- quality: 1.0,
+ quality: 1,
noData: true,
permissionDenied: {
title: formatMessage({
@@ -116,10 +122,14 @@ export default class AttachmentButton extends PureComponent {
});
};
+ attachVideoFromCamera = () => {
+ return this.attachFileFromCamera('video');
+ };
+
attachVideoFromLibraryAndroid = () => {
const {formatMessage} = this.context.intl;
const options = {
- quality: 1.0,
+ videoQuality: 'high',
mediaType: 'video',
noData: true,
permissionDenied: {
@@ -313,12 +323,19 @@ export default class AttachmentButton extends PureComponent {
this.props.blurTextBox();
const options = {
items: [{
- action: () => this.handleFileAttachmentOption(this.attachFileFromCamera),
+ action: () => this.handleFileAttachmentOption(this.attachPhotoFromCamera),
text: {
- id: t('mobile.file_upload.camera'),
- defaultMessage: 'Take Photo or Video',
+ id: t('mobile.file_upload.camera_photo'),
+ defaultMessage: 'Take Photo',
},
icon: 'camera',
+ }, {
+ action: () => this.handleFileAttachmentOption(this.attachVideoFromCamera),
+ text: {
+ id: t('mobile.file_upload.camera_video'),
+ defaultMessage: 'Take Video',
+ },
+ icon: 'video-camera',
}, {
action: () => this.handleFileAttachmentOption(this.attachFileFromLibrary),
text: {
diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json
index ad5afc2bb..af4c34c3b 100644
--- a/assets/base/i18n/en.json
+++ b/assets/base/i18n/en.json
@@ -235,7 +235,8 @@
"mobile.failed_network_action.shortDescription": "Make sure you have an active connection and try again.",
"mobile.failed_network_action.title": "No internet connection",
"mobile.file_upload.browse": "Browse Files",
- "mobile.file_upload.camera": "Take Photo or Video",
+ "mobile.file_upload.camera_photo": "Take Photo",
+ "mobile.file_upload.camera_video": "Take Video",
"mobile.file_upload.library": "Photo Library",
"mobile.file_upload.max_warning": "Uploads limited to 5 files maximum.",
"mobile.file_upload.video": "Video Library",
diff --git a/ios/Mattermost.xcodeproj/project.pbxproj b/ios/Mattermost.xcodeproj/project.pbxproj
index 83cb0e285..807cf586d 100644
--- a/ios/Mattermost.xcodeproj/project.pbxproj
+++ b/ios/Mattermost.xcodeproj/project.pbxproj
@@ -5,6 +5,7 @@
};
objectVersion = 46;
objects = {
+
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
@@ -1043,7 +1044,6 @@
EE3EE4548D3F4A49B1274722 /* libRNLocalAuth.a */,
17A75F5A3D0D4A4A995DCD76 /* libRNPasscodeStatus.a */,
77810F0A063349439B0D8B6B /* libJailMonkey.a */,
- 0C0C75A424714EAC8E876A8F /* libFastImage.a */,
4B19E38FBCB94C57BB03B8E6 /* libRNFetchBlob.a */,
4A22BC320BA04E18A7F2A4E6 /* libReactNativeExceptionHandler.a */,
2AE23B96BF7545B9A77C0C87 /* libRNSentry.a */,
@@ -2376,9 +2376,7 @@
INFOPLIST_FILE = MattermostTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- LIBRARY_SEARCH_PATHS = (
- "$(inherited)",
- );
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -2405,9 +2403,7 @@
INFOPLIST_FILE = MattermostTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
- LIBRARY_SEARCH_PATHS = (
- "$(inherited)",
- );
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
diff --git a/ios/Mattermost/Info.plist b/ios/Mattermost/Info.plist
index 191789729..e16a7afdc 100644
--- a/ios/Mattermost/Info.plist
+++ b/ios/Mattermost/Info.plist
@@ -62,10 +62,12 @@
Share contacts in your Mattermost instance
NSCameraUsageDescription
Take a Photo or Video and upload it to your mattermost instance
+ NSLocationAlwaysUsageDescription
+ Send your current location to your Mattermost instance
NSLocationWhenInUseUsageDescription
Send your current location to your Mattermost instance
- NSLocationAlwaysUsageDescription
- Send your current location to your Mattermost instance
+ NSMicrophoneUsageDescription
+ Capture audio when recording a video to share to your Mattermost instance
NSMotionUsageDescription
Share your route in your Mattermost instance
NSPhotoLibraryUsageDescription
diff --git a/native_modules/ImagePickerModule.java b/native_modules/ImagePickerModule.java
deleted file mode 100644
index b3b3ee9c6..000000000
--- a/native_modules/ImagePickerModule.java
+++ /dev/null
@@ -1,729 +0,0 @@
-package com.imagepicker;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Build;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.StyleRes;
-import android.support.v4.app.ActivityCompat;
-import android.support.v7.app.AlertDialog;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Patterns;
-import android.webkit.MimeTypeMap;
-import android.content.pm.PackageManager;
-
-import com.facebook.react.ReactActivity;
-import com.facebook.react.bridge.ActivityEventListener;
-import com.facebook.react.bridge.Callback;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.facebook.react.bridge.ReactContextBaseJavaModule;
-import com.facebook.react.bridge.ReactMethod;
-import com.facebook.react.bridge.ReadableMap;
-import com.imagepicker.media.ImageConfig;
-import com.imagepicker.permissions.PermissionUtils;
-import com.imagepicker.permissions.OnImagePickerPermissionsCallback;
-import com.imagepicker.utils.MediaUtils.ReadExifResult;
-import com.imagepicker.utils.RealPathUtil;
-import com.imagepicker.utils.UI;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.ref.WeakReference;
-import java.util.List;
-
-import com.facebook.react.modules.core.PermissionListener;
-import com.facebook.react.modules.core.PermissionAwareActivity;
-
-import static com.imagepicker.utils.MediaUtils.*;
-import static com.imagepicker.utils.MediaUtils.createNewFile;
-import static com.imagepicker.utils.MediaUtils.getResizedImage;
-
-public class ImagePickerModule extends ReactContextBaseJavaModule
- implements ActivityEventListener
-{
-
- public static final int REQUEST_LAUNCH_IMAGE_CAPTURE = 13001;
- public static final int REQUEST_LAUNCH_IMAGE_LIBRARY = 13002;
- public static final int REQUEST_LAUNCH_VIDEO_LIBRARY = 13003;
- public static final int REQUEST_LAUNCH_VIDEO_CAPTURE = 13004;
- public static final int REQUEST_PERMISSIONS_FOR_CAMERA = 14001;
- public static final int REQUEST_PERMISSIONS_FOR_LIBRARY = 14002;
-
- private final ReactApplicationContext reactContext;
- private final int dialogThemeId;
-
- protected Callback callback;
- private ReadableMap options;
- protected Uri cameraCaptureURI;
- private Boolean noData = false;
- private Boolean pickVideo = false;
- private ImageConfig imageConfig = new ImageConfig(null, null, 0, 0, 100, 0, false);
-
- @Deprecated
- private int videoQuality = 1;
-
- @Deprecated
- private int videoDurationLimit = 0;
-
- private ResponseHelper responseHelper = new ResponseHelper();
- private PermissionListener listener = new PermissionListener()
- {
- public boolean onRequestPermissionsResult(final int requestCode,
- @NonNull final String[] permissions,
- @NonNull final int[] grantResults)
- {
- boolean permissionsGranted = true;
- for (int i = 0; i < permissions.length; i++)
- {
- final boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
- permissionsGranted = permissionsGranted && granted;
- }
-
- if (callback == null || options == null)
- {
- return false;
- }
-
- if (!permissionsGranted)
- {
- responseHelper.invokeError(callback, "Permissions weren't granted");
- return false;
- }
-
- switch (requestCode)
- {
- case REQUEST_PERMISSIONS_FOR_CAMERA:
- launchCamera(options, callback);
- break;
-
- case REQUEST_PERMISSIONS_FOR_LIBRARY:
- launchImageLibrary(options, callback);
- break;
-
- }
- return true;
- }
- };
-
- public ImagePickerModule(ReactApplicationContext reactContext,
- @StyleRes final int dialogThemeId)
- {
- super(reactContext);
-
- this.dialogThemeId = dialogThemeId;
- this.reactContext = reactContext;
- this.reactContext.addActivityEventListener(this);
- }
-
- @Override
- public String getName() {
- return "ImagePickerManager";
- }
-
- @ReactMethod
- public void showImagePicker(final ReadableMap options, final Callback callback) {
- Activity currentActivity = getCurrentActivity();
-
- if (currentActivity == null)
- {
- responseHelper.invokeError(callback, "can't find current Activity");
- return;
- }
-
- this.callback = callback;
- this.options = options;
- imageConfig = new ImageConfig(null, null, 0, 0, 100, 0, false);
-
- final AlertDialog dialog = UI.chooseDialog(this, options, new UI.OnAction()
- {
- @Override
- public void onTakePhoto(@NonNull final ImagePickerModule module)
- {
- if (module == null)
- {
- return;
- }
- module.launchCamera();
- }
-
- @Override
- public void onUseLibrary(@NonNull final ImagePickerModule module)
- {
- if (module == null)
- {
- return;
- }
- module.launchImageLibrary();
- }
-
- @Override
- public void onCancel(@NonNull final ImagePickerModule module)
- {
- if (module == null)
- {
- return;
- }
- module.doOnCancel();
- }
-
- @Override
- public void onCustomButton(@NonNull final ImagePickerModule module,
- @NonNull final String action)
- {
- if (module == null)
- {
- return;
- }
- module.invokeCustomButton(action);
- }
- });
- dialog.show();
- }
-
- public void doOnCancel()
- {
- if (this.callback != null) {
- responseHelper.invokeCancel(this.callback);
- }
- }
-
- public void launchCamera()
- {
- this.launchCamera(this.options, this.callback);
- }
-
- // NOTE: Currently not reentrant / doesn't support concurrent requests
- @ReactMethod
- public void launchCamera(final ReadableMap options, final Callback callback)
- {
- if (!isCameraAvailable())
- {
- responseHelper.invokeError(callback, "Camera not available");
- return;
- }
-
- final Activity currentActivity = getCurrentActivity();
- if (currentActivity == null)
- {
- responseHelper.invokeError(callback, "can't find current Activity");
- return;
- }
-
- this.callback = callback;
- this.options = options;
-
- if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_CAMERA))
- {
- return;
- }
-
- parseOptions(this.options);
-
- int requestCode;
- Intent cameraIntent;
-
- if (pickVideo)
- {
- requestCode = REQUEST_LAUNCH_VIDEO_CAPTURE;
- cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
- cameraIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, videoQuality);
- if (videoDurationLimit > 0)
- {
- cameraIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, videoDurationLimit);
- }
- }
- else
- {
- requestCode = REQUEST_LAUNCH_IMAGE_CAPTURE;
- cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-
- final File original = createNewFile(reactContext, this.options, false);
- imageConfig = imageConfig.withOriginalFile(original);
-
- if (imageConfig.original != null) {
- cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original);
- }else {
- responseHelper.invokeError(callback, "Couldn't get file path for photo");
- return;
- }
- if (cameraCaptureURI == null)
- {
- responseHelper.invokeError(callback, "Couldn't get file path for photo");
- return;
- }
- cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraCaptureURI);
- }
-
- if (cameraIntent.resolveActivity(reactContext.getPackageManager()) == null)
- {
- responseHelper.invokeError(callback, "Cannot launch camera");
- return;
- }
-
- // Workaround for Android bug.
- // grantUriPermission also needed for KITKAT,
- // see https://code.google.com/p/android/issues/detail?id=76683
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
- List resInfoList = reactContext.getPackageManager().queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
- for (ResolveInfo resolveInfo : resInfoList) {
- String packageName = resolveInfo.activityInfo.packageName;
- reactContext.grantUriPermission(packageName, cameraCaptureURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- }
-
- try
- {
- currentActivity.startActivityForResult(cameraIntent, requestCode);
- }
- catch (ActivityNotFoundException e)
- {
- e.printStackTrace();
- responseHelper.invokeError(callback, "Cannot launch camera");
- }
- }
-
- public void launchImageLibrary()
- {
- this.launchImageLibrary(this.options, this.callback);
- }
- // NOTE: Currently not reentrant / doesn't support concurrent requests
- @ReactMethod
- public void launchImageLibrary(final ReadableMap options, final Callback callback)
- {
- final Activity currentActivity = getCurrentActivity();
- if (currentActivity == null) {
- responseHelper.invokeError(callback, "can't find current Activity");
- return;
- }
-
- this.options = options;
- this.callback = callback;
-
- if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_LIBRARY))
- {
- return;
- }
-
- parseOptions(this.options);
-
- int requestCode;
- Intent libraryIntent;
- if (pickVideo)
- {
- requestCode = REQUEST_LAUNCH_VIDEO_LIBRARY;
- libraryIntent = new Intent(Intent.ACTION_PICK);
- libraryIntent.setType("video/*");
- }
- else
- {
- requestCode = REQUEST_LAUNCH_IMAGE_LIBRARY;
- libraryIntent = new Intent(Intent.ACTION_PICK,
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
- }
-
- if (libraryIntent.resolveActivity(reactContext.getPackageManager()) == null)
- {
- responseHelper.invokeError(callback, "Cannot launch photo library");
- return;
- }
-
- try
- {
- currentActivity.startActivityForResult(libraryIntent, requestCode);
- }
- catch (ActivityNotFoundException e)
- {
- e.printStackTrace();
- responseHelper.invokeError(callback, "Cannot launch photo library");
- }
- }
-
- @Override
- public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
- //robustness code
- if (passResult(requestCode))
- {
- return;
- }
-
- responseHelper.cleanResponse();
-
- // user cancel
- if (resultCode != Activity.RESULT_OK)
- {
- removeUselessFiles(requestCode, imageConfig);
- responseHelper.invokeCancel(callback);
- callback = null;
- return;
- }
-
- Uri uri = null;
- switch (requestCode)
- {
- case REQUEST_LAUNCH_IMAGE_CAPTURE:
- uri = cameraCaptureURI;
- break;
-
- case REQUEST_LAUNCH_IMAGE_LIBRARY:
- uri = data.getData();
- String realPath = getRealPathFromURI(uri);
- final boolean isUrl = !TextUtils.isEmpty(realPath) &&
- Patterns.WEB_URL.matcher(realPath).matches();
- if (realPath == null || isUrl)
- {
- try
- {
- File file = createFileFromURI(uri);
- realPath = file.getAbsolutePath();
- uri = Uri.fromFile(file);
- }
- catch (Exception e)
- {
- // image not in cache
- responseHelper.putString("error", "Could not read photo");
- responseHelper.putString("uri", uri.toString());
- responseHelper.invokeResponse(callback);
- callback = null;
- return;
- }
- }
- imageConfig = imageConfig.withOriginalFile(new File(realPath));
- break;
-
- case REQUEST_LAUNCH_VIDEO_LIBRARY:
- responseHelper.putString("uri", data.getData().toString());
- responseHelper.putString("path", getRealPathFromURI(data.getData()));
- responseHelper.invokeResponse(callback);
- callback = null;
- return;
-
- case REQUEST_LAUNCH_VIDEO_CAPTURE:
- final String path = getRealPathFromURI(data.getData());
- responseHelper.putString("uri", data.getData().toString());
- responseHelper.putString("path", path);
- fileScan(reactContext, path);
- responseHelper.invokeResponse(callback);
- callback = null;
- return;
- }
-
- final ReadExifResult result = readExifInterface(responseHelper, imageConfig);
-
- if (result.error != null)
- {
- removeUselessFiles(requestCode, imageConfig);
- responseHelper.invokeError(callback, result.error.getMessage());
- callback = null;
- return;
- }
-
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(imageConfig.original.getAbsolutePath(), options);
- int initialWidth = options.outWidth;
- int initialHeight = options.outHeight;
- updatedResultResponse(uri, imageConfig.original.getAbsolutePath());
-
- // don't create a new file if contraint are respected
- if (imageConfig.useOriginal(initialWidth, initialHeight, result.currentRotation))
- {
- responseHelper.putInt("width", initialWidth);
- responseHelper.putInt("height", initialHeight);
- fileScan(reactContext, imageConfig.original.getAbsolutePath());
- }
- else
- {
- imageConfig = getResizedImage(reactContext, this.options, imageConfig, initialWidth, initialHeight, requestCode);
- if (imageConfig.resized == null)
- {
- removeUselessFiles(requestCode, imageConfig);
- responseHelper.putString("error", "Can't resize the image");
- }
- else
- {
- uri = Uri.fromFile(imageConfig.resized);
- BitmapFactory.decodeFile(imageConfig.resized.getAbsolutePath(), options);
- responseHelper.putInt("width", options.outWidth);
- responseHelper.putInt("height", options.outHeight);
-
- updatedResultResponse(uri, imageConfig.resized.getAbsolutePath());
- fileScan(reactContext, imageConfig.resized.getAbsolutePath());
- }
- }
-
- if (imageConfig.saveToCameraRoll && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE)
- {
- final RolloutPhotoResult rolloutResult = rolloutPhotoFromCamera(imageConfig);
-
- if (rolloutResult.error == null)
- {
- imageConfig = rolloutResult.imageConfig;
- uri = Uri.fromFile(imageConfig.getActualFile());
- updatedResultResponse(uri, imageConfig.getActualFile().getAbsolutePath());
- }
- else
- {
- removeUselessFiles(requestCode, imageConfig);
- final String errorMessage = new StringBuilder("Error moving image to camera roll: ")
- .append(rolloutResult.error.getMessage()).toString();
- responseHelper.putString("error", errorMessage);
- return;
- }
- }
-
- responseHelper.invokeResponse(callback);
- callback = null;
- this.options = null;
- }
-
- public void invokeCustomButton(@NonNull final String action)
- {
- responseHelper.invokeCustomButton(this.callback, action);
- }
-
- @Override
- public void onNewIntent(Intent intent) { }
-
- public Context getContext()
- {
- return getReactApplicationContext();
- }
-
- public @StyleRes int getDialogThemeId()
- {
- return this.dialogThemeId;
- }
-
- public @NonNull Activity getActivity()
- {
- return getCurrentActivity();
- }
-
-
- private boolean passResult(int requestCode)
- {
- return callback == null || (cameraCaptureURI == null && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE)
- || (requestCode != REQUEST_LAUNCH_IMAGE_CAPTURE && requestCode != REQUEST_LAUNCH_IMAGE_LIBRARY
- && requestCode != REQUEST_LAUNCH_VIDEO_LIBRARY && requestCode != REQUEST_LAUNCH_VIDEO_CAPTURE);
- }
-
- private void updatedResultResponse(@Nullable final Uri uri,
- @NonNull final String path)
- {
- responseHelper.putString("uri", uri.toString());
- responseHelper.putString("path", path);
-
- if (!noData) {
- responseHelper.putString("data", getBase64StringFromFile(path));
- }
-
- putExtraFileInfo(path, responseHelper);
- }
-
- private boolean permissionsCheck(@NonNull final Activity activity,
- @NonNull final Callback callback,
- @NonNull final int requestCode)
- {
- final int writePermission = ActivityCompat
- .checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
- final int cameraPermission = ActivityCompat
- .checkSelfPermission(activity, Manifest.permission.CAMERA);
-
- final boolean permissionsGrated = writePermission == PackageManager.PERMISSION_GRANTED &&
- cameraPermission == PackageManager.PERMISSION_GRANTED;
-
- if (!permissionsGrated)
- {
- final Boolean dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA);
-
- if (dontAskAgain)
- {
- final AlertDialog dialog = PermissionUtils
- .explainingDialog(this, options, new PermissionUtils.OnExplainingPermissionCallback()
- {
- @Override
- public void onCancel(WeakReference moduleInstance,
- DialogInterface dialogInterface)
- {
- final ImagePickerModule module = moduleInstance.get();
- if (module == null)
- {
- return;
- }
- module.doOnCancel();
- }
-
- @Override
- public void onReTry(WeakReference moduleInstance,
- DialogInterface dialogInterface)
- {
- final ImagePickerModule module = moduleInstance.get();
- if (module == null)
- {
- return;
- }
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- Uri uri = Uri.fromParts("package", module.getContext().getPackageName(), null);
- intent.setData(uri);
- final Activity innerActivity = module.getActivity();
- if (innerActivity == null)
- {
- return;
- }
- innerActivity.startActivityForResult(intent, 1);
- }
- });
- if (dialog != null) {
- dialog.show();
- }
- return false;
- }
- else
- {
- String[] PERMISSIONS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
- if (activity instanceof ReactActivity)
- {
- ((ReactActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
- }
- else if (activity instanceof OnImagePickerPermissionsCallback)
- {
- ((OnImagePickerPermissionsCallback) activity).setPermissionListener(listener);
- ActivityCompat.requestPermissions(activity, PERMISSIONS, requestCode);
- }
- else if (activity instanceof PermissionAwareActivity) {
- ((PermissionAwareActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
- }
- else
- {
- final String errorDescription = new StringBuilder(activity.getClass().getSimpleName())
- .append(" must implement ")
- .append(OnImagePickerPermissionsCallback.class.getSimpleName())
- .append(PermissionAwareActivity.class.getSimpleName())
- .toString();
- throw new UnsupportedOperationException(errorDescription);
- }
- return false;
- }
- }
- return true;
- }
-
- private boolean isCameraAvailable() {
- return reactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)
- || reactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
- }
-
- private @NonNull String getRealPathFromURI(@NonNull final Uri uri) {
- return RealPathUtil.getRealPathFromURI(reactContext, uri);
- }
-
- /**
- * Create a file from uri to allow image picking of image in disk cache
- * (Exemple: facebook image, google image etc..)
- *
- * @doc =>
- * https://github.com/nostra13/Android-Universal-Image-Loader#load--display-task-flow
- *
- * @param uri
- * @return File
- * @throws Exception
- */
- private File createFileFromURI(Uri uri) throws Exception {
- File file = new File(reactContext.getExternalCacheDir(), "photo-" + uri.getLastPathSegment());
- InputStream input = reactContext.getContentResolver().openInputStream(uri);
- OutputStream output = new FileOutputStream(file);
-
- try {
- byte[] buffer = new byte[4 * 1024];
- int read;
- while ((read = input.read(buffer)) != -1) {
- output.write(buffer, 0, read);
- }
- output.flush();
- } finally {
- output.close();
- input.close();
- }
-
- return file;
- }
-
- private String getBase64StringFromFile(String absoluteFilePath) {
- InputStream inputStream = null;
- try {
- inputStream = new FileInputStream(new File(absoluteFilePath));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
-
- byte[] bytes;
- byte[] buffer = new byte[8192];
- int bytesRead;
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- try {
- while ((bytesRead = inputStream.read(buffer)) != -1) {
- output.write(buffer, 0, bytesRead);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- bytes = output.toByteArray();
- return Base64.encodeToString(bytes, Base64.NO_WRAP);
- }
-
- private void putExtraFileInfo(@NonNull final String path,
- @NonNull final ResponseHelper responseHelper)
- {
- // size && filename
- try {
- File f = new File(path);
- responseHelper.putDouble("fileSize", f.length());
- responseHelper.putString("fileName", f.getName());
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- // type
- String extension = MimeTypeMap.getFileExtensionFromUrl(path);
- if (extension != null) {
- responseHelper.putString("type", MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
- }
- }
-
- private void parseOptions(final ReadableMap options) {
- noData = false;
- if (options.hasKey("noData")) {
- noData = options.getBoolean("noData");
- }
- imageConfig = imageConfig.updateFromOptions(options);
- pickVideo = false;
- if (options.hasKey("mediaType") && options.getString("mediaType").equals("video")) {
- pickVideo = true;
- }
- videoQuality = 1;
- if (options.hasKey("videoQuality") && options.getString("videoQuality").equals("low")) {
- videoQuality = 0;
- }
- videoDurationLimit = 0;
- if (options.hasKey("durationLimit")) {
- videoDurationLimit = options.getInt("durationLimit");
- }
- }
-}
diff --git a/package-lock.json b/package-lock.json
index e9f941cc1..f0724e141 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12754,9 +12754,9 @@
}
},
"react-native-image-picker": {
- "version": "0.26.10",
- "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.10.tgz",
- "integrity": "sha512-z6gAbru2E6SyGWm4ZTbiM9hPHZ5Tsl9kXGfRxW6YQXf9us7zybKoS7dKE1fQPsssv/OSvpPDKannJNncE+ATRA=="
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.27.0.tgz",
+ "integrity": "sha512-x4UDEs1XvfO+wXx41CZcZ4eVB+zj0vZuIl14ExO00WhyRf2NUXd4BG1uJzajOiyYQ+eRJQgv2PaNUamN6JqXZg=="
},
"react-native-iphone-x-helper": {
"version": "1.1.0",
diff --git a/package.json b/package.json
index c1441a9eb..8f1609490 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"react-native-drawer-layout": "2.0.0",
"react-native-exception-handler": "2.9.0",
"react-native-image-gallery": "github:enahum/react-native-image-gallery#a98b1051e94f5a394541ca1ff9b15e2c9ffed84f",
- "react-native-image-picker": "0.26.10",
+ "react-native-image-picker": "0.27.0",
"react-native-keyboard-aware-scroll-view": "0.7.2",
"react-native-keychain": "3.0.0",
"react-native-linear-gradient": "2.4.2",