package com.mattermost.share; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.Arguments; import com.mattermost.helpers.Credentials; import com.mattermost.rnbeta.MainApplication; import com.mattermost.helpers.RealPathUtil; import android.app.Activity; import android.content.Intent; import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.io.File; import java.util.ArrayList; import org.json.JSONArray; import org.json.JSONObject; import org.json.JSONException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.MultipartBody; import okhttp3.RequestBody; import okhttp3.Response; public class ShareModule extends ReactContextBaseJavaModule { private final OkHttpClient client = new OkHttpClient(); public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); private static ShareModule instance; private final MainApplication mApplication; private ReactApplicationContext mReactContext; private File tempFolder; private ShareModule(ReactApplicationContext reactContext) { super(reactContext); mReactContext = reactContext; mApplication = (MainApplication)reactContext.getApplicationContext(); } public static ShareModule getInstance(ReactApplicationContext reactContext) { if (instance == null) { instance = new ShareModule(reactContext); } else { instance.mReactContext = reactContext; } return instance; } public static ShareModule getInstance() { return instance; } @NonNull @Override public String getName() { return "MattermostShare"; } @ReactMethod(isBlockingSynchronousMethod = true) public String getCurrentActivityName() { Activity currentActivity = getCurrentActivity(); if (currentActivity != null) { String actvName = currentActivity.getComponentName().getClassName(); String[] components = actvName.split("\\."); return components[components.length - 1]; } return ""; } @ReactMethod public void clear() { Activity currentActivity = getCurrentActivity(); if (currentActivity != null && this.getCurrentActivityName().equals("ShareActivity")) { Intent intent = currentActivity.getIntent(); intent.setAction(""); intent.removeExtra(Intent.EXTRA_TEXT); intent.removeExtra(Intent.EXTRA_STREAM); } } @Nullable @Override public Map getConstants() { HashMap constants = new HashMap<>(1); constants.put("cacheDirName", RealPathUtil.CACHE_DIR_NAME); constants.put("isOpened", mApplication.sharedExtensionIsOpened); return constants; } @ReactMethod public void close(ReadableMap data) { this.clear(); Activity currentActivity = getCurrentActivity(); if (currentActivity == null || !this.getCurrentActivityName().equals("ShareActivity")) { return; } currentActivity.finishAndRemoveTask(); if (data != null && data.hasKey("serverUrl")) { ReadableArray files = data.getArray("files"); String serverUrl = data.getString("serverUrl"); final String token = Credentials.getCredentialsForServerSync(this.getReactApplicationContext(), serverUrl); JSONObject postData = buildPostObject(data); if (files != null && files.size() > 0) { uploadFiles(serverUrl, token, files, postData); } else { try { post(serverUrl, token, postData); } catch (IOException e) { e.printStackTrace(); } } } mApplication.sharedExtensionIsOpened = false; RealPathUtil.deleteTempFiles(this.tempFolder); } @ReactMethod public void getSharedData(Promise promise) { promise.resolve(processIntent()); } public WritableArray processIntent() { String type, action, extra; WritableArray items = Arguments.createArray(); Activity currentActivity = getCurrentActivity(); if (currentActivity != null) { this.tempFolder = new File(currentActivity.getCacheDir(), RealPathUtil.CACHE_DIR_NAME); Intent intent = currentActivity.getIntent(); action = intent.getAction(); type = intent.getType(); extra = intent.getStringExtra(Intent.EXTRA_TEXT); if (Intent.ACTION_SEND.equals(action) && "text/plain".equals(type) && extra != null) { items.pushMap(ShareUtils.getTextItem(extra)); } else if (Intent.ACTION_SEND.equals(action)) { if (extra != null) { items.pushMap(ShareUtils.getTextItem(extra)); } Uri uri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (uri != null) { ReadableMap fileInfo = ShareUtils.getFileItem(currentActivity, uri); if (fileInfo != null) { items.pushMap(fileInfo); } } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { if (extra != null) { items.pushMap(ShareUtils.getTextItem(extra)); } ArrayList uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); for (Uri uri : uris) { ReadableMap fileInfo = ShareUtils.getFileItem(currentActivity, uri); if (fileInfo != null) { items.pushMap(fileInfo); } } } } return items; } private JSONObject buildPostObject(ReadableMap data) { JSONObject json = new JSONObject(); try { json.put("user_id", data.getString("userId")); if (data.hasKey("channelId")) { json.put("channel_id", data.getString("channelId")); } if (data.hasKey("message")) { json.put("message", data.getString("message")); } } catch (JSONException e) { e.printStackTrace(); } return json; } private void post(String serverUrl, String token, JSONObject postData) throws IOException { RequestBody body = RequestBody.create(postData.toString(), JSON); Request request = new Request.Builder() .header("Authorization", "BEARER " + token) .url(serverUrl + "/api/v4/posts") .post(body) .build(); client.newCall(request).execute(); } private void uploadFiles(String serverUrl, String token, ReadableArray files, JSONObject postData) { try { MultipartBody.Builder builder = new MultipartBody.Builder() .setType(MultipartBody.FORM); for(int i = 0 ; i < files.size() ; i++) { ReadableMap file = files.getMap(i); String mime = file.getString("type"); String fullPath = file.getString("value"); if (fullPath != null) { String filePath = fullPath.replaceFirst("file://", ""); File fileInfo = new File(filePath); if (fileInfo.exists() && mime != null) { final MediaType MEDIA_TYPE = MediaType.parse(mime); builder.addFormDataPart("files", file.getString("filename"), RequestBody.create(fileInfo, MEDIA_TYPE)); } } } builder.addFormDataPart("channel_id", postData.getString("channel_id")); RequestBody body = builder.build(); Request request = new Request.Builder() .header("Authorization", "BEARER " + token) .url(serverUrl + "/api/v4/files") .post(body) .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { String responseData = response.body().string(); JSONObject responseJson = new JSONObject(responseData); JSONArray fileInfoArray = responseJson.getJSONArray("file_infos"); JSONArray file_ids = new JSONArray(); for(int i = 0 ; i < fileInfoArray.length() ; i++) { JSONObject fileInfo = fileInfoArray.getJSONObject(i); file_ids.put(fileInfo.getString("id")); } postData.put("file_ids", file_ids); post(serverUrl, token, postData); } } catch (IOException e) { e.printStackTrace(); } } catch (JSONException e) { e.printStackTrace(); } } }