diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index c531c9016..ac17a845a 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -17,6 +17,7 @@ import expo.modules.xmtpreactnativesdk.wrappers.DecodedMessageWrapper import expo.modules.xmtpreactnativesdk.wrappers.DecryptedLocalAttachment import expo.modules.xmtpreactnativesdk.wrappers.EncryptedLocalAttachment import expo.modules.xmtpreactnativesdk.wrappers.PreparedLocalMessage +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -126,6 +127,9 @@ class XMTPModule : Module() { private val isDebugEnabled = BuildConfig.DEBUG // TODO: consider making this configurable private val conversations: MutableMap = mutableMapOf() private val subscriptions: MutableMap = mutableMapOf() + private var preEnableIdentityCallbackDeferred: CompletableDeferred? = null + private var preCreateIdentityCallbackDeferred: CompletableDeferred? = null + override fun definition() = ModuleDefinition { Name("XMTP") @@ -151,6 +155,11 @@ class XMTPModule : Module() { logV("auth") val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address) signer = reactSigner + + if (hasCreateIdentityCallback == true) + preCreateIdentityCallbackDeferred = CompletableDeferred() + if (hasEnableIdentityCallback == true) + preEnableIdentityCallbackDeferred = CompletableDeferred() val preCreateIdentityCallback: PreEventCallback? = preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true } val preEnableIdentityCallback: PreEventCallback? = @@ -175,6 +184,11 @@ class XMTPModule : Module() { AsyncFunction("createRandom") { environment: String, appVersion: String?, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean? -> logV("createRandom") val privateKey = PrivateKeyBuilder() + + if (hasCreateIdentityCallback == true) + preCreateIdentityCallbackDeferred = CompletableDeferred() + if (hasEnableIdentityCallback == true) + preEnableIdentityCallbackDeferred = CompletableDeferred() val preCreateIdentityCallback: PreEventCallback? = preCreateIdentityCallback.takeIf { hasCreateIdentityCallback == true } val preEnableIdentityCallback: PreEventCallback? = @@ -590,6 +604,16 @@ class XMTPModule : Module() { val client = clients[clientAddress] ?: throw XMTPException("No client") client.contacts.consentList.entries.map { ConsentWrapper.encode(it.value) } } + + Function("preCreateIdentityCallbackCompleted") { + logV("preCreateIdentityCallbackCompleted") + preCreateIdentityCallbackDeferred?.complete(Unit) + } + + Function("preEnableIdentityCallbackCompleted") { + logV("preEnableIdentityCallbackCompleted") + preEnableIdentityCallbackDeferred?.complete(Unit) + } } // @@ -715,10 +739,14 @@ class XMTPModule : Module() { private val preEnableIdentityCallback: suspend () -> Unit = { sendEvent("preEnableIdentityCallback") + preEnableIdentityCallbackDeferred?.await() + preCreateIdentityCallbackDeferred == null } private val preCreateIdentityCallback: suspend () -> Unit = { sendEvent("preCreateIdentityCallback") + preCreateIdentityCallbackDeferred?.await() + preCreateIdentityCallbackDeferred = null } } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 8387ab56d..0c521997d 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -28,6 +28,8 @@ public class XMTPModule: Module { let clientsManager = ClientsManager() let conversationsManager = IsolatedManager() let subscriptionsManager = IsolatedManager>() + private var preEnableIdentityCallbackDeferred: DispatchSemaphore? + private var preCreateIdentityCallbackDeferred: DispatchSemaphore? actor ClientsManager { private var clients: [String: XMTP.Client] = [:] @@ -67,6 +69,12 @@ public class XMTPModule: Module { AsyncFunction("auth") { (address: String, environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) in let signer = ReactNativeSigner(module: self, address: address) self.signer = signer + if(hasCreateIdentityCallback ?? false) { + preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0) + } + if(hasEnableIdentityCallback ?? false) { + preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0) + } let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil let options = createClientConfig(env: environment, appVersion: appVersion, preEnableIdentityCallback: preEnableIdentityCallback, preCreateIdentityCallback: preCreateIdentityCallback) @@ -82,6 +90,12 @@ public class XMTPModule: Module { // Generate a random wallet and set the client to that AsyncFunction("createRandom") { (environment: String, appVersion: String?, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?) -> String in let privateKey = try PrivateKey.generate() + if(hasCreateIdentityCallback ?? false) { + preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0) + } + if(hasEnableIdentityCallback ?? false) { + preEnableIdentityCallbackDeferred = DispatchSemaphore(value: 0) + } let preCreateIdentityCallback: PreEventCallback? = hasCreateIdentityCallback ?? false ? self.preCreateIdentityCallback : nil let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil @@ -534,6 +548,18 @@ public class XMTPModule: Module { try ConsentWrapper.encode(entry.value) } } + + Function("preEnableIdentityCallbackCompleted") { + DispatchQueue.global().async { + self.preEnableIdentityCallbackDeferred?.signal() + } + } + + Function("preCreateIdentityCallbackCompleted") { + DispatchQueue.global().async { + self.preCreateIdentityCallbackDeferred?.signal() + } + } } // @@ -673,9 +699,13 @@ public class XMTPModule: Module { func preEnableIdentityCallback() { sendEvent("preEnableIdentityCallback") + self.preEnableIdentityCallbackDeferred?.wait() + self.preCreateIdentityCallbackDeferred = nil } func preCreateIdentityCallback() { sendEvent("preCreateIdentityCallback") + self.preCreateIdentityCallbackDeferred?.wait() + self.preEnableIdentityCallbackDeferred = nil } } diff --git a/src/index.ts b/src/index.ts index 5e324ad8b..80c8a5834 100644 --- a/src/index.ts +++ b/src/index.ts @@ -393,6 +393,14 @@ export async function consentList( }) } +export function preEnableIdentityCallbackCompleted() { + XMTPModule.preEnableIdentityCallbackCompleted() +} + +export function preCreateIdentityCallbackCompleted() { + XMTPModule.preCreateIdentityCallbackCompleted() +} + export const emitter = new EventEmitter(XMTPModule ?? NativeModulesProxy.XMTP) export * from './lib/ContentCodec' diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 745e333b2..8ea8b96b5 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -236,6 +236,7 @@ export class Client { opts, async () => { await this.executeCallback(opts?.preEnableIdentityCallback) + XMTPModule.preEnableIdentityCallbackCompleted() } ) @@ -244,6 +245,7 @@ export class Client { opts, async () => { await this.executeCallback(opts?.preCreateIdentityCallback) + XMTPModule.preCreateIdentityCallbackCompleted() } )