Migrate FileReaderModule to kotlin (#50562)

Summary:
This PR aims to migrate FileReaderModule from Java to kotlin as part of https://github.com/facebook/react-native/issues/50513

## Changelog:

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
[ANDROID][CHANGED]Migrate FileReaderModule to Kotlin

Pull Request resolved: https://github.com/facebook/react-native/pull/50562

Test Plan: Tested on RN tester with both new and old arch

Reviewed By: arushikesarwani94

Differential Revision: D72726333

Pulled By: cortinico

fbshipit-source-id: 130393373a258f18f8baaa96745da8fdebd62436
This commit is contained in:
Devansh Saini
2025-04-10 02:55:06 -07:00
committed by Facebook GitHub Bot
parent f21e61f4c5
commit 07a1fb8e6b
3 changed files with 105 additions and 119 deletions
@@ -2676,12 +2676,17 @@ public final class com/facebook/react/modules/blob/BlobProvider : android/conten
public fun update (Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
}
public class com/facebook/react/modules/blob/FileReaderModule : com/facebook/fbreact/specs/NativeFileReaderModuleSpec {
public final class com/facebook/react/modules/blob/FileReaderModule : com/facebook/fbreact/specs/NativeFileReaderModuleSpec {
public static final field Companion Lcom/facebook/react/modules/blob/FileReaderModule$Companion;
public fun <init> (Lcom/facebook/react/bridge/ReactApplicationContext;)V
public fun readAsDataURL (Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Promise;)V
public fun readAsText (Lcom/facebook/react/bridge/ReadableMap;Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V
}
public final class com/facebook/react/modules/blob/FileReaderModule$Companion {
public final fun getNAME ()Ljava/lang/String;
}
public final class com/facebook/react/modules/common/ModuleDataCleaner {
public static final field INSTANCE Lcom/facebook/react/modules/common/ModuleDataCleaner;
public static final fun cleanDataFromModules (Lcom/facebook/react/bridge/ReactContext;)V
@@ -1,118 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.blob;
import android.util.Base64;
import androidx.annotation.Nullable;
import com.facebook.fbreact.specs.NativeFileReaderModuleSpec;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.module.annotations.ReactModule;
@Nullsafe(Nullsafe.Mode.LOCAL)
@ReactModule(name = NativeFileReaderModuleSpec.NAME)
public class FileReaderModule extends NativeFileReaderModuleSpec {
private static final String ERROR_INVALID_BLOB = "ERROR_INVALID_BLOB";
public FileReaderModule(ReactApplicationContext reactContext) {
super(reactContext);
}
private @Nullable BlobModule getBlobModule(String reason) {
ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn();
if (reactApplicationContext != null) {
return reactApplicationContext.getNativeModule(BlobModule.class);
}
return null;
}
@Override
public void readAsText(ReadableMap blob, String encoding, Promise promise) {
BlobModule blobModule = getBlobModule("readAsText");
if (blobModule == null) {
promise.reject(
new IllegalStateException("Could not get BlobModule from ReactApplicationContext"));
return;
} else if (blob == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is null");
return;
}
String blobId = blob.getString("blobId");
if (blobId == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob does not contain a blobId");
return;
}
byte[] bytes = blobModule.resolve(blobId, blob.getInt("offset"), blob.getInt("size"));
if (bytes == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is invalid");
return;
}
try {
promise.resolve(new String(bytes, encoding));
} catch (Exception e) {
promise.reject(e);
}
}
@Override
public void readAsDataURL(ReadableMap blob, Promise promise) {
BlobModule blobModule = getBlobModule("readAsDataURL");
if (blobModule == null) {
promise.reject(
new IllegalStateException("Could not get BlobModule from ReactApplicationContext"));
return;
} else if (blob == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is null");
return;
}
String blobId = blob.getString("blobId");
if (blobId == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob does not contain a blobId");
return;
}
byte[] bytes = blobModule.resolve(blobId, blob.getInt("offset"), blob.getInt("size"));
if (bytes == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is invalid");
return;
}
try {
StringBuilder sb = new StringBuilder();
sb.append("data:");
if (blob.hasKey("type")
&& blob.getString("type") != null
&& !blob.getString("type").isEmpty()) {
sb.append(blob.getString("type"));
} else {
sb.append("application/octet-stream");
}
sb.append(";base64,");
sb.append(Base64.encodeToString(bytes, Base64.NO_WRAP));
promise.resolve(sb.toString());
} catch (Exception e) {
promise.reject(e);
}
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.blob
import android.util.Base64
import com.facebook.fbreact.specs.NativeFileReaderModuleSpec
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.module.annotations.ReactModule
@ReactModule(name = NativeFileReaderModuleSpec.NAME)
public class FileReaderModule(reactContext: ReactApplicationContext) :
NativeFileReaderModuleSpec(reactContext) {
private fun getBlobModule(reason: String): BlobModule? {
val reactApplicationContext = getReactApplicationContextIfActiveOrWarn()
return reactApplicationContext?.getNativeModule(BlobModule::class.java)
}
public override fun readAsText(blob: ReadableMap, encoding: String, promise: Promise) {
val blobModule = getBlobModule("readAsText")
if (blobModule == null) {
promise.reject(IllegalStateException("Could not get BlobModule from ReactApplicationContext"))
return
}
val blobId = blob.getString("blobId")
if (blobId == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob does not contain a blobId")
return
}
val bytes = blobModule.resolve(blobId, blob.getInt("offset"), blob.getInt("size"))
if (bytes == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is invalid")
return
}
try {
promise.resolve(String(bytes, charset(encoding)))
} catch (e: Exception) {
promise.reject(e)
}
}
public override fun readAsDataURL(blob: ReadableMap, promise: Promise) {
val blobModule = getBlobModule("readAsDataURL")
if (blobModule == null) {
promise.reject(IllegalStateException("Could not get BlobModule from ReactApplicationContext"))
return
}
val blobId = blob.getString("blobId")
if (blobId == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob does not contain a blobId")
return
}
val bytes = blobModule.resolve(blobId, blob.getInt("offset"), blob.getInt("size"))
if (bytes == null) {
promise.reject(ERROR_INVALID_BLOB, "The specified blob is invalid")
return
}
try {
val sb = StringBuilder()
sb.append("data:")
if (blob.hasKey("type") && !blob.getString("type").isNullOrEmpty()) {
sb.append(blob.getString("type"))
} else {
sb.append("application/octet-stream")
}
sb.append(";base64,")
sb.append(Base64.encodeToString(bytes, Base64.NO_WRAP))
promise.resolve(sb.toString())
} catch (e: Exception) {
promise.reject(e)
}
}
public companion object {
public val NAME: String = NativeFileReaderModuleSpec.NAME
private const val ERROR_INVALID_BLOB = "ERROR_INVALID_BLOB"
}
}