@bubblsdk/react-native-sdk 3.1.7 → 4.0.1
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/BubblReactNativeSdk.podspec +2 -2
- package/CHANGELOG.md +12 -0
- package/README.md +15 -0
- package/android/build.gradle +2 -2
- package/android/src/main/kotlin/tech/bubbl/reactnative/BubblSdkModule.kt +36 -0
- package/ios/BubblSdk.swift +75 -2
- package/ios/BubblSdkBridge.m +3 -0
- package/package.json +1 -1
- package/src/index.ts +32 -0
- package/src/specs/NativeBubblSdk.ts +2 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Pod::Spec.new do |s|
|
|
2
2
|
s.name = 'BubblReactNativeSdk'
|
|
3
|
-
s.version = '
|
|
3
|
+
s.version = '4.0.1'
|
|
4
4
|
s.summary = 'React Native wrapper for Bubbl SDK v3 native Android and iOS cores.'
|
|
5
5
|
s.homepage = 'https://bubbl.tech'
|
|
6
6
|
s.license = { :type => 'Commercial', :text => 'Copyright Bubbl. All rights reserved.' }
|
|
@@ -13,5 +13,5 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.static_framework = true
|
|
14
14
|
|
|
15
15
|
s.dependency 'React-Core'
|
|
16
|
-
s.dependency 'BubblSDK', '
|
|
16
|
+
s.dependency 'BubblSDK', '4.0.1'
|
|
17
17
|
end
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.0.1
|
|
4
|
+
|
|
5
|
+
- Android and iOS default notification modals now render image, audio, and video media inline instead of showing an external media button.
|
|
6
|
+
- YouTube notification media remains embedded in-app inside the default modal.
|
|
7
|
+
- Aligns the React Native wrapper with the native SDK 4.0.1 release.
|
|
8
|
+
|
|
9
|
+
## 4.0.0
|
|
10
|
+
|
|
11
|
+
- Primes iOS native background region monitoring when location tracking starts and after geofence/location refresh calls, so background geofence notifications can fire without relying on foreground JavaScript execution.
|
|
12
|
+
- Adds an iOS launch-options helper so React Native apps can restore persisted SDK state and resume native geofence monitoring before the bridge or JavaScript UI mounts.
|
|
13
|
+
- Aligns the React Native wrapper with the native SDK 4.0.0 release.
|
|
14
|
+
|
|
3
15
|
## 3.1.7
|
|
4
16
|
|
|
5
17
|
- Aligns the React Native wrapper with the native SDK 3.1.7 release.
|
package/README.md
CHANGED
|
@@ -35,6 +35,21 @@ bundled foreground location service and WorkManager restore/refresh path, and
|
|
|
35
35
|
iOS uses the bundled CoreLocation monitor. The host app still owns platform
|
|
36
36
|
declarations and runtime permission UX.
|
|
37
37
|
|
|
38
|
+
For iOS background geofence cold starts, forward launch options from your
|
|
39
|
+
`AppDelegate` before the React Native bridge or JavaScript UI is mounted:
|
|
40
|
+
|
|
41
|
+
```swift
|
|
42
|
+
import BubblReactNativeSdk
|
|
43
|
+
|
|
44
|
+
func application(
|
|
45
|
+
_ application: UIApplication,
|
|
46
|
+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
47
|
+
) -> Bool {
|
|
48
|
+
BubblSdkLocationLaunchHandler.handleLaunchOptions(launchOptions as NSDictionary?)
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
38
53
|
For apps that render their own in-app notification modal while still letting
|
|
39
54
|
the native SDK trigger device notifications:
|
|
40
55
|
|
package/android/build.gradle
CHANGED
|
@@ -4,7 +4,7 @@ plugins {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
group = "tech.bubbl.reactnative"
|
|
7
|
-
version = "
|
|
7
|
+
version = "4.0.1"
|
|
8
8
|
|
|
9
9
|
def isNewArchitectureEnabled() {
|
|
10
10
|
project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
|
@@ -41,6 +41,6 @@ android {
|
|
|
41
41
|
|
|
42
42
|
dependencies {
|
|
43
43
|
implementation "com.facebook.react:react-android:${reactNativeVersion}"
|
|
44
|
-
implementation "tech.bubbl.sdk:bubbl-sdk:
|
|
44
|
+
implementation "tech.bubbl.sdk:bubbl-sdk:4.0.1"
|
|
45
45
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1"
|
|
46
46
|
}
|
|
@@ -35,6 +35,8 @@ import tech.bubbl.sdk.BubblLogLevel
|
|
|
35
35
|
import tech.bubbl.sdk.BubblNotificationCta
|
|
36
36
|
import tech.bubbl.sdk.BubblNotificationDisplayResult
|
|
37
37
|
import tech.bubbl.sdk.BubblNotificationMedia
|
|
38
|
+
import tech.bubbl.sdk.BubblNotificationModalStyle
|
|
39
|
+
import tech.bubbl.sdk.BubblNotificationModalTheme
|
|
38
40
|
import tech.bubbl.sdk.BubblNotificationPayload
|
|
39
41
|
import tech.bubbl.sdk.BubblNotificationRenderingMode
|
|
40
42
|
import tech.bubbl.sdk.BubblNotificationSource
|
|
@@ -172,6 +174,12 @@ class BubblSdkModule(
|
|
|
172
174
|
null
|
|
173
175
|
}
|
|
174
176
|
|
|
177
|
+
@ReactMethod
|
|
178
|
+
fun setDefaultNotificationModalStyle(style: ReadableMap?, promise: Promise) = resolve(promise) {
|
|
179
|
+
BubblSdk.setDefaultNotificationModalStyle(style?.toNotificationModalStyle())
|
|
180
|
+
null
|
|
181
|
+
}
|
|
182
|
+
|
|
175
183
|
@ReactMethod
|
|
176
184
|
fun registerPushToken(token: String, promise: Promise) = resolve(promise) {
|
|
177
185
|
BubblSdk.registerPushToken(token)
|
|
@@ -288,12 +296,40 @@ class BubblSdkModule(
|
|
|
288
296
|
}
|
|
289
297
|
},
|
|
290
298
|
enableDefaultNotificationModal = bool("enableDefaultNotificationModal", true),
|
|
299
|
+
defaultNotificationModalStyle = map("defaultNotificationModalStyle")?.toNotificationModalStyle(),
|
|
291
300
|
enableDefaultSurveyUi = bool("enableDefaultSurveyUi", true),
|
|
292
301
|
logLevel = enumValue(string("logLevel"), BubblLogLevel.Warn) {
|
|
293
302
|
BubblLogLevel.valueOf(it.replaceFirstChar(Char::uppercaseChar))
|
|
294
303
|
}
|
|
295
304
|
)
|
|
296
305
|
|
|
306
|
+
private fun ReadableMap.toNotificationModalStyle(): BubblNotificationModalStyle =
|
|
307
|
+
BubblNotificationModalStyle(
|
|
308
|
+
theme = enumValue(string("theme"), BubblNotificationModalTheme.Light) {
|
|
309
|
+
if (it == "dark") BubblNotificationModalTheme.Dark else BubblNotificationModalTheme.Light
|
|
310
|
+
},
|
|
311
|
+
transparentBackdrop = bool("transparentBackdrop", true),
|
|
312
|
+
backdropColor = string("backdropColor"),
|
|
313
|
+
cardBackgroundColor = string("cardBackgroundColor"),
|
|
314
|
+
cardBorderColor = string("cardBorderColor"),
|
|
315
|
+
titleColor = string("titleColor"),
|
|
316
|
+
bodyColor = string("bodyColor"),
|
|
317
|
+
accentColor = string("accentColor"),
|
|
318
|
+
iconBackgroundColor = string("iconBackgroundColor"),
|
|
319
|
+
iconTextColor = string("iconTextColor"),
|
|
320
|
+
primaryButtonBackgroundColor = string("primaryButtonBackgroundColor"),
|
|
321
|
+
primaryButtonTextColor = string("primaryButtonTextColor"),
|
|
322
|
+
secondaryButtonBackgroundColor = string("secondaryButtonBackgroundColor"),
|
|
323
|
+
secondaryButtonTextColor = string("secondaryButtonTextColor"),
|
|
324
|
+
textButtonColor = string("textButtonColor"),
|
|
325
|
+
surveyBackgroundColor = string("surveyBackgroundColor"),
|
|
326
|
+
inputBackgroundColor = string("inputBackgroundColor"),
|
|
327
|
+
inputTextColor = string("inputTextColor"),
|
|
328
|
+
inputBorderColor = string("inputBorderColor"),
|
|
329
|
+
cornerRadius = nullableDouble("cornerRadius"),
|
|
330
|
+
buttonCornerRadius = nullableDouble("buttonCornerRadius")
|
|
331
|
+
)
|
|
332
|
+
|
|
297
333
|
private fun ReadableMap.toTrackEvent(): BubblTrackEvent =
|
|
298
334
|
BubblTrackEvent(
|
|
299
335
|
type = requiredString("type"),
|
package/ios/BubblSdk.swift
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import React
|
|
3
3
|
import BubblSDK
|
|
4
|
+
import UIKit
|
|
4
5
|
|
|
5
6
|
#if canImport(CoreLocation)
|
|
6
7
|
import CoreLocation
|
|
@@ -114,7 +115,11 @@ final class BubblSdk: RCTEventEmitter {
|
|
|
114
115
|
reject: @escaping RCTPromiseRejectBlock
|
|
115
116
|
) {
|
|
116
117
|
resolveAsync(resolve, reject) {
|
|
117
|
-
|
|
118
|
+
let location = BubblLocation(latitude: latitude, longitude: longitude)
|
|
119
|
+
try await self.sdk.refreshGeofence(location)
|
|
120
|
+
#if canImport(CoreLocation)
|
|
121
|
+
await self.locationMonitor.refreshBackgroundRegions(near: location)
|
|
122
|
+
#endif
|
|
118
123
|
return nil
|
|
119
124
|
}
|
|
120
125
|
}
|
|
@@ -127,7 +132,11 @@ final class BubblSdk: RCTEventEmitter {
|
|
|
127
132
|
reject: @escaping RCTPromiseRejectBlock
|
|
128
133
|
) {
|
|
129
134
|
resolveAsync(resolve, reject) {
|
|
130
|
-
|
|
135
|
+
let location = BubblLocation(latitude: latitude, longitude: longitude)
|
|
136
|
+
try await self.sdk.handleLocationUpdate(location)
|
|
137
|
+
#if canImport(CoreLocation)
|
|
138
|
+
await self.locationMonitor.refreshBackgroundRegions(near: location)
|
|
139
|
+
#endif
|
|
131
140
|
return nil
|
|
132
141
|
}
|
|
133
142
|
}
|
|
@@ -210,6 +219,18 @@ final class BubblSdk: RCTEventEmitter {
|
|
|
210
219
|
}
|
|
211
220
|
}
|
|
212
221
|
|
|
222
|
+
@objc(setDefaultNotificationModalStyle:resolver:rejecter:)
|
|
223
|
+
func setDefaultNotificationModalStyle(
|
|
224
|
+
_ style: NSDictionary?,
|
|
225
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
226
|
+
reject: @escaping RCTPromiseRejectBlock
|
|
227
|
+
) {
|
|
228
|
+
resolveAsync(resolve, reject) {
|
|
229
|
+
try await self.sdk.setDefaultNotificationModalStyle(try style?.swiftMap.notificationModalStyle())
|
|
230
|
+
return nil
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
213
234
|
@objc(registerPushToken:resolver:rejecter:)
|
|
214
235
|
func registerPushToken(
|
|
215
236
|
_ token: NSString,
|
|
@@ -382,6 +403,31 @@ final class BubblSdk: RCTEventEmitter {
|
|
|
382
403
|
private static let eventName = "BubblSdkEvent"
|
|
383
404
|
}
|
|
384
405
|
|
|
406
|
+
@objc(BubblSdkLocationLaunchHandler)
|
|
407
|
+
public final class BubblSdkLocationLaunchHandler: NSObject {
|
|
408
|
+
#if canImport(CoreLocation)
|
|
409
|
+
@MainActor private static let locationMonitor = BubblLocationMonitor(sdk: .shared)
|
|
410
|
+
#endif
|
|
411
|
+
|
|
412
|
+
@objc(handleLaunchOptions:)
|
|
413
|
+
public static func handleLaunchOptions(_ launchOptions: NSDictionary?) -> Bool {
|
|
414
|
+
let launchedForLocation = launchOptions?[UIApplication.LaunchOptionsKey.location.rawValue] != nil
|
|
415
|
+
|| launchOptions?[UIApplication.LaunchOptionsKey.location] != nil
|
|
416
|
+
|
|
417
|
+
guard launchedForLocation else {
|
|
418
|
+
return false
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
#if canImport(CoreLocation)
|
|
422
|
+
Task { @MainActor in
|
|
423
|
+
await locationMonitor.resumeForBackgroundLocationLaunch()
|
|
424
|
+
}
|
|
425
|
+
#endif
|
|
426
|
+
|
|
427
|
+
return true
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
385
431
|
private struct BubblReactNativeError: Error {
|
|
386
432
|
let code: String
|
|
387
433
|
let message: String
|
|
@@ -457,11 +503,38 @@ private extension Dictionary where Key == String, Value == Any {
|
|
|
457
503
|
enableLocationTracking: bool("enableLocationTracking", default: false),
|
|
458
504
|
notificationRenderingMode: BubblNotificationRenderingMode(rawValue: string("notificationRenderingMode") ?? "sdkDefault") ?? .sdkDefault,
|
|
459
505
|
enableDefaultNotificationModal: bool("enableDefaultNotificationModal", default: true),
|
|
506
|
+
defaultNotificationModalStyle: try map("defaultNotificationModalStyle")?.notificationModalStyle(),
|
|
460
507
|
enableDefaultSurveyUi: bool("enableDefaultSurveyUi", default: true),
|
|
461
508
|
logLevel: BubblLogLevel(rawValue: string("logLevel") ?? "warn") ?? .warn
|
|
462
509
|
)
|
|
463
510
|
}
|
|
464
511
|
|
|
512
|
+
func notificationModalStyle() throws -> BubblNotificationModalStyle {
|
|
513
|
+
BubblNotificationModalStyle(
|
|
514
|
+
theme: BubblNotificationModalTheme(rawValue: string("theme") ?? "light") ?? .light,
|
|
515
|
+
transparentBackdrop: bool("transparentBackdrop", default: true),
|
|
516
|
+
backdropColor: string("backdropColor"),
|
|
517
|
+
cardBackgroundColor: string("cardBackgroundColor"),
|
|
518
|
+
cardBorderColor: string("cardBorderColor"),
|
|
519
|
+
titleColor: string("titleColor"),
|
|
520
|
+
bodyColor: string("bodyColor"),
|
|
521
|
+
accentColor: string("accentColor"),
|
|
522
|
+
iconBackgroundColor: string("iconBackgroundColor"),
|
|
523
|
+
iconTextColor: string("iconTextColor"),
|
|
524
|
+
primaryButtonBackgroundColor: string("primaryButtonBackgroundColor"),
|
|
525
|
+
primaryButtonTextColor: string("primaryButtonTextColor"),
|
|
526
|
+
secondaryButtonBackgroundColor: string("secondaryButtonBackgroundColor"),
|
|
527
|
+
secondaryButtonTextColor: string("secondaryButtonTextColor"),
|
|
528
|
+
textButtonColor: string("textButtonColor"),
|
|
529
|
+
surveyBackgroundColor: string("surveyBackgroundColor"),
|
|
530
|
+
inputBackgroundColor: string("inputBackgroundColor"),
|
|
531
|
+
inputTextColor: string("inputTextColor"),
|
|
532
|
+
inputBorderColor: string("inputBorderColor"),
|
|
533
|
+
cornerRadius: optionalDouble("cornerRadius"),
|
|
534
|
+
buttonCornerRadius: optionalDouble("buttonCornerRadius")
|
|
535
|
+
)
|
|
536
|
+
}
|
|
537
|
+
|
|
465
538
|
func trackEvent() throws -> BubblTrackEvent {
|
|
466
539
|
BubblTrackEvent(
|
|
467
540
|
type: try requiredString("type"),
|
package/ios/BubblSdkBridge.m
CHANGED
|
@@ -39,6 +39,9 @@ RCT_EXTERN_METHOD(clearCorrelationId:(RCTPromiseResolveBlock)resolve
|
|
|
39
39
|
RCT_EXTERN_METHOD(setDefaultNotificationModalEnabled:(BOOL)enabled
|
|
40
40
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
41
41
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
|
+
RCT_EXTERN_METHOD(setDefaultNotificationModalStyle:(NSDictionary *)style
|
|
43
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
44
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
42
45
|
RCT_EXTERN_METHOD(registerPushToken:(NSString *)token
|
|
43
46
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
44
47
|
rejecter:(RCTPromiseRejectBlock)reject)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -9,6 +9,31 @@ export type BubblEnvironment = 'development' | 'staging' | 'production';
|
|
|
9
9
|
export type BubblLogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug';
|
|
10
10
|
export type BubblNotificationRenderingMode = 'sdkDefault' | 'hostRendered' | 'eventOnly';
|
|
11
11
|
export type BubblNotificationSource = 'firebase' | 'apns' | 'runtime' | 'geofence' | 'manual';
|
|
12
|
+
export type BubblNotificationModalTheme = 'light' | 'dark';
|
|
13
|
+
|
|
14
|
+
export type BubblNotificationModalStyle = {
|
|
15
|
+
theme?: BubblNotificationModalTheme;
|
|
16
|
+
transparentBackdrop?: boolean;
|
|
17
|
+
backdropColor?: string | null;
|
|
18
|
+
cardBackgroundColor?: string | null;
|
|
19
|
+
cardBorderColor?: string | null;
|
|
20
|
+
titleColor?: string | null;
|
|
21
|
+
bodyColor?: string | null;
|
|
22
|
+
accentColor?: string | null;
|
|
23
|
+
iconBackgroundColor?: string | null;
|
|
24
|
+
iconTextColor?: string | null;
|
|
25
|
+
primaryButtonBackgroundColor?: string | null;
|
|
26
|
+
primaryButtonTextColor?: string | null;
|
|
27
|
+
secondaryButtonBackgroundColor?: string | null;
|
|
28
|
+
secondaryButtonTextColor?: string | null;
|
|
29
|
+
textButtonColor?: string | null;
|
|
30
|
+
surveyBackgroundColor?: string | null;
|
|
31
|
+
inputBackgroundColor?: string | null;
|
|
32
|
+
inputTextColor?: string | null;
|
|
33
|
+
inputBorderColor?: string | null;
|
|
34
|
+
cornerRadius?: number | null;
|
|
35
|
+
buttonCornerRadius?: number | null;
|
|
36
|
+
};
|
|
12
37
|
|
|
13
38
|
export type BubblConfig = {
|
|
14
39
|
apiKey: string;
|
|
@@ -24,6 +49,7 @@ export type BubblConfig = {
|
|
|
24
49
|
enableLocationTracking?: boolean;
|
|
25
50
|
notificationRenderingMode?: BubblNotificationRenderingMode;
|
|
26
51
|
enableDefaultNotificationModal?: boolean;
|
|
52
|
+
defaultNotificationModalStyle?: BubblNotificationModalStyle | null;
|
|
27
53
|
enableDefaultSurveyUi?: boolean;
|
|
28
54
|
logLevel?: BubblLogLevel;
|
|
29
55
|
};
|
|
@@ -237,6 +263,12 @@ export const Bubbl = {
|
|
|
237
263
|
async setDefaultNotificationModalEnabled(enabled: boolean): Promise<void> {
|
|
238
264
|
return nativeModule().setDefaultNotificationModalEnabled(enabled);
|
|
239
265
|
},
|
|
266
|
+
async setDefaultNotificationModalStyle(style: BubblNotificationModalStyle | null): Promise<void> {
|
|
267
|
+
return nativeModule().setDefaultNotificationModalStyle(style);
|
|
268
|
+
},
|
|
269
|
+
async resetDefaultNotificationModalStyle(): Promise<void> {
|
|
270
|
+
return nativeModule().setDefaultNotificationModalStyle(null);
|
|
271
|
+
},
|
|
240
272
|
async disableDefaultNotificationModal(): Promise<void> {
|
|
241
273
|
return nativeModule().setDefaultNotificationModalEnabled(false);
|
|
242
274
|
},
|
|
@@ -15,6 +15,7 @@ export type BubblBootOptions = {
|
|
|
15
15
|
enableLocationTracking?: boolean;
|
|
16
16
|
notificationRenderingMode?: string;
|
|
17
17
|
enableDefaultNotificationModal?: boolean;
|
|
18
|
+
defaultNotificationModalStyle?: Object | null;
|
|
18
19
|
enableDefaultSurveyUi?: boolean;
|
|
19
20
|
logLevel?: string;
|
|
20
21
|
};
|
|
@@ -34,6 +35,7 @@ export interface Spec extends TurboModule {
|
|
|
34
35
|
setCorrelationId(value: string): Promise<void>;
|
|
35
36
|
clearCorrelationId(): Promise<void>;
|
|
36
37
|
setDefaultNotificationModalEnabled(enabled: boolean): Promise<void>;
|
|
38
|
+
setDefaultNotificationModalStyle(style?: Object | null): Promise<void>;
|
|
37
39
|
registerPushToken(token: string): Promise<void>;
|
|
38
40
|
handleFirebasePayload(payload: Object): Promise<Object | null>;
|
|
39
41
|
showNotification(payload: Object): Promise<Object>;
|