@amplytools/react-native-amply-sdk 0.1.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/LICENSE +178 -0
- package/README.md +714 -0
- package/android/build.gradle +90 -0
- package/android/consumer-rules.pro +1 -0
- package/android/gradle.properties +3 -0
- package/android/settings.gradle +9 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/AmplyModule.kt +384 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/AmplyPackage.kt +39 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/core/AmplyClient.kt +30 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/core/DefaultAmplyClient.kt +296 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/AmplyInitializationOptions.kt +10 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/DataSetType.kt +42 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/DataSetTypeMapper.kt +38 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/DeepLinkPayload.kt +8 -0
- package/android/src/main/java/tools/amply/sdk/reactnative/model/EventEnvelope.kt +9 -0
- package/android/src/main/jni/AmplyTurboModule.cpp +29 -0
- package/android/src/main/jni/CMakeLists.txt +76 -0
- package/android/src/newarch/java/tools/amply/sdk/reactnative/NativeAmplyModuleSpec.java +75 -0
- package/android/src/newarch/jni/AmplyReactNative-generated.cpp +77 -0
- package/android/src/newarch/jni/AmplyReactNative.h +31 -0
- package/android/src/newarch/jni/CMakeLists.txt +40 -0
- package/app.plugin.js +1 -0
- package/dist/index.js +272 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +234 -0
- package/dist/index.mjs.map +1 -0
- package/dist/plugin/index.d.ts +6 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +186 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/index.mjs +169 -0
- package/dist/plugin/index.mjs.map +1 -0
- package/dist/plugin/src/index.d.ts +6 -0
- package/dist/plugin/src/index.d.ts.map +1 -0
- package/dist/plugin/src/index.js +3 -0
- package/dist/plugin/src/withAmply.d.ts +30 -0
- package/dist/plugin/src/withAmply.d.ts.map +1 -0
- package/dist/plugin/src/withAmply.js +51 -0
- package/dist/plugin/withAmply.d.ts +12 -0
- package/dist/plugin/withAmply.d.ts.map +1 -0
- package/dist/src/__tests__/index.test.d.ts +2 -0
- package/dist/src/__tests__/index.test.d.ts.map +1 -0
- package/dist/src/__tests__/index.test.js +70 -0
- package/dist/src/hooks/useAmplySystemEvents.d.ts +12 -0
- package/dist/src/hooks/useAmplySystemEvents.d.ts.map +1 -0
- package/dist/src/hooks/useAmplySystemEvents.js +56 -0
- package/dist/src/index.d.ts +32 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +80 -0
- package/dist/src/nativeModule.d.ts +5 -0
- package/dist/src/nativeModule.d.ts.map +1 -0
- package/dist/src/nativeModule.js +48 -0
- package/dist/src/nativeSpecs/NativeAmplyModule.d.ts +75 -0
- package/dist/src/nativeSpecs/NativeAmplyModule.d.ts.map +1 -0
- package/dist/src/nativeSpecs/NativeAmplyModule.js +2 -0
- package/dist/src/systemEventUtils.d.ts +3 -0
- package/dist/src/systemEventUtils.d.ts.map +1 -0
- package/dist/src/systemEventUtils.js +30 -0
- package/dist/src/systemEvents.d.ts +6 -0
- package/dist/src/systemEvents.d.ts.map +1 -0
- package/dist/src/systemEvents.js +8 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/docs/ARCHITECTURE.md +1115 -0
- package/expo-module.config.json +11 -0
- package/ios/AmplyReactNative.podspec +32 -0
- package/ios/README.md +11 -0
- package/ios/Sources/AmplyReactNative/AmplyModule.mm +332 -0
- package/ios/Sources/AmplyReactNative/AmplyReactNative/AmplyReactNative-generated.mm +111 -0
- package/ios/Sources/AmplyReactNative/AmplyReactNative/AmplyReactNative.h +152 -0
- package/package.json +71 -0
- package/plugin/build/index.d.ts +5 -0
- package/plugin/build/index.js +8 -0
- package/plugin/build/withAmply.d.ts +29 -0
- package/plugin/build/withAmply.js +53 -0
- package/plugin/src/index.ts +7 -0
- package/plugin/src/withAmply.ts +68 -0
- package/plugin/tsconfig.json +8 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/react-native.config.js +34 -0
- package/scripts/codegen.js +212 -0
- package/src/__tests__/index.test.ts +92 -0
- package/src/hooks/useAmplySystemEvents.ts +75 -0
- package/src/index.ts +115 -0
- package/src/nativeModule.ts +65 -0
- package/src/nativeSpecs/NativeAmplyModule.ts +80 -0
- package/src/systemEventUtils.ts +35 -0
- package/src/systemEvents.ts +13 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = 'AmplyReactNative'
|
|
3
|
+
s.version = '0.1.0-alpha.0'
|
|
4
|
+
s.summary = 'React Native bridge for Amply SDK'
|
|
5
|
+
s.homepage = 'https://github.com/amply/amply-react-native'
|
|
6
|
+
s.license = { :type => 'MIT' }
|
|
7
|
+
s.authors = { 'Amply' => 'opensource@amply.tools' }
|
|
8
|
+
s.source = { :git => 'https://github.com/amply/amply-react-native.git', :tag => s.version.to_s }
|
|
9
|
+
|
|
10
|
+
s.platforms = { :ios => '15.1' }
|
|
11
|
+
s.source_files = 'Sources/**/*.{swift,h,m,mm}'
|
|
12
|
+
|
|
13
|
+
# React Native dependencies for TurboModules
|
|
14
|
+
s.dependency 'React-Core'
|
|
15
|
+
s.dependency 'ReactCommon/turbomodule/core'
|
|
16
|
+
s.dependency 'React-RCTFabric'
|
|
17
|
+
|
|
18
|
+
# Amply KMP SDK from CocoaPods
|
|
19
|
+
s.dependency 'AmplySDK', '~> 0.1.7'
|
|
20
|
+
|
|
21
|
+
s.libraries = 'c++'
|
|
22
|
+
s.pod_target_xcconfig = {
|
|
23
|
+
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
|
|
24
|
+
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
|
|
25
|
+
'DEFINES_MODULE' => 'YES',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Enable modules for importing the AmplySDK framework
|
|
29
|
+
s.user_target_xcconfig = {
|
|
30
|
+
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
|
|
31
|
+
}
|
|
32
|
+
end
|
package/ios/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# iOS Placeholder
|
|
2
|
+
|
|
3
|
+
The Amply React Native Swift bridge will land once the Amply KMP XCFramework is published.
|
|
4
|
+
|
|
5
|
+
Planned steps:
|
|
6
|
+
|
|
7
|
+
1. Publish `AmplySDK.xcframework` + Swift Package.
|
|
8
|
+
2. Replace placeholder Swift stubs with the generated TurboModule implementation.
|
|
9
|
+
3. Wire CocoaPods + SPM manifests to consume the binary target.
|
|
10
|
+
|
|
11
|
+
Until then, the module intentionally rejects calls on iOS builds.
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <UIKit/UIKit.h>
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
#import <React/RCTConvert.h>
|
|
5
|
+
#import <React/RCTLog.h>
|
|
6
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
7
|
+
#import "AmplyReactNative/AmplyReactNative.h"
|
|
8
|
+
|
|
9
|
+
// Import the KMP SDK
|
|
10
|
+
#import <AmplySDK/AmplySDK.h>
|
|
11
|
+
|
|
12
|
+
using namespace facebook::react;
|
|
13
|
+
|
|
14
|
+
@interface Amply : NativeAmplyModuleSpecBase <NativeAmplyModuleSpec, ASDKDeepLinkListener>
|
|
15
|
+
@property (nonatomic, strong) ASDKAmply *amplyInstance;
|
|
16
|
+
@property (nonatomic, assign) BOOL deepLinkListenerRegistered;
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@implementation Amply
|
|
20
|
+
|
|
21
|
+
RCT_EXPORT_MODULE()
|
|
22
|
+
|
|
23
|
+
- (void)initialize:(JS::NativeAmplyModule::AmplyInitializationConfig &)config
|
|
24
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
25
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
26
|
+
{
|
|
27
|
+
@try {
|
|
28
|
+
NSString *appId = config.appId();
|
|
29
|
+
NSString *apiKeyPublic = config.apiKeyPublic();
|
|
30
|
+
NSString *apiKeySecret = config.apiKeySecret();
|
|
31
|
+
NSString *defaultConfig = config.defaultConfig();
|
|
32
|
+
|
|
33
|
+
if (!appId || appId.length == 0) {
|
|
34
|
+
if (reject) {
|
|
35
|
+
reject(@"AMP_INVALID_CONFIG", @"'appId' is required", nil);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!apiKeyPublic || apiKeyPublic.length == 0) {
|
|
41
|
+
if (reject) {
|
|
42
|
+
reject(@"AMP_INVALID_CONFIG", @"'apiKeyPublic' is required", nil);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Build the Amply config using the builder pattern
|
|
48
|
+
ASDKAmplyConfigBuilder *configBuilder = [[ASDKAmplyConfigBuilder alloc] init];
|
|
49
|
+
|
|
50
|
+
// Configure API settings using the api block
|
|
51
|
+
[configBuilder apiBlock:^(ASDKAmplyApiBuilder *apiBuilder) {
|
|
52
|
+
apiBuilder.appId = appId;
|
|
53
|
+
apiBuilder.apiKeyPublic = apiKeyPublic;
|
|
54
|
+
if (apiKeySecret && apiKeySecret.length > 0) {
|
|
55
|
+
apiBuilder.apiKeySecret = apiKeySecret;
|
|
56
|
+
}
|
|
57
|
+
}];
|
|
58
|
+
|
|
59
|
+
// Set default config if provided
|
|
60
|
+
if (defaultConfig && defaultConfig.length > 0) {
|
|
61
|
+
configBuilder.defaultConfig = defaultConfig;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
ASDKAmplyConfig *amplyConfig = [configBuilder build];
|
|
65
|
+
|
|
66
|
+
// Create Amply instance
|
|
67
|
+
self.amplyInstance = [[ASDKAmply alloc] initWithConfig:amplyConfig];
|
|
68
|
+
|
|
69
|
+
RCTLogInfo(@"[AmplyReactNative] Initialized with appId=%@", appId);
|
|
70
|
+
|
|
71
|
+
if (resolve) {
|
|
72
|
+
resolve(nil);
|
|
73
|
+
}
|
|
74
|
+
} @catch (NSException *exception) {
|
|
75
|
+
RCTLogError(@"[AmplyReactNative] Failed to initialize: %@", exception.reason);
|
|
76
|
+
if (reject) {
|
|
77
|
+
reject(@"AMP_INIT_FAILED", exception.reason, nil);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- (NSNumber *)isInitialized
|
|
83
|
+
{
|
|
84
|
+
return @(self.amplyInstance != nil);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
- (void)track:(JS::NativeAmplyModule::TrackEventPayload &)payload
|
|
88
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
89
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
90
|
+
{
|
|
91
|
+
if (!self.amplyInstance) {
|
|
92
|
+
if (reject) {
|
|
93
|
+
reject(@"AMP_NOT_INITIALIZED", @"Amply has not been initialized yet", nil);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@try {
|
|
99
|
+
NSString *eventName = payload.name();
|
|
100
|
+
|
|
101
|
+
if (!eventName || eventName.length == 0) {
|
|
102
|
+
if (reject) {
|
|
103
|
+
reject(@"AMP_INVALID_EVENT", @"Event 'name' is required", nil);
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Convert properties to NSDictionary
|
|
109
|
+
NSDictionary *properties = @{};
|
|
110
|
+
id<NSObject> propsObj = payload.properties();
|
|
111
|
+
if (propsObj && [propsObj isKindOfClass:[NSDictionary class]]) {
|
|
112
|
+
properties = (NSDictionary *)propsObj;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Use the correct method signature: trackEvent:properties:
|
|
116
|
+
[self.amplyInstance trackEvent:eventName properties:properties];
|
|
117
|
+
|
|
118
|
+
RCTLogInfo(@"[AmplyReactNative] Tracked event: %@", eventName);
|
|
119
|
+
|
|
120
|
+
if (resolve) {
|
|
121
|
+
resolve(nil);
|
|
122
|
+
}
|
|
123
|
+
} @catch (NSException *exception) {
|
|
124
|
+
RCTLogError(@"[AmplyReactNative] Failed to track event: %@", exception.reason);
|
|
125
|
+
if (reject) {
|
|
126
|
+
reject(@"AMP_TRACK_FAILED", exception.reason, nil);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
- (void)getRecentEvents:(double)limit
|
|
132
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
133
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
134
|
+
{
|
|
135
|
+
if (!self.amplyInstance) {
|
|
136
|
+
if (reject) {
|
|
137
|
+
reject(@"AMP_NOT_INITIALIZED", @"Amply has not been initialized yet", nil);
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Use the async completion handler API
|
|
143
|
+
[self.amplyInstance getRecentEventsLimit:(int32_t)limit completionHandler:^(NSArray<id<ASDKEventInterface>> *events, NSError *error) {
|
|
144
|
+
if (error) {
|
|
145
|
+
RCTLogError(@"[AmplyReactNative] Failed to get recent events: %@", error.localizedDescription);
|
|
146
|
+
if (reject) {
|
|
147
|
+
reject(@"AMP_EVENTS_FAILED", error.localizedDescription, error);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
NSMutableArray *result = [NSMutableArray array];
|
|
153
|
+
|
|
154
|
+
for (id<ASDKEventInterface> event in events) {
|
|
155
|
+
NSMutableDictionary *eventDict = [NSMutableDictionary dictionary];
|
|
156
|
+
eventDict[@"name"] = event.name;
|
|
157
|
+
eventDict[@"timestamp"] = @(event.timestamp);
|
|
158
|
+
eventDict[@"type"] = event.type.name;
|
|
159
|
+
eventDict[@"properties"] = event.properties ?: @{};
|
|
160
|
+
[result addObject:eventDict];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
RCTLogInfo(@"[AmplyReactNative] Fetched %lu recent events", (unsigned long)result.count);
|
|
164
|
+
|
|
165
|
+
if (resolve) {
|
|
166
|
+
resolve(result);
|
|
167
|
+
}
|
|
168
|
+
}];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
- (void)getDataSetSnapshot:(NSDictionary *)type
|
|
172
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
173
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
174
|
+
{
|
|
175
|
+
if (!self.amplyInstance) {
|
|
176
|
+
if (reject) {
|
|
177
|
+
reject(@"AMP_NOT_INITIALIZED", @"Amply has not been initialized yet", nil);
|
|
178
|
+
}
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
NSString *kind = type[@"kind"];
|
|
183
|
+
RCTLogInfo(@"[AmplyReactNative] getDataSetSnapshot called with kind: %@", kind);
|
|
184
|
+
|
|
185
|
+
// Convert JS type to native ASDKDataSetType
|
|
186
|
+
ASDKDataSetType *dataSetType = nil;
|
|
187
|
+
|
|
188
|
+
if ([kind isEqualToString:@"@device"]) {
|
|
189
|
+
dataSetType = ASDKDataSetTypeDevice.shared;
|
|
190
|
+
} else if ([kind isEqualToString:@"@user"]) {
|
|
191
|
+
dataSetType = ASDKDataSetTypeUser.shared;
|
|
192
|
+
} else if ([kind isEqualToString:@"@session"]) {
|
|
193
|
+
dataSetType = ASDKDataSetTypeSession.shared;
|
|
194
|
+
} else {
|
|
195
|
+
if (reject) {
|
|
196
|
+
reject(@"AMP_INVALID_TYPE", [NSString stringWithFormat:@"Unknown dataset type: %@", kind], nil);
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
[self.amplyInstance getDataSetSnapshotType:dataSetType completionHandler:^(NSDictionary<NSString *, id> *snapshot, NSError *error) {
|
|
202
|
+
if (error) {
|
|
203
|
+
RCTLogError(@"[AmplyReactNative] Failed to get data set snapshot: %@", error.localizedDescription);
|
|
204
|
+
if (reject) {
|
|
205
|
+
reject(@"AMP_DATASET_FAILED", error.localizedDescription, error);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
RCTLogInfo(@"[AmplyReactNative] Got dataset snapshot: %@", snapshot);
|
|
211
|
+
|
|
212
|
+
if (resolve) {
|
|
213
|
+
resolve(snapshot ?: @{});
|
|
214
|
+
}
|
|
215
|
+
}];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Registers a listener for deep links triggered by Amply SDK campaigns.
|
|
220
|
+
*
|
|
221
|
+
* This listener allows app developers to:
|
|
222
|
+
* 1. Know that a deep link originated from Amply SDK (vs. external sources like
|
|
223
|
+
* push notifications, browser links, or other SDKs)
|
|
224
|
+
* 2. Access campaign metadata via the `info` dictionary (campaign ID, variant, etc.)
|
|
225
|
+
* that is not available in the URL itself
|
|
226
|
+
* 3. Track/log Amply-specific deep link events for analytics
|
|
227
|
+
*
|
|
228
|
+
* Example use case:
|
|
229
|
+
* // In JS:
|
|
230
|
+
* Amply.addDeepLinkListener(event => {
|
|
231
|
+
* // We know this deep link came from an Amply campaign, not from elsewhere
|
|
232
|
+
* analytics.track('Amply campaign triggered', { url: event.url, info: event.info });
|
|
233
|
+
* });
|
|
234
|
+
*
|
|
235
|
+
* The deep link flow:
|
|
236
|
+
* Campaign triggers → KMP SDK → onDeepLink callback → JS event emitted
|
|
237
|
+
* ↓ (then)
|
|
238
|
+
* UIApplication.openURL() → Linking API
|
|
239
|
+
*
|
|
240
|
+
* Note: The listener is an observer, not a controller. The SDK will still open
|
|
241
|
+
* the URL via system after emitting the event.
|
|
242
|
+
*
|
|
243
|
+
* This ensures feature parity with Android implementation.
|
|
244
|
+
*/
|
|
245
|
+
- (void)registerDeepLinkListener
|
|
246
|
+
{
|
|
247
|
+
if (!self.amplyInstance) {
|
|
248
|
+
RCTLogWarn(@"[AmplyReactNative] Cannot register deep link listener - Amply not initialized");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (self.deepLinkListenerRegistered) {
|
|
253
|
+
RCTLogInfo(@"[AmplyReactNative] Deep link listener already registered");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
RCTLogInfo(@"[AmplyReactNative] Registering deep link listener");
|
|
258
|
+
[self.amplyInstance registerDeepLinkListenerListener:self];
|
|
259
|
+
self.deepLinkListenerRegistered = YES;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#pragma mark - ASDKDeepLinkListener
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Called by KMP SDK when a campaign triggers a deep link action.
|
|
266
|
+
*
|
|
267
|
+
* @param url The deep link URL configured in the campaign
|
|
268
|
+
* @param info Campaign metadata (may include campaign ID, action data, etc.)
|
|
269
|
+
* @return YES if the deep link was fully handled (SDK won't open URL via system)
|
|
270
|
+
* NO to let SDK also open the URL via UIApplication.openURL()
|
|
271
|
+
*
|
|
272
|
+
* Current implementation:
|
|
273
|
+
* 1. Emits event to JS via Amply.addDeepLinkListener() for custom handling/logging
|
|
274
|
+
* 2. Opens URL using modern UIApplication.open(_:options:completionHandler:) API
|
|
275
|
+
* 3. Returns YES to prevent SDK from using deprecated UIApplication.openURL()
|
|
276
|
+
*
|
|
277
|
+
* Note: KMP SDK uses deprecated UIApplication.openURL() which returns NO on iOS 18+,
|
|
278
|
+
* so we handle URL opening ourselves using the modern API.
|
|
279
|
+
*/
|
|
280
|
+
- (BOOL)onDeepLinkUrl:(NSString *)url info:(NSDictionary<NSString *, id> *)info
|
|
281
|
+
{
|
|
282
|
+
RCTLogInfo(@"[AmplyReactNative] Received deep link from Amply: url=%@", url);
|
|
283
|
+
|
|
284
|
+
NSDictionary *payload = @{
|
|
285
|
+
@"url": url ?: @"",
|
|
286
|
+
@"info": info ?: @{},
|
|
287
|
+
@"consumed": @NO
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
[self emitOnDeepLink:payload];
|
|
291
|
+
|
|
292
|
+
// For custom scheme URLs (e.g., amply://), let JS handle navigation via the event above.
|
|
293
|
+
// For external URLs (http/https), open via system.
|
|
294
|
+
NSURL *nsUrl = [NSURL URLWithString:url];
|
|
295
|
+
if (nsUrl) {
|
|
296
|
+
NSString *scheme = nsUrl.scheme.lowercaseString;
|
|
297
|
+
BOOL isExternalUrl = [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"];
|
|
298
|
+
|
|
299
|
+
if (isExternalUrl) {
|
|
300
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
301
|
+
[[UIApplication sharedApplication] openURL:nsUrl
|
|
302
|
+
options:@{}
|
|
303
|
+
completionHandler:^(BOOL success) {
|
|
304
|
+
if (!success) {
|
|
305
|
+
RCTLogWarn(@"[AmplyReactNative] Failed to open URL: %@", url);
|
|
306
|
+
}
|
|
307
|
+
}];
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return YES; // Tell SDK we handled it
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
- (void)addListener:(NSString *)eventName
|
|
316
|
+
{
|
|
317
|
+
// Required by RN EventEmitter contracts.
|
|
318
|
+
RCTLogInfo(@"[AmplyReactNative] addListener called for event: %@", eventName);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
- (void)removeListeners:(double)count
|
|
322
|
+
{
|
|
323
|
+
// Required by RN EventEmitter contracts.
|
|
324
|
+
RCTLogInfo(@"[AmplyReactNative] removeListeners called with count: %f", count);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
- (std::shared_ptr<TurboModule>)getTurboModule:(const ObjCTurboModule::InitParams &)params
|
|
328
|
+
{
|
|
329
|
+
return std::make_shared<NativeAmplyModuleSpecJSI>(params);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
@end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
3
|
+
*
|
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
5
|
+
* once the code is regenerated.
|
|
6
|
+
*
|
|
7
|
+
* @generated by codegen project: GenerateModuleObjCpp
|
|
8
|
+
*
|
|
9
|
+
* We create an umbrella header (and corresponding implementation) here since
|
|
10
|
+
* Cxx compilation in BUCK has a limitation: source-code producing genrule()s
|
|
11
|
+
* must have a single output. More files => more genrule()s => slower builds.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#import "AmplyReactNative.h"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@implementation NativeAmplyModuleSpecBase
|
|
18
|
+
- (void)emitOnSystemEvent:(NSDictionary *)value
|
|
19
|
+
{
|
|
20
|
+
_eventEmitterCallback("onSystemEvent", value);
|
|
21
|
+
}
|
|
22
|
+
- (void)emitOnDeepLink:(NSDictionary *)value
|
|
23
|
+
{
|
|
24
|
+
_eventEmitterCallback("onDeepLink", value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper
|
|
28
|
+
{
|
|
29
|
+
_eventEmitterCallback = std::move(eventEmitterCallbackWrapper->_eventEmitterCallback);
|
|
30
|
+
}
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
@implementation RCTCxxConvert (NativeAmplyModule_AmplyInitializationConfig)
|
|
34
|
+
+ (RCTManagedPointer *)JS_NativeAmplyModule_AmplyInitializationConfig:(id)json
|
|
35
|
+
{
|
|
36
|
+
return facebook::react::managedPointer<JS::NativeAmplyModule::AmplyInitializationConfig>(json);
|
|
37
|
+
}
|
|
38
|
+
@end
|
|
39
|
+
@implementation RCTCxxConvert (NativeAmplyModule_TrackEventPayload)
|
|
40
|
+
+ (RCTManagedPointer *)JS_NativeAmplyModule_TrackEventPayload:(id)json
|
|
41
|
+
{
|
|
42
|
+
return facebook::react::managedPointer<JS::NativeAmplyModule::TrackEventPayload>(json);
|
|
43
|
+
}
|
|
44
|
+
@end
|
|
45
|
+
namespace facebook::react {
|
|
46
|
+
|
|
47
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_initialize(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
48
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "initialize", @selector(initialize:resolve:reject:), args, count);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_isInitialized(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
52
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, BooleanKind, "isInitialized", @selector(isInitialized), args, count);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_track(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
56
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "track", @selector(track:resolve:reject:), args, count);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_getRecentEvents(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
60
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "getRecentEvents", @selector(getRecentEvents:resolve:reject:), args, count);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_getDataSetSnapshot(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
64
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, PromiseKind, "getDataSetSnapshot", @selector(getDataSetSnapshot:resolve:reject:), args, count);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_registerDeepLinkListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
68
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "registerDeepLinkListener", @selector(registerDeepLinkListener), args, count);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_addListener(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
72
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "addListener", @selector(addListener:), args, count);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static facebook::jsi::Value __hostFunction_NativeAmplyModuleSpecJSI_removeListeners(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
|
|
76
|
+
return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, VoidKind, "removeListeners", @selector(removeListeners:), args, count);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
NativeAmplyModuleSpecJSI::NativeAmplyModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms)
|
|
80
|
+
: ObjCTurboModule(params) {
|
|
81
|
+
|
|
82
|
+
methodMap_["initialize"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_initialize};
|
|
83
|
+
setMethodArgConversionSelector(@"initialize", 0, @"JS_NativeAmplyModule_AmplyInitializationConfig:");
|
|
84
|
+
|
|
85
|
+
methodMap_["isInitialized"] = MethodMetadata {0, __hostFunction_NativeAmplyModuleSpecJSI_isInitialized};
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
methodMap_["track"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_track};
|
|
89
|
+
setMethodArgConversionSelector(@"track", 0, @"JS_NativeAmplyModule_TrackEventPayload:");
|
|
90
|
+
|
|
91
|
+
methodMap_["getRecentEvents"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_getRecentEvents};
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
methodMap_["getDataSetSnapshot"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_getDataSetSnapshot};
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
methodMap_["registerDeepLinkListener"] = MethodMetadata {0, __hostFunction_NativeAmplyModuleSpecJSI_registerDeepLinkListener};
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
methodMap_["addListener"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_addListener};
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
methodMap_["removeListeners"] = MethodMetadata {1, __hostFunction_NativeAmplyModuleSpecJSI_removeListeners};
|
|
104
|
+
|
|
105
|
+
eventEmitterMap_["onSystemEvent"] = std::make_shared<AsyncEventEmitter<id>>();
|
|
106
|
+
eventEmitterMap_["onDeepLink"] = std::make_shared<AsyncEventEmitter<id>>();
|
|
107
|
+
setEventEmitterCallback([&](const std::string &name, id value) {
|
|
108
|
+
static_cast<AsyncEventEmitter<id> &>(*eventEmitterMap_[name]).emit(value);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
3
|
+
*
|
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
5
|
+
* once the code is regenerated.
|
|
6
|
+
*
|
|
7
|
+
* @generated by codegen project: GenerateModuleObjCpp
|
|
8
|
+
*
|
|
9
|
+
* We create an umbrella header (and corresponding implementation) here since
|
|
10
|
+
* Cxx compilation in BUCK has a limitation: source-code producing genrule()s
|
|
11
|
+
* must have a single output. More files => more genrule()s => slower builds.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#ifndef __cplusplus
|
|
15
|
+
#error This file must be compiled as Obj-C++. If you are importing it, you must change your file extension to .mm.
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
// Avoid multiple includes of AmplyReactNative symbols
|
|
19
|
+
#ifndef AmplyReactNative_H
|
|
20
|
+
#define AmplyReactNative_H
|
|
21
|
+
|
|
22
|
+
#import <Foundation/Foundation.h>
|
|
23
|
+
#import <RCTRequired/RCTRequired.h>
|
|
24
|
+
#import <RCTTypeSafety/RCTConvertHelpers.h>
|
|
25
|
+
#import <RCTTypeSafety/RCTTypedModuleConstants.h>
|
|
26
|
+
#import <React/RCTBridgeModule.h>
|
|
27
|
+
#import <React/RCTCxxConvert.h>
|
|
28
|
+
#import <React/RCTManagedPointer.h>
|
|
29
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
30
|
+
#import <optional>
|
|
31
|
+
#import <vector>
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
35
|
+
namespace JS {
|
|
36
|
+
namespace NativeAmplyModule {
|
|
37
|
+
struct AmplyInitializationConfig {
|
|
38
|
+
NSString *appId() const;
|
|
39
|
+
NSString *apiKeyPublic() const;
|
|
40
|
+
NSString *apiKeySecret() const;
|
|
41
|
+
NSString *endpoint() const;
|
|
42
|
+
id<NSObject> _Nullable datasetPrefetch() const;
|
|
43
|
+
NSString *defaultConfig() const;
|
|
44
|
+
|
|
45
|
+
AmplyInitializationConfig(NSDictionary *const v) : _v(v) {}
|
|
46
|
+
private:
|
|
47
|
+
NSDictionary *_v;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@interface RCTCxxConvert (NativeAmplyModule_AmplyInitializationConfig)
|
|
53
|
+
+ (RCTManagedPointer *)JS_NativeAmplyModule_AmplyInitializationConfig:(id)json;
|
|
54
|
+
@end
|
|
55
|
+
namespace JS {
|
|
56
|
+
namespace NativeAmplyModule {
|
|
57
|
+
struct TrackEventPayload {
|
|
58
|
+
NSString *name() const;
|
|
59
|
+
id<NSObject> _Nullable properties() const;
|
|
60
|
+
|
|
61
|
+
TrackEventPayload(NSDictionary *const v) : _v(v) {}
|
|
62
|
+
private:
|
|
63
|
+
NSDictionary *_v;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@interface RCTCxxConvert (NativeAmplyModule_TrackEventPayload)
|
|
69
|
+
+ (RCTManagedPointer *)JS_NativeAmplyModule_TrackEventPayload:(id)json;
|
|
70
|
+
@end
|
|
71
|
+
@protocol NativeAmplyModuleSpec <RCTBridgeModule, RCTTurboModule>
|
|
72
|
+
|
|
73
|
+
- (void)initialize:(JS::NativeAmplyModule::AmplyInitializationConfig &)config
|
|
74
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
75
|
+
reject:(RCTPromiseRejectBlock)reject;
|
|
76
|
+
- (NSNumber *)isInitialized;
|
|
77
|
+
- (void)track:(JS::NativeAmplyModule::TrackEventPayload &)payload
|
|
78
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
79
|
+
reject:(RCTPromiseRejectBlock)reject;
|
|
80
|
+
- (void)getRecentEvents:(double)limit
|
|
81
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
82
|
+
reject:(RCTPromiseRejectBlock)reject;
|
|
83
|
+
- (void)getDataSetSnapshot:(NSDictionary *)type
|
|
84
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
85
|
+
reject:(RCTPromiseRejectBlock)reject;
|
|
86
|
+
- (void)registerDeepLinkListener;
|
|
87
|
+
- (void)addListener:(NSString *)eventName;
|
|
88
|
+
- (void)removeListeners:(double)count;
|
|
89
|
+
|
|
90
|
+
@end
|
|
91
|
+
|
|
92
|
+
@interface NativeAmplyModuleSpecBase : NSObject {
|
|
93
|
+
@protected
|
|
94
|
+
facebook::react::EventEmitterCallback _eventEmitterCallback;
|
|
95
|
+
}
|
|
96
|
+
- (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper;
|
|
97
|
+
|
|
98
|
+
- (void)emitOnSystemEvent:(NSDictionary *)value;
|
|
99
|
+
- (void)emitOnDeepLink:(NSDictionary *)value;
|
|
100
|
+
@end
|
|
101
|
+
|
|
102
|
+
namespace facebook::react {
|
|
103
|
+
/**
|
|
104
|
+
* ObjC++ class for module 'NativeAmplyModule'
|
|
105
|
+
*/
|
|
106
|
+
class JSI_EXPORT NativeAmplyModuleSpecJSI : public ObjCTurboModule {
|
|
107
|
+
public:
|
|
108
|
+
NativeAmplyModuleSpecJSI(const ObjCTurboModule::InitParams ¶ms);
|
|
109
|
+
};
|
|
110
|
+
} // namespace facebook::react
|
|
111
|
+
inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::appId() const
|
|
112
|
+
{
|
|
113
|
+
id const p = _v[@"appId"];
|
|
114
|
+
return RCTBridgingToString(p);
|
|
115
|
+
}
|
|
116
|
+
inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::apiKeyPublic() const
|
|
117
|
+
{
|
|
118
|
+
id const p = _v[@"apiKeyPublic"];
|
|
119
|
+
return RCTBridgingToString(p);
|
|
120
|
+
}
|
|
121
|
+
inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::apiKeySecret() const
|
|
122
|
+
{
|
|
123
|
+
id const p = _v[@"apiKeySecret"];
|
|
124
|
+
return RCTBridgingToOptionalString(p);
|
|
125
|
+
}
|
|
126
|
+
inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::endpoint() const
|
|
127
|
+
{
|
|
128
|
+
id const p = _v[@"endpoint"];
|
|
129
|
+
return RCTBridgingToOptionalString(p);
|
|
130
|
+
}
|
|
131
|
+
inline id<NSObject> _Nullable JS::NativeAmplyModule::AmplyInitializationConfig::datasetPrefetch() const
|
|
132
|
+
{
|
|
133
|
+
id const p = _v[@"datasetPrefetch"];
|
|
134
|
+
return p;
|
|
135
|
+
}
|
|
136
|
+
inline NSString *JS::NativeAmplyModule::AmplyInitializationConfig::defaultConfig() const
|
|
137
|
+
{
|
|
138
|
+
id const p = _v[@"defaultConfig"];
|
|
139
|
+
return RCTBridgingToOptionalString(p);
|
|
140
|
+
}
|
|
141
|
+
inline NSString *JS::NativeAmplyModule::TrackEventPayload::name() const
|
|
142
|
+
{
|
|
143
|
+
id const p = _v[@"name"];
|
|
144
|
+
return RCTBridgingToString(p);
|
|
145
|
+
}
|
|
146
|
+
inline id<NSObject> _Nullable JS::NativeAmplyModule::TrackEventPayload::properties() const
|
|
147
|
+
{
|
|
148
|
+
id const p = _v[@"properties"];
|
|
149
|
+
return p;
|
|
150
|
+
}
|
|
151
|
+
NS_ASSUME_NONNULL_END
|
|
152
|
+
#endif // AmplyReactNative_H
|