Files
mattermost-mobile/android/app/src/main/java/com/mattermost/rnbeta/MattermostManagedModule.java
Elias Nahum e883186fde [Gekidou] retry post (#6293)
* Add try again functionality to failed posts

* Fix attach files on Android

* feedback review

* Prevent android crash when uploading files for the first time

* Update the timestamp for updateAt when retrying to post

* Add POST TIME TO FAIL

* use function isPostFailed
2022-05-20 13:23:19 -04:00

262 lines
9.6 KiB
Java

package com.mattermost.rnbeta;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.GuardedResultAsyncTask;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.mattermost.helpers.RealPathUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.nio.channels.FileChannel;
public class MattermostManagedModule extends ReactContextBaseJavaModule {
private static final String SAVE_EVENT = "MattermostManagedSaveFile";
private static final Integer SAVE_REQUEST = 38641;
private static MattermostManagedModule instance;
private ReactApplicationContext reactContext;
private Promise mPickerPromise;
private String fileContent;
private static final String TAG = MattermostManagedModule.class.getSimpleName();
private MattermostManagedModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
// Let the document provider know you're done by closing the stream.
ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
if (requestCode == SAVE_REQUEST) {
if (mPickerPromise != null) {
if (resultCode == Activity.RESULT_CANCELED) {
mPickerPromise.reject(SAVE_EVENT, "Save operation cancelled");
} else if (resultCode == Activity.RESULT_OK) {
Uri uri = intent.getData();
if (uri == null) {
mPickerPromise.reject(SAVE_EVENT, "No data found");
} else {
try {
new SaveDataTask(reactContext, fileContent, uri).execute();
mPickerPromise.resolve(uri.toString());
} catch (Exception e) {
mPickerPromise.reject(SAVE_EVENT, e.getMessage());
}
}
}
mPickerPromise = null;
} else if (resultCode == Activity.RESULT_OK) {
try {
Uri uri = intent.getData();
if (uri != null)
new SaveDataTask(reactContext, fileContent, uri).execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
};
reactContext.addActivityEventListener(mActivityEventListener);
}
public static MattermostManagedModule getInstance(ReactApplicationContext reactContext) {
if (instance == null) {
instance = new MattermostManagedModule(reactContext);
} else {
instance.reactContext = reactContext;
}
return instance;
}
public static MattermostManagedModule getInstance() {
return instance;
}
public void sendEvent(String eventName,
@Nullable WritableMap params) {
this.reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}
@Override
@NonNull
public String getName() {
return "MattermostManaged";
}
@ReactMethod
public void getFilePath(String filePath, Promise promise) {
Activity currentActivity = getCurrentActivity();
WritableMap map = Arguments.createMap();
if (currentActivity != null) {
Uri uri = Uri.parse(filePath);
String path = RealPathUtil.getRealPathFromURI(currentActivity, uri);
if (path != null) {
String text = "file://" + path;
map.putString("filePath", text);
}
}
promise.resolve(map);
}
@ReactMethod
public void isRunningInSplitView(final Promise promise) {
WritableMap result = Arguments.createMap();
Activity current = getCurrentActivity();
if (current != null) {
result.putBoolean("isSplitView", current.isInMultiWindowMode());
} else {
result.putBoolean("isSplitView", false);
}
promise.resolve(result);
}
@ReactMethod
public void saveFile(String path, final Promise promise) {
Uri contentUri;
String filename = "";
if(path.startsWith("content://")) {
contentUri = Uri.parse(path);
} else {
File newFile = new File(path);
filename = newFile.getName();
Activity currentActivity = getCurrentActivity();
if(currentActivity == null) {
promise.reject(SAVE_EVENT, "Activity doesn't exist");
return;
}
try {
final String packageName = currentActivity.getPackageName();
final String authority = new StringBuilder(packageName).append(".provider").toString();
contentUri = FileProvider.getUriForFile(currentActivity, authority, newFile);
}
catch(IllegalArgumentException e) {
promise.reject(SAVE_EVENT, e.getMessage());
return;
}
}
if(contentUri == null) {
promise.reject(SAVE_EVENT, "Invalid file");
return;
}
String extension = MimeTypeMap.getFileExtensionFromUrl(path).toLowerCase();
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
if (mimeType == null) {
mimeType = RealPathUtil.getMimeType(path);
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CREATE_DOCUMENT);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_TITLE, filename);
PackageManager pm = getCurrentActivity().getPackageManager();
if (intent.resolveActivity(pm) != null) {
try {
getCurrentActivity().startActivityForResult(intent, SAVE_REQUEST);
mPickerPromise = promise;
fileContent = path;
}
catch(Exception e) {
promise.reject(SAVE_EVENT, e.getMessage());
}
} else {
try {
if(mimeType == null) {
throw new Exception("It wasn't possible to detect the type of the file");
}
throw new Exception("No app associated with this mime type");
}
catch(Exception e) {
promise.reject(SAVE_EVENT, e.getMessage());
}
}
}
private static class SaveDataTask extends GuardedResultAsyncTask<Object> {
private final WeakReference<Context> weakContext;
private final String fromFile;
private final Uri toFile;
protected SaveDataTask(ReactApplicationContext reactContext, String path, Uri destination) {
super(reactContext.getExceptionHandler());
weakContext = new WeakReference<>(reactContext.getApplicationContext());
fromFile = path;
toFile = destination;
}
@Override
protected Object doInBackgroundGuarded() {
FileChannel source = null;
FileChannel dest = null;
try {
File input = new File(this.fromFile);
FileInputStream fileInputStream = new FileInputStream(input);
ParcelFileDescriptor pfd = weakContext.get().getContentResolver().openFileDescriptor(toFile, "w");
FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
source = fileInputStream.getChannel();
dest = fileOutputStream.getChannel();
dest.transferFrom(source, 0, source.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (source != null) {
try {
source.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dest != null) {
try {
dest.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecuteGuarded(Object o) {
}
}
}