react-native-cliqit 0.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.
Files changed (39) hide show
  1. package/README.md +209 -0
  2. package/android/build.gradle +27 -0
  3. package/android/src/main/AndroidManifest.xml +1 -0
  4. package/android/src/main/java/com/cliqit/CliqItModule.kt +242 -0
  5. package/android/src/main/java/com/cliqit/CliqItPackage.kt +14 -0
  6. package/android/src/main/java/com/cliqit/sdk/CliqItDefaults.kt +17 -0
  7. package/android/src/main/java/com/cliqit/sdk/CliqItDeviceInfo.kt +196 -0
  8. package/android/src/main/java/com/cliqit/sdk/CliqItHttp.kt +98 -0
  9. package/android/src/main/java/com/cliqit/sdk/CliqItModels.kt +130 -0
  10. package/android/src/main/java/com/cliqit/sdk/CliqItSDK.kt +514 -0
  11. package/android/src/main/java/com/cliqit/sdk/CliqItWebFingerprint.kt +230 -0
  12. package/ios/CliqItModule.m +14 -0
  13. package/ios/CliqItModule.swift +238 -0
  14. package/ios/Frameworks/CliqIt.xcframework/Info.plist +44 -0
  15. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/CliqIt +0 -0
  16. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Headers/CliqIt-Swift.h +382 -0
  17. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Info.plist +0 -0
  18. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios.abi.json +12111 -0
  19. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios.private.swiftinterface +419 -0
  20. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  21. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios.swiftinterface +419 -0
  22. package/ios/Frameworks/CliqIt.xcframework/ios-arm64/CliqIt.framework/Modules/module.modulemap +3 -0
  23. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/CliqIt +0 -0
  24. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Headers/CliqIt-Swift.h +760 -0
  25. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Info.plist +0 -0
  26. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios-simulator.abi.json +12111 -0
  27. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +419 -0
  28. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  29. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/arm64-apple-ios-simulator.swiftinterface +419 -0
  30. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/x86_64-apple-ios-simulator.abi.json +12111 -0
  31. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +419 -0
  32. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  33. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/CliqIt.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +419 -0
  34. package/ios/Frameworks/CliqIt.xcframework/ios-arm64_x86_64-simulator/CliqIt.framework/Modules/module.modulemap +3 -0
  35. package/package.json +48 -0
  36. package/react-native-cliqit.podspec +27 -0
  37. package/react-native.config.js +11 -0
  38. package/src/index.d.ts +92 -0
  39. package/src/index.js +152 -0
package/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # react-native-cliqit
2
+
3
+ React Native bridge for **CliqIt** deferred deep linking.
4
+
5
+ - **iOS:** ships `CliqIt.xcframework` (closed-source native SDK)
6
+ - **Android:** Kotlin SDK + RN bridge included
7
+ - **No npm publish required** — install from Git
8
+
9
+ **Version:** `2.0.6`
10
+
11
+ ## Install (Git)
12
+
13
+ ```bash
14
+ npm install git+https://github.com/mindrootstech/react-native-cliqit.git#v2.0.6
15
+ # or yarn / pnpm equivalent
16
+
17
+ cd ios && pod install && cd ..
18
+ ```
19
+
20
+ `package.json`:
21
+
22
+ ```json
23
+ "dependencies": {
24
+ "react-native-cliqit": "git+https://github.com/mindrootstech/react-native-cliqit.git#v2.0.6"
25
+ }
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ All APIs use a `{ result, error }` callback object.
31
+
32
+ Register listeners **before** `configure` — deferred match can finish very fast.
33
+
34
+ ```js
35
+ import { useEffect } from 'react';
36
+ import { Linking } from 'react-native';
37
+ import CliqIt from 'react-native-cliqit';
38
+
39
+ useEffect(() => {
40
+ // onDeepLink — runs when the app should navigate:
41
+ // • Direct: user opens a SmartLink / App Link while app is installed (isDeferred: false)
42
+ // • Deferred: after a successful first-open match, SDK delivers the path (isDeferred: true)
43
+ const offDeepLink = CliqIt.onDeepLink(({ result, error }) => {
44
+ if (error) return;
45
+ console.log('deep link', result.path, result.isDeferred);
46
+ });
47
+
48
+ // onDeferredMatch — runs once on cold start / configure (first install attribution):
49
+ // Server fingerprint match result (matched / notMatched / alreadyReported + score/slug/path).
50
+ // Does NOT mean "navigate by itself" — if matched, onDeepLink usually fires next.
51
+ const offMatch = CliqIt.onDeferredMatch(({ result, error }) => {
52
+ if (error) return;
53
+ if (result?.status === 'matched') {
54
+ console.log('deferred', result.destinationPath);
55
+ }
56
+ });
57
+
58
+ // onLinkLookup — runs on direct SmartLink open when SDK resolves slug → destination via API.
59
+ // Not used for pure deferred-only first open (unless a URL was also handled).
60
+ const offLookup = CliqIt.onLinkLookup(({ result, error }) => {
61
+ if (error) return;
62
+ console.log('link lookup', result?.resolvedPath ?? result?.slug);
63
+ });
64
+
65
+ // onVerify — runs after configure (background): API key + package/bundle (/ SHA) identity check.
66
+ const offVerify = CliqIt.onVerify(({ result, error }) => {
67
+ console.log('verify', error || result?.status);
68
+ });
69
+
70
+ // configure — call once at startup (after listeners). Starts verify + deferred match.
71
+ CliqIt.configure({ apiKey: 'pk_live_…' }, ({ result, error }) => {
72
+ console.log('configured', result, error);
73
+ });
74
+
75
+ // handleUrl — pass Universal Links / App Links / custom-scheme URLs into the SDK.
76
+ // Cold start: Linking.getInitialURL(). Warm: Linking 'url' event.
77
+ Linking.getInitialURL().then((url) => {
78
+ if (url) CliqIt.handleUrl({ url }, ({ error }) => {});
79
+ });
80
+ const linkSub = Linking.addEventListener('url', ({ url }) => {
81
+ CliqIt.handleUrl({ url });
82
+ });
83
+
84
+ return () => {
85
+ offDeepLink();
86
+ offMatch();
87
+ offLookup();
88
+ offVerify();
89
+ linkSub.remove();
90
+ };
91
+ }, []);
92
+ ```
93
+
94
+
95
+ ## Callback results
96
+
97
+ Every listener / action callback receives:
98
+
99
+ ```ts
100
+ { result: object | null, error: string | null }
101
+ ```
102
+
103
+ - On success: `error` is `null`, use `result`
104
+ - On failure: `result` is `null`, use `error`
105
+
106
+ ### `configure({ apiKey }, cb)`
107
+
108
+ | Field | Type | Notes |
109
+ |-------|------|--------|
110
+ | `result.ok` | `boolean` | `true` when configure was accepted locally |
111
+ | `error` | `string` | Missing `apiKey`, or native throw |
112
+
113
+ Starts background **verify** + **deferred match** (listeners should be registered first).
114
+
115
+ ### `handleUrl({ url }, cb)`
116
+
117
+ | Field | Type | Notes |
118
+ |-------|------|--------|
119
+ | `result.ok` | `boolean` | URL was passed into the native SDK |
120
+ | `result.url` | `string` | Same URL you passed |
121
+ | `error` | `string` | Missing / invalid `url` |
122
+
123
+ Use for Universal Links / App Links / custom schemes (cold start + warm).
124
+
125
+ ### `onDeepLink(({ result, error }) => …)`
126
+
127
+ Navigation payload — **direct** opens and **deferred delivery**.
128
+
129
+ | Field | Type | Notes |
130
+ |-------|------|--------|
131
+ | `result.url` | `string` | Original or synthetic URL |
132
+ | `result.path` | `string` | In-app path (usually starts with `/`) |
133
+ | `result.pathComponents` | `string[]` | Path segments |
134
+ | `result.query` | `object` | Query key → value |
135
+ | `result.source` | `string` | e.g. `deferred`, `universalLink`, `customScheme` |
136
+ | `result.isDeferred` | `boolean` | `true` if from deferred match delivery |
137
+ | `error` | `string` | Rare bridge/payload issues |
138
+
139
+ ### `onDeferredMatch(({ result, error }) => …)`
140
+
141
+ First-open **attribution** only (not navigation by itself).
142
+
143
+ | Field | Type | When |
144
+ |-------|------|------|
145
+ | `result.status` | `string` | `matched` \| `notMatched` \| `alreadyReported` |
146
+ | `result.destinationPath` | `string?` | Matched in-app destination (may omit leading `/`) |
147
+ | `result.slug` | `string?` | SmartLink slug |
148
+ | `result.score` | `number?` | Match score |
149
+ | `result.tier` | `string?` | e.g. `probabilistic` |
150
+ | `result.confidence` | `string?` | e.g. `medium` |
151
+ | `result.note` | `string?` | Present when `alreadyReported` |
152
+ | `error` | `string` | Match request / decode failure (`status: failed`) |
153
+
154
+ If `status === 'matched'`, `onDeepLink` usually fires next with `isDeferred: true`.
155
+
156
+ ### `onLinkLookup(({ result, error }) => …)`
157
+
158
+ Direct SmartLink **slug → destination** API resolve.
159
+
160
+ | Field | Type | Notes |
161
+ |-------|------|--------|
162
+ | `result.status` | `string` | `resolved` on success |
163
+ | `result.resolvedPath` | `string?` | Platform path (`iosDestination` / `androidDestination` / `destination`) |
164
+ | `result.slug` | `string?` | Link slug |
165
+ | `result.destination` | `string?` | Default destination |
166
+ | `result.iosDestination` | `string?` | iOS-specific path |
167
+ | `result.androidDestination` | `string?` | Android-specific path |
168
+ | `result.ogTitle` / `ogDescription` / `ogImage` / `ogUrl` | `string?` | Open Graph fields |
169
+ | `result.webFallback` | `string?` | Web fallback URL |
170
+ | `result.showInterstitial` | `string?` | `"true"` / `"false"` when present |
171
+ | `result.isDeepLink` | `string?` | `"true"` / `"false"` when present |
172
+ | `result.appleTeamId` | `string?` | iOS team id |
173
+ | `result.iosBundleId` | `string?` | Expected iOS bundle |
174
+ | `result.androidPackageName` | `string?` | Expected Android package |
175
+ | `error` | `string` | Lookup failed |
176
+
177
+ Prefer `CliqIt.LinkField.resolvedPath` (and other `LinkField` keys) instead of raw strings.
178
+
179
+ ### `onVerify(({ result, error }) => …)`
180
+
181
+ Runs after `configure` — API key / app identity check.
182
+
183
+ | Field | Type | Notes |
184
+ |-------|------|--------|
185
+ | `result.status` | `string` | `ok` \| `mismatch` |
186
+ | `result.ok` | `boolean` | Same as server `ok` |
187
+ | `result.appId` | `string?` | App id from admin |
188
+ | `result.appName` | `string?` | App display name |
189
+ | `result.message` | `string?` | Human-readable summary |
190
+ | `result.checks` | `object?` | Per-field `{ actual, expected, match }` (bundle / package / SHA) |
191
+ | `result.raw` | `string?` | Raw JSON body (if provided by native) |
192
+ | `error` | `string` | Network / decode / failed verify transport |
193
+
194
+ `mismatch` stays in `result` (identity problem, not a dropped callback). Transport failures use `error`.
195
+
196
+ ## App setup
197
+
198
+ ### iOS
199
+ - Associated Domains: `applinks:<your-smartlink-domain>`
200
+ - iOS 15+
201
+
202
+ ### Android
203
+ - App Links intent-filter for your SmartLink host
204
+ - Autolinking registers `CliqItPackage` (RN 0.60+)
205
+
206
+ ## Notes
207
+
208
+ - This repo is **SDK only** — no demo app code.
209
+ - Native iOS binary alone (without RN): https://github.com/mindrootstech/CliqIt
@@ -0,0 +1,27 @@
1
+ buildscript {
2
+ ext.safeExtGet = { prop, fallback ->
3
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
4
+ }
5
+ }
6
+
7
+ apply plugin: 'com.android.library'
8
+ apply plugin: 'org.jetbrains.kotlin.android'
9
+
10
+ android {
11
+ namespace "com.cliqit"
12
+ compileSdkVersion safeExtGet('compileSdkVersion', 35)
13
+
14
+ defaultConfig {
15
+ minSdkVersion safeExtGet('minSdkVersion', 24)
16
+ }
17
+
18
+ sourceSets {
19
+ main {
20
+ java.srcDirs = ['src/main/java']
21
+ }
22
+ }
23
+ }
24
+
25
+ dependencies {
26
+ implementation "com.facebook.react:react-android"
27
+ }
@@ -0,0 +1 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android" />
@@ -0,0 +1,242 @@
1
+ package com.cliqit
2
+
3
+ import com.cliqit.sdk.CliqItSDK
4
+ import com.cliqit.sdk.DeferredMatchOutcome
5
+ import com.cliqit.sdk.LinkField
6
+ import com.cliqit.sdk.LinkLookupResult
7
+ import com.cliqit.sdk.VerifyOutcome
8
+ import com.facebook.react.bridge.Arguments
9
+ import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
11
+ import com.facebook.react.bridge.ReactMethod
12
+ import com.facebook.react.bridge.WritableMap
13
+ import com.facebook.react.modules.core.DeviceEventManagerModule
14
+
15
+ class CliqItModule(private val reactContext: ReactApplicationContext) :
16
+ ReactContextBaseJavaModule(reactContext) {
17
+
18
+ private var hasListeners = false
19
+ private var pendingDeepLink: WritableMap? = null
20
+ private var pendingDeferredMatch: WritableMap? = null
21
+ private var pendingLinkLookup: WritableMap? = null
22
+ private var pendingVerify: WritableMap? = null
23
+ private var handlersBound = false
24
+
25
+ override fun getName(): String = "CliqItModule"
26
+
27
+ override fun getConstants(): MutableMap<String, Any> = hashMapOf(
28
+ "LinkField" to hashMapOf(
29
+ "destination" to LinkField.destination,
30
+ "iosDestination" to LinkField.iosDestination,
31
+ "androidDestination" to LinkField.androidDestination,
32
+ "ogTitle" to LinkField.ogTitle,
33
+ "ogDescription" to LinkField.ogDescription,
34
+ "ogImage" to LinkField.ogImage,
35
+ "ogUrl" to LinkField.ogUrl,
36
+ "slug" to LinkField.slug,
37
+ "webFallback" to LinkField.webFallback,
38
+ "showInterstitial" to LinkField.showInterstitial,
39
+ "isDeepLink" to LinkField.isDeepLink,
40
+ "appleTeamId" to LinkField.appleTeamId,
41
+ "iosBundleId" to LinkField.iosBundleId,
42
+ "androidPackageName" to LinkField.androidPackageName,
43
+ "resolvedPath" to LinkField.resolvedPath,
44
+ ),
45
+ )
46
+
47
+ @ReactMethod
48
+ fun addListener(eventName: String) {
49
+ hasListeners = true
50
+ flushPending()
51
+ }
52
+
53
+ @ReactMethod
54
+ fun removeListeners(count: Int) {
55
+ if (count > 0) hasListeners = false
56
+ }
57
+
58
+ @ReactMethod
59
+ fun configure(apiKey: String) {
60
+ CliqItSDK.init(reactContext)
61
+ bindHandlersIfNeeded()
62
+ CliqItSDK.configure(apiKey)
63
+
64
+ if (CliqItSDK.hasDeferredMatchBeenReported && !CliqItSDK.isDeferredMatchInFlight) {
65
+ emitOrBuffer(
66
+ "CliqItDeferredMatch",
67
+ Arguments.createMap().apply {
68
+ putString("status", "alreadyReported")
69
+ putString(
70
+ "note",
71
+ "Deferred match already ran on this install. Clear app data to retest.",
72
+ )
73
+ },
74
+ ) { pendingDeferredMatch = it }
75
+ }
76
+ }
77
+
78
+ @ReactMethod
79
+ fun handleUrl(url: String) {
80
+ CliqItSDK.init(reactContext)
81
+ CliqItSDK.handle(url)
82
+ }
83
+
84
+ private fun bindHandlersIfNeeded() {
85
+ if (handlersBound) return
86
+ handlersBound = true
87
+
88
+ CliqItSDK.onDeepLink { payload ->
89
+ val query = Arguments.createMap()
90
+ payload.query.forEach { (k, v) -> query.putString(k, v) }
91
+ val components = Arguments.createArray()
92
+ payload.pathComponents.forEach { components.pushString(it) }
93
+ val map = Arguments.createMap().apply {
94
+ putString("url", payload.url)
95
+ putString("path", payload.path)
96
+ putArray("pathComponents", components)
97
+ putMap("query", query)
98
+ putString("source", payload.source)
99
+ putBoolean("isDeferred", payload.isDeferred)
100
+ }
101
+ emitOrBuffer("CliqItDeepLink", map) { pendingDeepLink = it }
102
+ }
103
+
104
+ CliqItSDK.onDeferredMatch { outcome ->
105
+ val map = Arguments.createMap()
106
+ when (outcome) {
107
+ is DeferredMatchOutcome.Matched -> {
108
+ map.putString("status", "matched")
109
+ putOpt(map, "destinationPath", outcome.info.destinationPath)
110
+ putOpt(map, "slug", outcome.info.slug)
111
+ putOpt(map, "tier", outcome.info.tier)
112
+ putOpt(map, "confidence", outcome.info.confidence)
113
+ outcome.info.score?.let { map.putDouble("score", it) }
114
+ }
115
+ is DeferredMatchOutcome.NotMatched -> {
116
+ map.putString("status", "notMatched")
117
+ putOpt(map, "tier", outcome.info.tier)
118
+ outcome.info.score?.let { map.putDouble("score", it) }
119
+ }
120
+ is DeferredMatchOutcome.Failed -> {
121
+ map.putString("status", "failed")
122
+ map.putString("error", outcome.error)
123
+ }
124
+ }
125
+ emitOrBuffer("CliqItDeferredMatch", map) { pendingDeferredMatch = it }
126
+ }
127
+
128
+ CliqItSDK.onDirectLinkLookup { result ->
129
+ val map = Arguments.createMap()
130
+ when (result) {
131
+ is LinkLookupResult.Resolved -> {
132
+ val d = result.details
133
+ map.putString("status", "resolved")
134
+ putOpt(map, LinkField.destination, d.destination)
135
+ putOpt(map, LinkField.iosDestination, d.iosDestination)
136
+ putOpt(map, LinkField.androidDestination, d.androidDestination)
137
+ putOpt(map, LinkField.ogTitle, d.ogTitle)
138
+ putOpt(map, LinkField.ogDescription, d.ogDescription)
139
+ putOpt(map, LinkField.ogImage, d.ogImage)
140
+ putOpt(map, LinkField.ogUrl, d.ogUrl)
141
+ putOpt(map, LinkField.slug, d.slug)
142
+ putOpt(map, LinkField.webFallback, d.webFallback)
143
+ putOpt(map, LinkField.showInterstitial, d.field(LinkField.showInterstitial))
144
+ putOpt(map, LinkField.isDeepLink, d.field(LinkField.isDeepLink))
145
+ putOpt(map, LinkField.appleTeamId, d.appleTeamId)
146
+ putOpt(map, LinkField.iosBundleId, d.iosBundleId)
147
+ putOpt(map, LinkField.androidPackageName, d.androidPackageName)
148
+ putOpt(map, LinkField.resolvedPath, d.resolvedPath)
149
+ }
150
+ is LinkLookupResult.Failed -> {
151
+ map.putString("status", "failed")
152
+ map.putString("error", result.error)
153
+ }
154
+ }
155
+ emitOrBuffer("CliqItLinkLookup", map) { pendingLinkLookup = it }
156
+ }
157
+
158
+ CliqItSDK.onVerify { outcome ->
159
+ val map = Arguments.createMap()
160
+ when (outcome) {
161
+ is VerifyOutcome.Passed -> {
162
+ map.putString("status", "ok")
163
+ map.putBoolean("ok", true)
164
+ putOpt(map, "appId", outcome.result.appId)
165
+ putOpt(map, "appName", outcome.result.appName)
166
+ map.putString("message", outcome.result.mismatchMessage)
167
+ map.putMap("checks", checksMap(outcome.result.checks))
168
+ map.putString("raw", outcome.result.rawJSON)
169
+ }
170
+ is VerifyOutcome.Mismatched -> {
171
+ map.putString("status", "mismatch")
172
+ map.putBoolean("ok", false)
173
+ putOpt(map, "appId", outcome.result.appId)
174
+ putOpt(map, "appName", outcome.result.appName)
175
+ map.putString("message", outcome.result.mismatchMessage)
176
+ map.putMap("checks", checksMap(outcome.result.checks))
177
+ map.putString("raw", outcome.result.rawJSON)
178
+ }
179
+ is VerifyOutcome.Error -> {
180
+ map.putString("status", "failed")
181
+ map.putBoolean("ok", false)
182
+ map.putString("error", outcome.message)
183
+ }
184
+ }
185
+ emitOrBuffer("CliqItVerify", map) { pendingVerify = it }
186
+ }
187
+ }
188
+
189
+ private fun checksMap(checks: Map<String, com.cliqit.sdk.VerifyCheck>): WritableMap {
190
+ val out = Arguments.createMap()
191
+ checks.forEach { (key, check) ->
192
+ val item = Arguments.createMap()
193
+ putOpt(item, "actual", check.actual)
194
+ putOpt(item, "expected", check.expected)
195
+ item.putBoolean("match", check.match)
196
+ out.putMap(key, item)
197
+ }
198
+ return out
199
+ }
200
+
201
+ private fun emitOrBuffer(
202
+ event: String,
203
+ body: WritableMap,
204
+ buffer: (WritableMap) -> Unit,
205
+ ) {
206
+ if (hasListeners) {
207
+ sendEvent(event, body)
208
+ } else {
209
+ buffer(body)
210
+ }
211
+ }
212
+
213
+ private fun flushPending() {
214
+ pendingDeepLink?.let {
215
+ pendingDeepLink = null
216
+ sendEvent("CliqItDeepLink", it)
217
+ }
218
+ pendingDeferredMatch?.let {
219
+ pendingDeferredMatch = null
220
+ sendEvent("CliqItDeferredMatch", it)
221
+ }
222
+ pendingLinkLookup?.let {
223
+ pendingLinkLookup = null
224
+ sendEvent("CliqItLinkLookup", it)
225
+ }
226
+ pendingVerify?.let {
227
+ pendingVerify = null
228
+ sendEvent("CliqItVerify", it)
229
+ }
230
+ }
231
+
232
+ private fun sendEvent(event: String, params: WritableMap) {
233
+ if (!reactContext.hasActiveReactInstance()) return
234
+ reactContext
235
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
236
+ .emit(event, params)
237
+ }
238
+
239
+ private fun putOpt(map: WritableMap, key: String, value: String?) {
240
+ if (value != null) map.putString(key, value) else map.putNull(key)
241
+ }
242
+ }
@@ -0,0 +1,14 @@
1
+ package com.cliqit
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class CliqItPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
10
+ listOf(CliqItModule(reactContext))
11
+
12
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> =
13
+ emptyList()
14
+ }
@@ -0,0 +1,17 @@
1
+ package com.cliqit.sdk
2
+
3
+ object CliqItDefaults {
4
+ const val SERVER_URL = "https://api.theblockyapp.com"
5
+ const val DEFERRED_MATCH_PATH = "api/v1/sdk/app/match"
6
+ const val LINK_LOOKUP_PATH = "api/v1/sdk/link"
7
+ const val VERIFY_PATH = "api/v1/sdk/verify"
8
+ const val API_KEY_HEADER = "x-api-key"
9
+ const val MAX_RETRY = 3
10
+ const val RETRY_INITIAL_DELAY_MS = 500L
11
+
12
+ const val PREFS = "cliqit_sdk"
13
+ const val KEY_MATCH_REPORTED = "com.cliqit.deferred.match.reported"
14
+ const val KEY_DEFERRED_DELIVERED = "com.cliqit.deferred.delivered"
15
+ /** When no explicit domain is configured, only this host + subdomains are accepted. */
16
+ const val ALLOWED_LINK_DOMAIN = "theblockyapp.com"
17
+ }