@dashx/react-native 1.1.5 → 1.3.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/.DS_Store +0 -0
- package/.claude/settings.local.json +18 -1
- package/.gitignore +1 -1
- package/CHANGELOG.md +34 -0
- package/DashXReactNative.podspec +12 -26
- package/README.md +3 -1
- package/__tests__/fallback.test.js +72 -0
- package/__tests__/index.test.js +46 -5
- package/android/build.gradle +27 -1
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/com/dashx/rn/sdk/DashXReactNativeModuleImpl.kt +384 -0
- package/android/src/newarch/java/com/dashx/rn/sdk/DashXReactNativeModule.kt +85 -0
- package/android/src/newarch/java/com/dashx/rn/sdk/DashXReactNativePackage.kt +33 -0
- package/android/src/oldarch/java/com/dashx/rn/sdk/DashXReactNativeModule.kt +106 -0
- package/android/src/oldarch/java/com/dashx/rn/sdk/DashXReactNativePackage.kt +33 -0
- package/index.d.ts +24 -2
- package/index.js +22 -11
- package/ios/DashXNotificationHandler.swift +257 -0
- package/ios/DashXReactNative-Bridging-Header.h +0 -2
- package/ios/DashXReactNative.mm +32 -9
- package/ios/DashXReactNative.swift +27 -19
- package/package.json +11 -2
- package/src/NativeDashXReactNative.ts +42 -0
- package/android/src/main/java/com/dashx/rn/sdk/DashXReactNativeModule.kt +0 -231
- package/android/src/main/java/com/dashx/rn/sdk/DashXReactNativePackage.kt +0 -18
- package/ios/DashXRCTAppDelegate.h +0 -3
- package/ios/DashXRCTAppDelegate.swift +0 -266
- package/ios/DashXReactNative.h +0 -1
package/.DS_Store
CHANGED
|
Binary file
|
|
@@ -8,7 +8,24 @@
|
|
|
8
8
|
"Bash(swift build:*)",
|
|
9
9
|
"Bash(xcodebuild -scheme DashX -destination 'generic/platform=iOS' build)",
|
|
10
10
|
"Bash(./gradlew :dashx:compileDebugKotlin)",
|
|
11
|
-
"Bash(./gradlew :dashx:compileDebugKotlin --info)"
|
|
11
|
+
"Bash(./gradlew :dashx:compileDebugKotlin --info)",
|
|
12
|
+
"Bash(gh pr:*)",
|
|
13
|
+
"WebFetch(domain:github.com)",
|
|
14
|
+
"WebFetch(domain:patch-diff.githubusercontent.com)",
|
|
15
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
16
|
+
"Bash(ls -la /Users/gulshan/Work/dashx-react-native/ios/DashXRCTAppDelegate*)",
|
|
17
|
+
"Bash(npx jest *)",
|
|
18
|
+
"Bash(ls *)",
|
|
19
|
+
"Bash(grep *)",
|
|
20
|
+
"Read(//private/tmp/**)",
|
|
21
|
+
"Bash(javap -p com/dashx/android/DashX.class)",
|
|
22
|
+
"Bash(javap -p 'com/dashx/android/DashX$Companion.class')",
|
|
23
|
+
"Bash(jar xf *)",
|
|
24
|
+
"Bash(javap 'com/dashx/android/DashX$Companion.class')",
|
|
25
|
+
"Bash(javap 'com/dashx/android/data/Asset.class')",
|
|
26
|
+
"Bash(javap 'com/dashx/android/data/AssetData.class')",
|
|
27
|
+
"Read(//Users/gulshan/Work/dashx-ios/**)",
|
|
28
|
+
"WebSearch"
|
|
12
29
|
]
|
|
13
30
|
}
|
|
14
31
|
}
|
package/.gitignore
CHANGED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@dashx/react-native` are documented in this file. Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versions follow [SemVer](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [1.3.0] — 2026-04-20
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
- **`DashX` pod → `DashX/SDK`.** The podspec now depends on the `DashX/SDK` subspec of [dashx-ios 1.3.1+](https://github.com/dashxhq/dashx-ios) with no version constraint. Consumers must update their Podfile:
|
|
9
|
+
```ruby
|
|
10
|
+
# before
|
|
11
|
+
pod 'DashX', :git => 'https://github.com/dashxhq/dashx-ios.git', :tag => '1.1.9'
|
|
12
|
+
|
|
13
|
+
# after
|
|
14
|
+
pod 'DashX/SDK', :git => 'https://github.com/dashxhq/dashx-ios.git', :tag => '1.3.1'
|
|
15
|
+
```
|
|
16
|
+
- **`FirebaseMessaging` is now a hard dependency.** Previously the bridge guarded Firebase usage with `#if canImport(FirebaseMessaging)`, but `canImport` doesn't see consumer-Podfile pods at this pod's compile time, so the guard silently elided every FCM code path — push registration stopped working on fresh installs. Consumers must enable modular headers in their Podfile:
|
|
17
|
+
```ruby
|
|
18
|
+
use_modular_headers!
|
|
19
|
+
# or, per-pod:
|
|
20
|
+
pod 'FirebaseMessaging', :modular_headers => true
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
- `DashX.onNotificationClicked(callback)` — fires when the user taps a DashX notification or one of its action buttons. Callback receives `{ notification, action, actionIdentifier }` where `action` is a resolved `NavigationAction` (`deepLink` / `screen` / `richLanding` / `clickAction`) or `null`.
|
|
25
|
+
- `DashXNotificationResponseResult.navigationAction` — new Swift-only field on the helper result type returned by `DashXNotificationHandler.handleNotificationResponse(_:)`.
|
|
26
|
+
- `NotificationClickedEvent` exported from `index.d.ts`.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **iOS dev builds silently failing to receive pushes.** `Messaging.messaging().setAPNSToken(_, type: .unknown)` sometimes mis-tagged the APNs environment on dev-signed binaries, producing an FCM token whose pushes 410'd at Apple. The bridge now forces `.sandbox` in `DEBUG` configurations and `.prod` otherwise.
|
|
30
|
+
- **`DashX.setIdentity(uid, token)` now passes `null` / `""` / `undefined` through to the native SDK unchanged** (apart from normalizing `undefined → null`, since the RN bridge can't carry `undefined`). Previously the JS wrapper threw on `null` / `""` / `undefined` for `uid`, contradicting the nullable signatures on iOS (`NSString?`) and Android (`String?`). TypeScript signature updated: `setIdentity(uid: string | null, token?: string | null): void`.
|
|
31
|
+
|
|
32
|
+
## [1.2.0] — 2026-04-16
|
|
33
|
+
|
|
34
|
+
Previous release — see git log.
|
package/DashXReactNative.podspec
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
require "json"
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
-
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
4
|
|
|
6
5
|
Pod::Spec.new do |s|
|
|
7
6
|
s.name = "DashXReactNative"
|
|
@@ -17,33 +16,20 @@ Pod::Spec.new do |s|
|
|
|
17
16
|
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
18
17
|
s.requires_arc = true
|
|
19
18
|
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
install_modules_dependencies(s)
|
|
24
|
-
else
|
|
25
|
-
s.dependency "React-Core"
|
|
19
|
+
# React Native >= 0.71 provides install_modules_dependencies.
|
|
20
|
+
# Since our minimum supported RN version is 0.74, we can call it directly.
|
|
21
|
+
install_modules_dependencies(s)
|
|
26
22
|
|
|
27
|
-
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
28
|
-
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
29
|
-
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
30
|
-
s.pod_target_xcconfig = {
|
|
31
|
-
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
32
|
-
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
33
|
-
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
34
|
-
}
|
|
35
|
-
s.dependency "React-Codegen"
|
|
36
|
-
s.dependency "RCT-Folly"
|
|
37
|
-
s.dependency "RCTRequired"
|
|
38
|
-
s.dependency "RCTTypeSafety"
|
|
39
|
-
s.dependency "ReactCommon/turbomodule/core"
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
s.dependency "React-RCTAppDelegate"
|
|
44
23
|
# DashX iOS SDK — consumers must provide the source in their Podfile:
|
|
45
|
-
# pod 'DashX', :git => 'https://github.com/dashxhq/dashx-ios.git', :tag => '1.1
|
|
24
|
+
# pod 'DashX/SDK', :git => 'https://github.com/dashxhq/dashx-ios.git', :tag => '1.3.1'
|
|
46
25
|
# For local development:
|
|
47
26
|
# pod 'DashX', :path => '../dashx-ios'
|
|
48
|
-
s.dependency "DashX"
|
|
27
|
+
s.dependency "DashX/SDK"
|
|
28
|
+
|
|
29
|
+
# Hard dependency so that `canImport(FirebaseMessaging)`
|
|
30
|
+
# evaluates at this pod's compile time, where consumer-Podfile pods aren't
|
|
31
|
+
# visible — so an "optional" guard silently elides every Firebase code path.
|
|
32
|
+
# Consumers should set `use_modular_headers!` (or `:modular_headers => true`
|
|
33
|
+
# on FirebaseMessaging) in their Podfile so this Swift import resolves.
|
|
34
|
+
s.dependency "FirebaseMessaging"
|
|
49
35
|
end
|
package/README.md
CHANGED
|
@@ -26,7 +26,9 @@ _DashX SDK for React Native_
|
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
29
|
-
Requires **React Native 0.
|
|
29
|
+
Requires **React Native 0.74+**, **iOS 13.0+**, **Android SDK 26+**, and **Node.js 16+**.
|
|
30
|
+
|
|
31
|
+
Supports both the **Old Architecture** (bridge) and **New Architecture** (TurboModule) from a single install.
|
|
30
32
|
|
|
31
33
|
> **Note:** This SDK uses native modules and is **not compatible with Expo Go**. Use a [development build](https://docs.expo.dev/develop/development-builds/introduction/) if you are using Expo.
|
|
32
34
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const mockNativeModule = {
|
|
2
|
+
configure: jest.fn(),
|
|
3
|
+
identify: jest.fn(),
|
|
4
|
+
setIdentity: jest.fn(),
|
|
5
|
+
reset: jest.fn(),
|
|
6
|
+
track: jest.fn(),
|
|
7
|
+
screen: jest.fn(),
|
|
8
|
+
fetchRecord: jest.fn(),
|
|
9
|
+
searchRecords: jest.fn(),
|
|
10
|
+
fetchStoredPreferences: jest.fn(),
|
|
11
|
+
saveStoredPreferences: jest.fn(),
|
|
12
|
+
subscribe: jest.fn(),
|
|
13
|
+
unsubscribe: jest.fn(),
|
|
14
|
+
setLogLevel: jest.fn(),
|
|
15
|
+
uploadAsset: jest.fn(),
|
|
16
|
+
fetchAsset: jest.fn(),
|
|
17
|
+
enableLifecycleTracking: jest.fn(),
|
|
18
|
+
enableAdTracking: jest.fn(),
|
|
19
|
+
processURL: jest.fn(),
|
|
20
|
+
trackNotificationNavigation: jest.fn(),
|
|
21
|
+
requestNotificationPermission: jest.fn(),
|
|
22
|
+
getNotificationPermissionStatus: jest.fn(),
|
|
23
|
+
addListener: jest.fn(),
|
|
24
|
+
removeListeners: jest.fn(),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
jest.mock('react-native', () => ({
|
|
28
|
+
NativeModules: {
|
|
29
|
+
DashXReactNative: mockNativeModule,
|
|
30
|
+
},
|
|
31
|
+
NativeEventEmitter: jest.fn().mockImplementation(() => ({
|
|
32
|
+
addListener: jest.fn(() => ({ remove: jest.fn() })),
|
|
33
|
+
})),
|
|
34
|
+
Platform: {
|
|
35
|
+
OS: 'ios',
|
|
36
|
+
select: jest.fn((obj) => obj.default || ''),
|
|
37
|
+
},
|
|
38
|
+
TurboModuleRegistry: {
|
|
39
|
+
get: jest.fn(() => null),
|
|
40
|
+
getEnforcing: jest.fn(() => {
|
|
41
|
+
throw new Error('not available');
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
// TurboModule returns null -> should fall back to NativeModules
|
|
47
|
+
jest.mock('../src/NativeDashXReactNative', () => ({
|
|
48
|
+
__esModule: true,
|
|
49
|
+
default: null,
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
const DashX = require('../index').default;
|
|
53
|
+
|
|
54
|
+
describe('NativeModules fallback', () => {
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
jest.clearAllMocks();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('falls back to NativeModules.DashXReactNative when TurboModule is null', () => {
|
|
60
|
+
DashX.configure({ publicKey: 'pk_test' });
|
|
61
|
+
expect(mockNativeModule.configure).toHaveBeenCalledWith({
|
|
62
|
+
publicKey: 'pk_test',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('calls track on the fallback module', () => {
|
|
67
|
+
DashX.track('event_name', { key: 'value' });
|
|
68
|
+
expect(mockNativeModule.track).toHaveBeenCalledWith('event_name', {
|
|
69
|
+
key: 'value',
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
package/__tests__/index.test.js
CHANGED
|
@@ -37,6 +37,15 @@ jest.mock('react-native', () => ({
|
|
|
37
37
|
OS: 'ios',
|
|
38
38
|
select: jest.fn((obj) => obj.default || ''),
|
|
39
39
|
},
|
|
40
|
+
TurboModuleRegistry: {
|
|
41
|
+
get: jest.fn(() => mockNativeModule),
|
|
42
|
+
getEnforcing: jest.fn(() => mockNativeModule),
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
jest.mock('../src/NativeDashXReactNative', () => ({
|
|
47
|
+
__esModule: true,
|
|
48
|
+
default: mockNativeModule,
|
|
40
49
|
}));
|
|
41
50
|
|
|
42
51
|
const DashX = require('../index').default;
|
|
@@ -97,13 +106,45 @@ describe('setIdentity', () => {
|
|
|
97
106
|
);
|
|
98
107
|
});
|
|
99
108
|
|
|
100
|
-
it('
|
|
101
|
-
|
|
109
|
+
it('passes null uid through to native', () => {
|
|
110
|
+
DashX.setIdentity(null, 'token');
|
|
111
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith(null, 'token');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('normalizes undefined uid to null', () => {
|
|
115
|
+
DashX.setIdentity(undefined, 'token');
|
|
116
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith(null, 'token');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('passes empty-string uid through to native without coercing to null', () => {
|
|
120
|
+
DashX.setIdentity('', 'token');
|
|
121
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith('', 'token');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('throws if uid is not a string or null', () => {
|
|
125
|
+
expect(() => DashX.setIdentity(42, 'token')).toThrow(
|
|
126
|
+
'uid must be a string or null'
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('passes null token through to native', () => {
|
|
131
|
+
DashX.setIdentity('uid', null);
|
|
132
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith('uid', null);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('passes empty-string token through to native without coercing to null', () => {
|
|
136
|
+
DashX.setIdentity('uid', '');
|
|
137
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith('uid', '');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('passes undefined token as null to native', () => {
|
|
141
|
+
DashX.setIdentity('uid');
|
|
142
|
+
expect(mockNativeModule.setIdentity).toHaveBeenCalledWith('uid', null);
|
|
102
143
|
});
|
|
103
144
|
|
|
104
|
-
it('throws if token is
|
|
105
|
-
expect(() => DashX.setIdentity('uid',
|
|
106
|
-
'token
|
|
145
|
+
it('throws if token is not a string or null', () => {
|
|
146
|
+
expect(() => DashX.setIdentity('uid', 42)).toThrow(
|
|
147
|
+
'token must be a string or null'
|
|
107
148
|
);
|
|
108
149
|
});
|
|
109
150
|
});
|
package/android/build.gradle
CHANGED
|
@@ -3,6 +3,14 @@ import groovy.json.JsonSlurper
|
|
|
3
3
|
apply plugin: 'com.android.library'
|
|
4
4
|
apply plugin: 'kotlin-android'
|
|
5
5
|
|
|
6
|
+
def isNewArchitectureEnabled() {
|
|
7
|
+
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (isNewArchitectureEnabled()) {
|
|
11
|
+
apply plugin: 'com.facebook.react'
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
def getVersionFromNpm() {
|
|
7
15
|
def inputFile = new File("../package.json")
|
|
8
16
|
def packageJson = new JsonSlurper().parseText(inputFile.text)
|
|
@@ -30,6 +38,16 @@ android {
|
|
|
30
38
|
abortOnError false
|
|
31
39
|
}
|
|
32
40
|
|
|
41
|
+
sourceSets {
|
|
42
|
+
main {
|
|
43
|
+
if (isNewArchitectureEnabled()) {
|
|
44
|
+
java.srcDirs += ['src/newarch/java']
|
|
45
|
+
} else {
|
|
46
|
+
java.srcDirs += ['src/oldarch/java']
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
33
51
|
packaging {
|
|
34
52
|
pickFirst 'lib/arm64-v8a/libc++_shared.so'
|
|
35
53
|
pickFirst 'lib/arm64-v8a/libfbjni.so'
|
|
@@ -42,6 +60,14 @@ android {
|
|
|
42
60
|
}
|
|
43
61
|
}
|
|
44
62
|
|
|
63
|
+
if (isNewArchitectureEnabled()) {
|
|
64
|
+
react {
|
|
65
|
+
jsRootDir = file("../src/")
|
|
66
|
+
libraryName = "RNDashXReactNativeSpec"
|
|
67
|
+
codegenJavaPackageName = "com.dashx.rn.sdk"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
45
71
|
repositories {
|
|
46
72
|
mavenCentral()
|
|
47
73
|
google()
|
|
@@ -55,5 +81,5 @@ dependencies {
|
|
|
55
81
|
// Ensure Firebase Messaging types are available for FCM service subclass
|
|
56
82
|
implementation 'com.google.firebase:firebase-messaging-ktx:23.1.2'
|
|
57
83
|
|
|
58
|
-
implementation "com.dashx:dashx-android:1.2.
|
|
84
|
+
implementation "com.dashx:dashx-android:1.2.5"
|
|
59
85
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
2
|
xmlns:tools="http://schemas.android.com/tools">
|
|
3
|
+
|
|
4
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
5
|
+
|
|
3
6
|
<application>
|
|
4
7
|
<!-- Replace dashx-android's FCM service with our subclass that also emits to JS. -->
|
|
5
8
|
<service
|