react-native-smallcase-gateway 5.3.2 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/reactnativesmallcasegateway/SCGatewayBridgeEmitter.kt +112 -0
- package/android/src/main/java/com/reactnativesmallcasegateway/SCLoansBridgeEmitter.kt +117 -0
- package/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayModule.kt +0 -5
- package/android/src/main/java/com/reactnativesmallcasegateway/SmallcaseGatewayPackage.kt +5 -1
- package/ios/SCGatewayBridgeEmitter.m +20 -0
- package/ios/SCGatewayEmitter.swift +117 -0
- package/ios/SCLoansBridgeEmitter.m +20 -0
- package/ios/SCLoansEmitter.swift +115 -0
- package/ios/SmallcaseGateway-Bridging-Header.h +7 -0
- package/lib/commonjs/SCGatewayEventEmitter.js +107 -0
- package/lib/commonjs/SCGatewayEventEmitter.js.map +1 -0
- package/lib/commonjs/SCLoansEventEmitter.js +103 -0
- package/lib/commonjs/SCLoansEventEmitter.js.map +1 -0
- package/lib/commonjs/SmallcaseGateway.js.map +1 -1
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/SCGatewayEventEmitter.js +102 -0
- package/lib/module/SCGatewayEventEmitter.js.map +1 -0
- package/lib/module/SCLoansEventEmitter.js +98 -0
- package/lib/module/SCLoansEventEmitter.js.map +1 -0
- package/lib/module/SmallcaseGateway.js.map +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/package.json +1 -1
- package/react-native-smallcase-gateway.podspec +2 -2
- package/src/SCGatewayEventEmitter.js +121 -0
- package/src/SCLoansEventEmitter.js +116 -0
- package/src/SmallcaseGateway.js +1 -1
- package/src/index.js +3 -1
- package/types/index.d.ts +45 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [6.0.0](https://github.com/smallcase/react-native-smallcase-gateway/compare/v5.2.0...v6.0.0) (2025-11-20)
|
|
6
|
+
|
|
7
|
+
### [5.0.2-rc.3](https://github.com/smallcase/react-native-smallcase-gateway/compare/v5.0.2-rc.2...v5.0.2-rc.3) (2025-07-22)
|
|
8
|
+
|
|
5
9
|
### [5.3.2](https://github.com/smallcase/react-native-smallcase-gateway/compare/v5.3.1...v5.3.2) (2025-11-13)
|
|
6
10
|
|
|
7
11
|
### [5.3.1](https://github.com/smallcase/react-native-smallcase-gateway/compare/v5.2.0...v5.3.1) (2025-10-28)
|
package/android/build.gradle
CHANGED
|
@@ -149,8 +149,8 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
|
|
|
149
149
|
dependencies {
|
|
150
150
|
//noinspection GradleDynamicVersion
|
|
151
151
|
implementation 'com.facebook.react:react-native:+' // From node_modules
|
|
152
|
-
implementation 'com.smallcase.gateway:sdk:
|
|
153
|
-
implementation 'com.smallcase.loans:sdk:
|
|
152
|
+
implementation 'com.smallcase.gateway:sdk:5.0.0'
|
|
153
|
+
implementation 'com.smallcase.loans:sdk:4.0.0'
|
|
154
154
|
implementation "androidx.core:core-ktx:1.3.1"
|
|
155
155
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
|
156
156
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
|
|
2
|
+
// SCGatewayBridgeEmitter.kt
|
|
3
|
+
package com.reactnativesmallcasegateway
|
|
4
|
+
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.facebook.react.bridge.*
|
|
7
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
8
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
9
|
+
import com.smallcase.gateway.data.listeners.Notification
|
|
10
|
+
import com.smallcase.gateway.data.listeners.NotificationCenter
|
|
11
|
+
import com.smallcase.gateway.portal.ScgNotification
|
|
12
|
+
import com.smallcase.gateway.portal.SmallcaseGatewaySdk
|
|
13
|
+
|
|
14
|
+
class SCGatewayBridgeEmitter(private val reactContext: ReactApplicationContext) :
|
|
15
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
16
|
+
|
|
17
|
+
companion object {
|
|
18
|
+
const val TAG = "SCGatewayBridgeEmitter"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private var notificationObserver: ((Notification) -> Unit)? = null
|
|
22
|
+
|
|
23
|
+
private val isListening: Boolean
|
|
24
|
+
get() = notificationObserver != null
|
|
25
|
+
|
|
26
|
+
init {
|
|
27
|
+
UiThreadUtil.runOnUiThread { startListening() }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override fun getName(): String = "SCGatewayBridgeEmitter"
|
|
31
|
+
|
|
32
|
+
override fun onCatalystInstanceDestroy() {
|
|
33
|
+
super.onCatalystInstanceDestroy()
|
|
34
|
+
if (isListening) {
|
|
35
|
+
notificationObserver?.let { observer ->
|
|
36
|
+
NotificationCenter.removeObserver(observer)
|
|
37
|
+
}
|
|
38
|
+
notificationObserver = null
|
|
39
|
+
Log.d(TAG, "Successfully cleaned up notification observer")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@ReactMethod
|
|
44
|
+
fun startListening(promise: Promise? = null) {
|
|
45
|
+
Log.d(TAG, "startListening called")
|
|
46
|
+
|
|
47
|
+
if (isListening) {
|
|
48
|
+
Log.d(TAG, "Already listening to events")
|
|
49
|
+
promise?.resolve("Already listening")
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
UiThreadUtil.runOnUiThread {
|
|
54
|
+
Log.d(TAG, "Starting listener on thread: ${Thread.currentThread().name}")
|
|
55
|
+
|
|
56
|
+
notificationObserver = { notification ->
|
|
57
|
+
Log.d(TAG, "Received notification: ${notification.name}")
|
|
58
|
+
processScgNotification(notification)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
notificationObserver?.let { observer ->
|
|
62
|
+
NotificationCenter.addObserver(observer)
|
|
63
|
+
Log.d(TAG, "Successfully started listening for notifications")
|
|
64
|
+
promise?.resolve("Started listening successfully")
|
|
65
|
+
} ?: run {
|
|
66
|
+
promise?.reject("START_LISTENING_ERROR", "Failed to create observer")
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@ReactMethod
|
|
72
|
+
fun stopListening(promise: Promise) {
|
|
73
|
+
if (!isListening) {
|
|
74
|
+
promise.resolve("Not listening")
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
UiThreadUtil.runOnUiThread {
|
|
79
|
+
notificationObserver?.let { observer ->
|
|
80
|
+
NotificationCenter.removeObserver(observer)
|
|
81
|
+
notificationObserver = null
|
|
82
|
+
promise.resolve("Stopped listening successfully")
|
|
83
|
+
} ?: run {
|
|
84
|
+
promise.resolve("No observer to remove")
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private fun processScgNotification(notification: Notification) {
|
|
90
|
+
val jsonString = notification.userInfo?.get(ScgNotification.STRINGIFIED_PAYLOAD_KEY) as? String
|
|
91
|
+
if (jsonString == null) {
|
|
92
|
+
Log.e(TAG, "SCGatewayBridgeEmitter: Invalid notification object - expected JSON string")
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
sendEvent(SmallcaseGatewaySdk.SCG_NOTIFICATION_NAME, jsonString)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private fun sendEvent(eventName: String, jsonString: String) {
|
|
100
|
+
try {
|
|
101
|
+
if (reactContext.hasActiveCatalystInstance()) {
|
|
102
|
+
reactContext
|
|
103
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
104
|
+
.emit(eventName, jsonString)
|
|
105
|
+
} else {
|
|
106
|
+
Log.w(TAG, "React context not active, cannot send event: $eventName")
|
|
107
|
+
}
|
|
108
|
+
} catch (e: Exception) {
|
|
109
|
+
Log.e(TAG, "Failed to send event: $eventName", e)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// SCLoansBridgeEmitter.kt
|
|
2
|
+
package com.reactnativesmallcasegateway
|
|
3
|
+
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.bridge.*
|
|
6
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
7
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
8
|
+
import com.smallcase.loans.core.external.ScLoan
|
|
9
|
+
import com.smallcase.loans.core.external.ScLoanNotification
|
|
10
|
+
import com.smallcase.loans.data.listeners.Notification
|
|
11
|
+
import com.smallcase.loans.data.listeners.NotificationCenter
|
|
12
|
+
|
|
13
|
+
class SCLoansBridgeEmitter(private val reactContext: ReactApplicationContext):
|
|
14
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
15
|
+
|
|
16
|
+
companion object {
|
|
17
|
+
const val TAG = "SCLoansBridgeEmitter"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private var notificationObserver: ((Notification) -> Unit)? = null
|
|
21
|
+
|
|
22
|
+
private val isListening: Boolean
|
|
23
|
+
get() = notificationObserver != null
|
|
24
|
+
|
|
25
|
+
init {
|
|
26
|
+
UiThreadUtil.runOnUiThread {
|
|
27
|
+
startListening()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun getName(): String = "SCLoansBridgeEmitter"
|
|
32
|
+
|
|
33
|
+
override fun onCatalystInstanceDestroy() {
|
|
34
|
+
super.onCatalystInstanceDestroy()
|
|
35
|
+
if (isListening) {
|
|
36
|
+
notificationObserver?.let { observer ->
|
|
37
|
+
NotificationCenter.removeObserver(observer)
|
|
38
|
+
}
|
|
39
|
+
notificationObserver = null
|
|
40
|
+
Log.d(TAG, "Successfully cleaned up notification observer")
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@ReactMethod
|
|
45
|
+
fun startListening(promise: Promise ? = null) {
|
|
46
|
+
Log.d(TAG, "startListening called")
|
|
47
|
+
|
|
48
|
+
if (isListening) {
|
|
49
|
+
Log.d(TAG, "Already listening to events")
|
|
50
|
+
promise?.resolve("Already listening")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
UiThreadUtil.runOnUiThread {
|
|
55
|
+
Log.d(TAG, "Starting listener on thread: ${Thread.currentThread().name}")
|
|
56
|
+
|
|
57
|
+
notificationObserver = { notification ->
|
|
58
|
+
Log.d(TAG, "Received notification: ${notification.name}")
|
|
59
|
+
processScLoansNotification(notification)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
notificationObserver?.let { observer ->
|
|
63
|
+
NotificationCenter.addObserver(observer)
|
|
64
|
+
Log.d(TAG, "Successfully started listening for notifications")
|
|
65
|
+
promise?.resolve("Started listening successfully")
|
|
66
|
+
} ?: run {
|
|
67
|
+
promise?.reject("START_LISTENING_ERROR", "Failed to create observer")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@ReactMethod
|
|
73
|
+
fun stopListening(promise: Promise) {
|
|
74
|
+
if (!isListening) {
|
|
75
|
+
promise.resolve("Not listening")
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
UiThreadUtil.runOnUiThread {
|
|
80
|
+
notificationObserver?.let { observer ->
|
|
81
|
+
NotificationCenter.removeObserver(observer)
|
|
82
|
+
notificationObserver = null
|
|
83
|
+
promise.resolve("Stopped listening successfully")
|
|
84
|
+
} ?: run {
|
|
85
|
+
promise.resolve("No observer to remove")
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private fun processScLoansNotification(notification: Notification) {
|
|
91
|
+
val jsonString =
|
|
92
|
+
notification.userInfo?.get(ScLoanNotification.STRINGIFIED_PAYLOAD_KEY) as? String
|
|
93
|
+
if (jsonString == null) {
|
|
94
|
+
Log.e(
|
|
95
|
+
TAG,
|
|
96
|
+
"SCLoansBridgeEmitter: Invalid notification object - expected JSON string"
|
|
97
|
+
)
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
sendEvent(ScLoan.SCLOANS_NOTIFICATION_NAME, jsonString)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private fun sendEvent(eventName: String, jsonString: String) {
|
|
105
|
+
try {
|
|
106
|
+
if (reactContext.hasActiveCatalystInstance()) {
|
|
107
|
+
reactContext
|
|
108
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
109
|
+
.emit(eventName, jsonString)
|
|
110
|
+
} else {
|
|
111
|
+
Log.w(TAG, "React context not active, cannot send event: $eventName")
|
|
112
|
+
}
|
|
113
|
+
} catch (e: Exception) {
|
|
114
|
+
Log.e(TAG, "Failed to send event: $eventName", e)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -67,7 +67,6 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
|
|
|
67
67
|
|
|
68
68
|
@ReactMethod
|
|
69
69
|
fun init(sdkToken: String, promise: Promise) {
|
|
70
|
-
Log.d(TAG, "init: start")
|
|
71
70
|
|
|
72
71
|
val initReq = InitRequest(sdkToken)
|
|
73
72
|
SmallcaseGatewaySdk.init(authRequest = initReq, gatewayInitialisationListener = object : DataListener<InitialisationResponse> {
|
|
@@ -85,7 +84,6 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
|
|
|
85
84
|
|
|
86
85
|
@ReactMethod
|
|
87
86
|
fun triggerTransaction(transactionId: String, utmParams: ReadableMap?, brokerList: ReadableArray?, promise: Promise) {
|
|
88
|
-
Log.d(TAG, "triggerTransaction: start")
|
|
89
87
|
|
|
90
88
|
var safeBrokerList = listOf<String>()
|
|
91
89
|
|
|
@@ -161,7 +159,6 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
|
|
|
161
159
|
|
|
162
160
|
@ReactMethod
|
|
163
161
|
fun launchSmallplug(targetEndpoint: String, params: String, promise: Promise) {
|
|
164
|
-
Log.d(TAG, "launchSmallplug: start")
|
|
165
162
|
|
|
166
163
|
SmallcaseGatewaySdk.launchSmallPlug(currentActivity!!, SmallplugData(targetEndpoint, params), object : SmallPlugResponseListener {
|
|
167
164
|
override fun onFailure(errorCode: Int, errorMessage: String) {
|
|
@@ -198,7 +195,6 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
|
|
|
198
195
|
}
|
|
199
196
|
}
|
|
200
197
|
}
|
|
201
|
-
Log.d(TAG, "launchSmallplugWithBranding: start")
|
|
202
198
|
|
|
203
199
|
var partnerProps: SmallplugPartnerProps? = SmallplugPartnerProps(headerColor = "#2F363F", backIconColor = "ffffff")
|
|
204
200
|
|
|
@@ -228,7 +224,6 @@ class SmallcaseGatewayModule(reactContext: ReactApplicationContext) : ReactConte
|
|
|
228
224
|
|
|
229
225
|
@ReactMethod
|
|
230
226
|
fun archiveSmallcase(iscid: String, promise: Promise) {
|
|
231
|
-
Log.d(TAG, "markSmallcaseArchive: start")
|
|
232
227
|
|
|
233
228
|
SmallcaseGatewaySdk.markSmallcaseArchived(iscid, object : DataListener<SmallcaseGatewayDataResponse> {
|
|
234
229
|
|
|
@@ -7,7 +7,11 @@ import com.facebook.react.uimanager.ViewManager
|
|
|
7
7
|
|
|
8
8
|
class SmallcaseGatewayPackage : ReactPackage {
|
|
9
9
|
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
-
return listOf(
|
|
10
|
+
return listOf(
|
|
11
|
+
SmallcaseGatewayModule(reactContext),
|
|
12
|
+
SCGatewayBridgeEmitter(reactContext),
|
|
13
|
+
SCLoansBridgeEmitter(reactContext)
|
|
14
|
+
)
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SCGatewayBridgeEmitter.m
|
|
3
|
+
// SCGateway
|
|
4
|
+
//
|
|
5
|
+
// Created by Dhruv Porwal
|
|
6
|
+
// Copyright © 2025 smallcase. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import <React/RCTBridgeModule.h>
|
|
10
|
+
#import "SmallcaseGateway-Bridging-Header.h"
|
|
11
|
+
|
|
12
|
+
@interface RCT_EXTERN_REMAP_MODULE(SCGatewayBridgeEmitter, SCGatewayEmitter, NSObject)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(startListening:(RCTPromiseResolveBlock)resolve
|
|
15
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
16
|
+
|
|
17
|
+
RCT_EXTERN_METHOD(stopListening:(RCTPromiseResolveBlock)resolve
|
|
18
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
19
|
+
|
|
20
|
+
@end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import SCGateway
|
|
4
|
+
|
|
5
|
+
@objc(SCGatewayEmitter)
|
|
6
|
+
class SCGatewayEmitter: RCTEventEmitter {
|
|
7
|
+
|
|
8
|
+
private static var shared: SCGatewayEmitter?
|
|
9
|
+
|
|
10
|
+
private var notificationObserver: NSObjectProtocol?
|
|
11
|
+
|
|
12
|
+
private var isListening: Bool {
|
|
13
|
+
return notificationObserver != nil
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
SCGatewayEmitter.shared = self
|
|
19
|
+
print("SCGatewayEmitter: Initialized.")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
deinit {
|
|
23
|
+
print("SCGatewayEmitter: Deinitializing.")
|
|
24
|
+
stopListening()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
override func supportedEvents() -> [String]! {
|
|
28
|
+
return [SCGateway.scgNotificationName.rawValue]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override func startObserving() {
|
|
32
|
+
super.startObserving()
|
|
33
|
+
print("SCGatewayEmitter: React Native bridge startObserving called.")
|
|
34
|
+
startListening()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
override func stopObserving() {
|
|
38
|
+
super.stopObserving()
|
|
39
|
+
print("SCGatewayEmitter: React Native bridge stopObserving called.")
|
|
40
|
+
stopListening()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@objc func startListening(
|
|
48
|
+
_ resolve: RCTPromiseResolveBlock? = nil,
|
|
49
|
+
rejecter reject: RCTPromiseRejectBlock? = nil
|
|
50
|
+
) {
|
|
51
|
+
print("SCGatewayEmitter: Starting to listen for notifications.")
|
|
52
|
+
|
|
53
|
+
guard !isListening else {
|
|
54
|
+
print("SCGatewayEmitter: Already listening, no action needed.")
|
|
55
|
+
resolve?("Already listening")
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
DispatchQueue.main.async { [weak self] in
|
|
60
|
+
guard let self = self else {
|
|
61
|
+
reject?("START_LISTENING_FAILED", "Self deallocated", nil)
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
self.stopListening()
|
|
66
|
+
|
|
67
|
+
self.notificationObserver = NotificationCenter.default.addObserver(
|
|
68
|
+
forName: SCGateway.scgNotificationName,
|
|
69
|
+
object: nil,
|
|
70
|
+
queue: .main
|
|
71
|
+
) { [weak self] notification in
|
|
72
|
+
self?.processScgNotification(notification)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
print(
|
|
76
|
+
"SCGatewayEmitter: Started listening to notifications with name: \(SCGateway.scgNotificationName.rawValue)."
|
|
77
|
+
)
|
|
78
|
+
resolve?("Started listening to SCGateway events")
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@objc func stopListening(
|
|
83
|
+
_ resolve: RCTPromiseResolveBlock? = nil,
|
|
84
|
+
rejecter reject: RCTPromiseRejectBlock? = nil
|
|
85
|
+
) {
|
|
86
|
+
print("SCGatewayEmitter: Stopping listening for notifications.")
|
|
87
|
+
|
|
88
|
+
guard isListening, let observer = notificationObserver else {
|
|
89
|
+
print("SCGatewayEmitter: Not listening or no observer, no action needed.")
|
|
90
|
+
resolve?("Not listening")
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
NotificationCenter.default.removeObserver(observer)
|
|
95
|
+
notificationObserver = nil
|
|
96
|
+
|
|
97
|
+
print("SCGatewayEmitter: Stopped listening to notifications.")
|
|
98
|
+
resolve?("Stopped listening to SCGateway events")
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private func processScgNotification(_ notification: Notification) {
|
|
102
|
+
let userInfo = notification.userInfo ?? [:]
|
|
103
|
+
|
|
104
|
+
print("SCGatewayEmitter: Received notification with userInfo keys: \(userInfo.keys)")
|
|
105
|
+
|
|
106
|
+
guard let jsonString = userInfo[SCGNotification.strigifiedPayloadKey] as? String else {
|
|
107
|
+
print(
|
|
108
|
+
"SCGatewayEmitter: No stringified payload found with key '\(SCGNotification.strigifiedPayloadKey)'"
|
|
109
|
+
)
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
print("SCGatewayEmitter: Received JSON string: \(jsonString).")
|
|
114
|
+
sendEvent(withName: SCGateway.scgNotificationName.rawValue, body: jsonString)
|
|
115
|
+
print("SCGatewayEmitter: Emitted event '\(SCGateway.scgNotificationName.rawValue)' with JSON string.")
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SCGatewayBridgeEmitter.m
|
|
3
|
+
// SCGateway
|
|
4
|
+
//
|
|
5
|
+
// Created by Dhruv Porwal
|
|
6
|
+
// Copyright © 2025 smallcase. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import <React/RCTBridgeModule.h>
|
|
10
|
+
#import "SmallcaseGateway-Bridging-Header.h"
|
|
11
|
+
|
|
12
|
+
@interface RCT_EXTERN_REMAP_MODULE(SCLoansBridgeEmitter, SCLoansEmitter, NSObject)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(startListening:(RCTPromiseResolveBlock)resolve
|
|
15
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
16
|
+
|
|
17
|
+
RCT_EXTERN_METHOD(stopListening:(RCTPromiseResolveBlock)resolve
|
|
18
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
19
|
+
|
|
20
|
+
@end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import Loans
|
|
4
|
+
|
|
5
|
+
@objc(SCLoansEmitter)
|
|
6
|
+
class SCLoansEmitter: RCTEventEmitter {
|
|
7
|
+
|
|
8
|
+
private static var shared: SCLoansEmitter?
|
|
9
|
+
|
|
10
|
+
private var notificationObserver: NSObjectProtocol?
|
|
11
|
+
|
|
12
|
+
private var isListening: Bool {
|
|
13
|
+
return notificationObserver != nil
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override init() {
|
|
17
|
+
super.init()
|
|
18
|
+
SCLoansEmitter.shared = self
|
|
19
|
+
print("SCLoansEmitter: Initialized.")
|
|
20
|
+
startListening()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
deinit {
|
|
24
|
+
print("SCLoansEmitter: Deinitializing.")
|
|
25
|
+
stopListening()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override func supportedEvents() -> [String]! {
|
|
29
|
+
return [ScLoan.scLoansNotificationName.rawValue]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override func startObserving() {
|
|
33
|
+
super.startObserving()
|
|
34
|
+
print("SCLoansEmitter: startObserving called.")
|
|
35
|
+
startListening()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override func stopObserving() {
|
|
39
|
+
super.stopObserving()
|
|
40
|
+
print("SCLoansEmitter: stopObserving called.")
|
|
41
|
+
stopListening()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
45
|
+
return true
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@objc func startListening(
|
|
49
|
+
_ resolve: RCTPromiseResolveBlock? = nil,
|
|
50
|
+
rejecter reject: RCTPromiseRejectBlock? = nil
|
|
51
|
+
) {
|
|
52
|
+
print("SCLoansEmitter: Starting to listen for notifications.")
|
|
53
|
+
|
|
54
|
+
guard !isListening else {
|
|
55
|
+
print("SCLoansEmitter: Already listening.")
|
|
56
|
+
resolve?("Already listening")
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
DispatchQueue.main.async { [weak self] in
|
|
61
|
+
guard let self = self else {
|
|
62
|
+
reject?("START_LISTENING_FAILED", "Self deallocated", nil)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
self.stopListening()
|
|
67
|
+
|
|
68
|
+
self.notificationObserver = NotificationCenter.default.addObserver(
|
|
69
|
+
forName: ScLoan.scLoansNotificationName,
|
|
70
|
+
object: nil,
|
|
71
|
+
queue: .main
|
|
72
|
+
) { [weak self] notification in
|
|
73
|
+
self?.processScLoansNotification(notification)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resolve?("Started listening to SCLoans events")
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@objc func stopListening(
|
|
81
|
+
_ resolve: RCTPromiseResolveBlock? = nil,
|
|
82
|
+
rejecter reject: RCTPromiseRejectBlock? = nil
|
|
83
|
+
) {
|
|
84
|
+
print("SCLoansEmitter: Stopping listening for notifications.")
|
|
85
|
+
|
|
86
|
+
guard isListening, let observer = notificationObserver else {
|
|
87
|
+
print("SCLoansEmitter: Not listening or no observer, no action needed.")
|
|
88
|
+
resolve?("Not listening")
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
NotificationCenter.default.removeObserver(observer)
|
|
93
|
+
notificationObserver = nil
|
|
94
|
+
|
|
95
|
+
print("SCLoansEmitter: Stopped listening.")
|
|
96
|
+
resolve?("Stopped listening to SCLoans events")
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private func processScLoansNotification(_ notification: Notification) {
|
|
100
|
+
let userInfo = notification.userInfo ?? [:]
|
|
101
|
+
|
|
102
|
+
print("SCLoansEmitter: Received notification with userInfo keys: \(userInfo.keys)")
|
|
103
|
+
|
|
104
|
+
guard let jsonString = userInfo[ScLoanNotification.strigifiedPayloadKey] as? String else {
|
|
105
|
+
print(
|
|
106
|
+
"SCLoansEmitter: No stringified payload found with key '\(ScLoanNotification.strigifiedPayloadKey)'"
|
|
107
|
+
)
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
print("SCLoansEmitter: Received JSON string: \(jsonString).")
|
|
112
|
+
sendEvent(withName: ScLoan.scLoansNotificationName.rawValue, body: jsonString)
|
|
113
|
+
print("SCLoansEmitter: Emitted event '\(ScLoan.scLoansNotificationName)' with JSON string.")
|
|
114
|
+
}
|
|
115
|
+
}
|