Changeset View
Standalone View
native/expo-modules/comm-expo-package/android/src/main/java/app/comm/android/utils/BlobUtilsModule.kt
- This file was added.
package app.comm.android.utils | |||||
import com.facebook.react.bridge.ReactApplicationContext | |||||
import com.facebook.react.modules.blob.BlobModule | |||||
import expo.modules.kotlin.exception.CodedException | |||||
import expo.modules.kotlin.modules.Module | |||||
import expo.modules.kotlin.modules.ModuleDefinition | |||||
import expo.modules.kotlin.records.Field | |||||
import expo.modules.kotlin.records.Record | |||||
import expo.modules.kotlin.records.Required | |||||
import expo.modules.kotlin.typedarray.TypedArray | |||||
import expo.modules.kotlin.typedarray.Uint8Array | |||||
// This type corresponds to the BlobData interface in react-native | |||||
class BlobMetadata: Record { | |||||
@Required @Field val blobId: String = "" | |||||
atul: Same nit as iOS version of this diff, we would usually name this `blobID` instead of `blobId`. | |||||
@Required @Field val size: Int = -1 | |||||
@Required @Field val offset: Int = 0 | |||||
} | |||||
class BlobUtilsModule : Module() { | |||||
override fun definition() = ModuleDefinition { | |||||
Name("BlobUtils") | |||||
Function("copyBlobToTypedArray") { blob: BlobMetadata, | |||||
marcinUnsubmitted Not Done Inline ActionsAre those methods async when used in JS? If not can we make them so? I recall from Java and Objective-C that it wasn't always the caseThis module appears to be a general purpose tool so it should support ability to process many independent blobs at once. marcin: Are those methods `async` when used in JS? If not can we make them so? I recall from Java and… | |||||
marcinUnsubmitted Not Done Inline ActionsAlso applies to the child diff where the usage of those methods suggests that they are not async. marcin: Also applies to the child diff where the usage of those methods suggests that they are not… | |||||
bartekAuthorUnsubmitted Done Inline ActionsThey're synchronous. Unfortunately, Typed arrays aren't supported yet in async expo-module functions. The problem is that arraybuffer/typedArray operations must be performed on the JS thread. In this particular case, I'd argue that these should be async because it's only pointer logic here + one copy operation (for contiguous memory) so they should be fast. Anyway, at this moment we can't do much about it (except using C++ and JSI which is more effort than it's worth) bartek: They're synchronous. Unfortunately, Typed arrays aren't supported yet in async expo-module… | |||||
destination: Uint8Array -> | |||||
val blobBytes = blobManager.resolve(blob.blobId, blob.offset, blob.size) | |||||
?: throw NoSuchBlobException(blob.blobId) | |||||
destination.write(blobBytes, 0, blob.size) | |||||
} | |||||
Function("blobFromTypedArray") { source: TypedArray -> | |||||
val bytes = ByteArray(source.byteLength).also { | |||||
source.read(it, 0, source.byteLength) | |||||
} | |||||
val blobId = blobManager.store(bytes) | |||||
?: throw BlobCreationFailedException() | |||||
return@Function blobId | |||||
} | |||||
} | |||||
private val reactContext | |||||
get() = requireNotNull( | |||||
this.appContext.reactContext as? ReactApplicationContext | |||||
) { "React context is null or is not a ReactApplicationContext" } | |||||
private val blobManager: BlobModule | |||||
get() = requireNotNull( | |||||
this.reactContext.getNativeModule(BlobModule::class.java) | |||||
) { "Couldn't load react-native's BlobModule" } | |||||
} | |||||
// region Exception definitions | |||||
private class NoSuchBlobException(blobId: String) : | |||||
CodedException("No blob data found for blob id=$blobId") | |||||
private class BlobCreationFailedException : | |||||
CodedException("Failed to store blob") | |||||
// endregion |
Same nit as iOS version of this diff, we would usually name this blobID instead of blobId.