react-native-hubspot-wrapper 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/HUBSPOT_IOS_SDK_VERSION.json +5 -0
- package/LICENSE +21 -0
- package/MIGRATION.md +19 -0
- package/README.md +119 -0
- package/ReactNativeHubspotWrapper.podspec +27 -0
- package/android/build.gradle +49 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/reactnativehubspotwrapper/HubspotWrapperModule.kt +83 -0
- package/android/src/main/java/com/reactnativehubspotwrapper/HubspotWrapperPackage.kt +32 -0
- package/ios/HubspotMobileSDK/API/APIModels.swift +50 -0
- package/ios/HubspotMobileSDK/API/HubspotAPI.swift +168 -0
- package/ios/HubspotMobileSDK/DeviceTokenSyncState.swift +13 -0
- package/ios/HubspotMobileSDK/HubspotConfig.swift +145 -0
- package/ios/HubspotMobileSDK/HubspotManager+Notifications.swift +178 -0
- package/ios/HubspotMobileSDK/HubspotManager+Properties.swift +53 -0
- package/ios/HubspotMobileSDK/HubspotManager.swift +548 -0
- package/ios/HubspotMobileSDK/HubspotMobileSDK.swift +7 -0
- package/ios/HubspotMobileSDK/HubspotUserProperties.swift +115 -0
- package/ios/HubspotMobileSDK/LICENSE.txt +19 -0
- package/ios/HubspotMobileSDK/PushNotificationChatData.swift +63 -0
- package/ios/HubspotMobileSDK/Resources/Images.xcassets/Contents.json +6 -0
- package/ios/HubspotMobileSDK/Resources/Images.xcassets/GenericChatIcon.imageset/Contents.json +16 -0
- package/ios/HubspotMobileSDK/Resources/Images.xcassets/GenericChatIcon.imageset/chat-open-svg.svg +1 -0
- package/ios/HubspotMobileSDK/Resources/Localizable.xcstrings +28 -0
- package/ios/HubspotMobileSDK/Resources/PrivacyInfo.xcprivacy +62 -0
- package/ios/HubspotMobileSDK/Views/Buttons/FloatingActionButton.swift +126 -0
- package/ios/HubspotMobileSDK/Views/Buttons/TextChatButtonChatButton.swift +78 -0
- package/ios/HubspotMobileSDK/Views/ChatView/HubspotChatView.swift +612 -0
- package/ios/HubspotWrapperImpl.swift +108 -0
- package/ios/RNHubspotWrapper.h +9 -0
- package/ios/RNHubspotWrapper.mm +66 -0
- package/package.json +55 -0
- package/react-native.config.js +11 -0
- package/scripts/update-hubspot-ios-sdk.sh +142 -0
- package/src/index.ts +41 -0
- package/src/specs/NativeHubspotWrapper.ts +17 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SwiftUI
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
@objcMembers
|
|
6
|
+
public class HubspotWrapperImpl: NSObject {
|
|
7
|
+
public func initialize(_ outError: NSErrorPointer) -> Bool {
|
|
8
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
9
|
+
var configureError: NSError?
|
|
10
|
+
|
|
11
|
+
Task { @MainActor in
|
|
12
|
+
do {
|
|
13
|
+
try HubspotManager.configure()
|
|
14
|
+
} catch let error {
|
|
15
|
+
configureError = error as NSError
|
|
16
|
+
}
|
|
17
|
+
semaphore.signal()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
semaphore.wait()
|
|
21
|
+
|
|
22
|
+
if let configureError {
|
|
23
|
+
outError?.pointee = configureError
|
|
24
|
+
return false
|
|
25
|
+
}
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public func openChat(_ chatflow: String, error outError: NSErrorPointer) -> Bool {
|
|
30
|
+
var didSucceed = false
|
|
31
|
+
let presentBlock = {
|
|
32
|
+
guard let rootVC = Self.topViewController() else {
|
|
33
|
+
outError?.pointee = NSError(
|
|
34
|
+
domain: "HubspotWrapper",
|
|
35
|
+
code: 1,
|
|
36
|
+
userInfo: [NSLocalizedDescriptionKey: "No root view controller available"]
|
|
37
|
+
)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let chatView = HubspotChatView(chatFlow: chatflow)
|
|
42
|
+
let hostingController = UIHostingController(rootView: chatView)
|
|
43
|
+
rootVC.present(hostingController, animated: true)
|
|
44
|
+
didSucceed = true
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if Thread.isMainThread {
|
|
48
|
+
presentBlock()
|
|
49
|
+
} else {
|
|
50
|
+
DispatchQueue.main.sync(execute: presentBlock)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return didSucceed
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public func setIdentity(_ identityToken: String, email: String?) {
|
|
57
|
+
let semaphore = DispatchSemaphore(value: 0)
|
|
58
|
+
Task { @MainActor in
|
|
59
|
+
HubspotManager.shared.setUserIdentity(identityToken: identityToken, email: email ?? "")
|
|
60
|
+
semaphore.signal()
|
|
61
|
+
}
|
|
62
|
+
semaphore.wait()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public func setProperties(_ properties: [NSDictionary]) {
|
|
66
|
+
var mapped: [String: String] = [:]
|
|
67
|
+
|
|
68
|
+
for item in properties {
|
|
69
|
+
guard
|
|
70
|
+
let name = item["name"] as? String,
|
|
71
|
+
let value = item["value"] as? String
|
|
72
|
+
else {
|
|
73
|
+
continue
|
|
74
|
+
}
|
|
75
|
+
mapped[name] = value
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Task {
|
|
79
|
+
await HubspotManager.shared.setChatProperties(data: mapped)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public func clearUserData() {
|
|
84
|
+
Task {
|
|
85
|
+
await HubspotManager.shared.clearUserData()
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private static func topViewController(
|
|
90
|
+
base: UIViewController? = UIApplication.shared.connectedScenes
|
|
91
|
+
.compactMap { $0 as? UIWindowScene }
|
|
92
|
+
.flatMap { $0.windows }
|
|
93
|
+
.first(where: \.isKeyWindow)?
|
|
94
|
+
.rootViewController
|
|
95
|
+
) -> UIViewController? {
|
|
96
|
+
if let navigationController = base as? UINavigationController {
|
|
97
|
+
return topViewController(base: navigationController.visibleViewController)
|
|
98
|
+
}
|
|
99
|
+
if let tabBarController = base as? UITabBarController,
|
|
100
|
+
let selected = tabBarController.selectedViewController {
|
|
101
|
+
return topViewController(base: selected)
|
|
102
|
+
}
|
|
103
|
+
if let presented = base?.presentedViewController {
|
|
104
|
+
return topViewController(base: presented)
|
|
105
|
+
}
|
|
106
|
+
return base
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#import "RNHubspotWrapper.h"
|
|
2
|
+
#import <UserNotifications/UserNotifications.h>
|
|
3
|
+
#import "ReactNativeHubspotWrapper-Swift.h"
|
|
4
|
+
|
|
5
|
+
@implementation RNHubspotWrapper {
|
|
6
|
+
HubspotWrapperImpl *_impl;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
RCT_EXPORT_MODULE(NativeHubspotWrapper)
|
|
10
|
+
|
|
11
|
+
- (instancetype)init
|
|
12
|
+
{
|
|
13
|
+
self = [super init];
|
|
14
|
+
if (self) {
|
|
15
|
+
_impl = [HubspotWrapperImpl new];
|
|
16
|
+
}
|
|
17
|
+
return self;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
21
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
22
|
+
{
|
|
23
|
+
return std::make_shared<facebook::react::NativeHubspotWrapperSpecJSI>(params);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (void)initialize:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
27
|
+
{
|
|
28
|
+
NSError *error = nil;
|
|
29
|
+
BOOL didInitialize = [_impl initialize:&error];
|
|
30
|
+
if (didInitialize) {
|
|
31
|
+
resolve(nil);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
reject(@"INIT_ERROR", @"Failed to initialize HubSpot SDK", error);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
- (void)openChat:(NSString *)chatflow resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
38
|
+
{
|
|
39
|
+
NSError *error = nil;
|
|
40
|
+
BOOL didOpen = [_impl openChat:chatflow error:&error];
|
|
41
|
+
if (didOpen) {
|
|
42
|
+
resolve(nil);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
reject(@"OPEN_CHAT_ERROR", @"Failed to open HubSpot chat", error);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (void)setIdentity:(NSString *)identityToken email:(NSString * _Nullable)email resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
49
|
+
{
|
|
50
|
+
[_impl setIdentity:identityToken email:email];
|
|
51
|
+
resolve(nil);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
- (void)setProperties:(NSArray<NSDictionary *> *)properties resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
55
|
+
{
|
|
56
|
+
[_impl setProperties:properties];
|
|
57
|
+
resolve(nil);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
- (void)clearUserData:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
|
|
61
|
+
{
|
|
62
|
+
[_impl clearUserData];
|
|
63
|
+
resolve(nil);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@end
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-hubspot-wrapper",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TurboModule wrapper for HubSpot mobile chat SDK",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"src",
|
|
9
|
+
"android",
|
|
10
|
+
"ios",
|
|
11
|
+
"ReactNativeHubspotWrapper.podspec",
|
|
12
|
+
"react-native.config.js",
|
|
13
|
+
"README.md",
|
|
14
|
+
"MIGRATION.md",
|
|
15
|
+
"HUBSPOT_IOS_SDK_VERSION.json",
|
|
16
|
+
"scripts",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"react-native",
|
|
21
|
+
"hubspot",
|
|
22
|
+
"chat",
|
|
23
|
+
"turbomodule"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/marcinolek/react-native-hubspot-wrapper.git"
|
|
28
|
+
},
|
|
29
|
+
"author": "Marcin Olek",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"update:hubspot:ios": "bash ./scripts/update-hubspot-ios-sdk.sh"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"react": "*",
|
|
39
|
+
"react-native": ">=0.81.0"
|
|
40
|
+
},
|
|
41
|
+
"codegenConfig": {
|
|
42
|
+
"name": "HubspotWrapperSpec",
|
|
43
|
+
"type": "modules",
|
|
44
|
+
"jsSrcsDir": "src/specs",
|
|
45
|
+
"android": {
|
|
46
|
+
"javaPackageName": "com.marcinolek.reactnativehubspotwrapper"
|
|
47
|
+
},
|
|
48
|
+
"ios": {
|
|
49
|
+
"modulesProvider": {
|
|
50
|
+
"NativeHubspotWrapper": "RNHubspotWrapper"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
55
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
REPO_URL="https://github.com/HubSpot/mobile-chat-sdk-ios.git"
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
8
|
+
TARGET_DIR="${ROOT_DIR}/ios/HubspotMobileSDK"
|
|
9
|
+
VERSION_FILE="${ROOT_DIR}/HUBSPOT_IOS_SDK_VERSION.json"
|
|
10
|
+
|
|
11
|
+
resolve_latest_tag() {
|
|
12
|
+
git ls-remote --tags --refs "${REPO_URL}" \
|
|
13
|
+
| awk -F'/' '{print $3}' \
|
|
14
|
+
| sort -V \
|
|
15
|
+
| tail -n 1
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply_cocoapods_compat_patches() {
|
|
19
|
+
python3 - "${TARGET_DIR}" <<'PY'
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
target_dir = Path(sys.argv[1])
|
|
24
|
+
|
|
25
|
+
def replace_once(path: Path, old: str, new: str) -> None:
|
|
26
|
+
content = path.read_text()
|
|
27
|
+
if old not in content:
|
|
28
|
+
raise RuntimeError(f"Expected snippet not found in {path}")
|
|
29
|
+
path.write_text(content.replace(old, new, 1))
|
|
30
|
+
|
|
31
|
+
# 1) Replace SPM-only asset symbol usage in FloatingActionButton.
|
|
32
|
+
replace_once(
|
|
33
|
+
target_dir / "Views/Buttons/FloatingActionButton.swift",
|
|
34
|
+
"Image(.genericChatIcon)",
|
|
35
|
+
"Image.hubspotChat",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# 2) Replace SPM-only asset/localization usage in TextChatButton.
|
|
39
|
+
replace_once(
|
|
40
|
+
target_dir / "Views/Buttons/TextChatButtonChatButton.swift",
|
|
41
|
+
"Image(.genericChatIcon)",
|
|
42
|
+
"Image.hubspotChat",
|
|
43
|
+
)
|
|
44
|
+
replace_once(
|
|
45
|
+
target_dir / "Views/Buttons/TextChatButtonChatButton.swift",
|
|
46
|
+
'Text("chat.label", bundle: .module)',
|
|
47
|
+
'Text("chat.label", bundle: .hubspotResources)',
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# 3) Add Bundle helper + shared image helper in HubspotManager.
|
|
51
|
+
hubspot_manager = target_dir / "HubspotManager.swift"
|
|
52
|
+
content = hubspot_manager.read_text()
|
|
53
|
+
old_block = """extension Image {
|
|
54
|
+
/// Exporting chat icon - initially for demo use - but maybe sharing some resources that aren't buttons or views might be needed eventually, if so refactor this
|
|
55
|
+
public static var hubspotChat: Image {
|
|
56
|
+
Image(.genericChatIcon)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
"""
|
|
60
|
+
new_block = """extension Image {
|
|
61
|
+
/// Exporting chat icon - initially for demo use - but maybe sharing some resources that aren't buttons or views might be needed eventually, if so refactor this
|
|
62
|
+
public static var hubspotChat: Image {
|
|
63
|
+
Image("GenericChatIcon", bundle: .hubspotResources)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
extension Bundle {
|
|
68
|
+
static var hubspotResources: Bundle? {
|
|
69
|
+
// CocoaPods bundles resources into a separate bundle, unlike Swift Package's `Bundle.module`.
|
|
70
|
+
Bundle.main.url(forResource: "HubspotMobileSDKResources", withExtension: "bundle")
|
|
71
|
+
.flatMap { Bundle(url: $0) }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
"""
|
|
75
|
+
if old_block not in content:
|
|
76
|
+
raise RuntimeError("Expected Image extension block was not found in HubspotManager.swift")
|
|
77
|
+
hubspot_manager.write_text(content.replace(old_block, new_block, 1))
|
|
78
|
+
PY
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
TAG="${1:-}"
|
|
82
|
+
if [[ -z "${TAG}" ]]; then
|
|
83
|
+
TAG="$(resolve_latest_tag)"
|
|
84
|
+
if [[ -z "${TAG}" ]]; then
|
|
85
|
+
echo "Could not determine latest tag from ${REPO_URL}" >&2
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
TMP_DIR="$(mktemp -d)"
|
|
91
|
+
cleanup() {
|
|
92
|
+
rm -rf "${TMP_DIR}"
|
|
93
|
+
}
|
|
94
|
+
trap cleanup EXIT
|
|
95
|
+
|
|
96
|
+
echo "Cloning ${REPO_URL} at tag ${TAG}..."
|
|
97
|
+
git clone --depth 1 --branch "${TAG}" "${REPO_URL}" "${TMP_DIR}/upstream"
|
|
98
|
+
|
|
99
|
+
if [[ ! -d "${TMP_DIR}/upstream/Sources/HubspotMobileSDK" ]]; then
|
|
100
|
+
echo "Expected Sources/HubspotMobileSDK was not found in tag ${TAG}" >&2
|
|
101
|
+
exit 1
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
echo "Updating vendored iOS SDK sources..."
|
|
105
|
+
rm -rf "${TARGET_DIR}"
|
|
106
|
+
mkdir -p "$(dirname "${TARGET_DIR}")"
|
|
107
|
+
cp -R "${TMP_DIR}/upstream/Sources/HubspotMobileSDK" "${TARGET_DIR}"
|
|
108
|
+
|
|
109
|
+
# Drop upstream Xcode documentation bundle: ~800KB of PNGs and markdown files
|
|
110
|
+
# that the podspec does not pick up and that aren't needed by consumers.
|
|
111
|
+
rm -rf "${TARGET_DIR}/Documentation.docc"
|
|
112
|
+
|
|
113
|
+
# MIT requires distributing the upstream license alongside the vendored sources.
|
|
114
|
+
UPSTREAM_LICENSE=""
|
|
115
|
+
for candidate in LICENSE.txt LICENSE LICENSE.md; do
|
|
116
|
+
if [[ -f "${TMP_DIR}/upstream/${candidate}" ]]; then
|
|
117
|
+
UPSTREAM_LICENSE="${TMP_DIR}/upstream/${candidate}"
|
|
118
|
+
break
|
|
119
|
+
fi
|
|
120
|
+
done
|
|
121
|
+
if [[ -z "${UPSTREAM_LICENSE}" ]]; then
|
|
122
|
+
echo "Could not find an upstream LICENSE file at tag ${TAG}" >&2
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
cp "${UPSTREAM_LICENSE}" "${TARGET_DIR}/LICENSE.txt"
|
|
126
|
+
|
|
127
|
+
echo "Applying CocoaPods compatibility patches..."
|
|
128
|
+
apply_cocoapods_compat_patches
|
|
129
|
+
|
|
130
|
+
UPSTREAM_COMMIT="$(git -C "${TMP_DIR}/upstream" rev-parse HEAD)"
|
|
131
|
+
|
|
132
|
+
cat > "${VERSION_FILE}" <<EOF
|
|
133
|
+
{
|
|
134
|
+
"sourceRepository": "${REPO_URL}",
|
|
135
|
+
"tag": "${TAG}",
|
|
136
|
+
"commit": "${UPSTREAM_COMMIT}"
|
|
137
|
+
}
|
|
138
|
+
EOF
|
|
139
|
+
|
|
140
|
+
echo "Updated:"
|
|
141
|
+
echo " - ${TARGET_DIR}"
|
|
142
|
+
echo " - ${VERSION_FILE}"
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import NativeHubspotWrapper, { HubspotProperty } from './specs/NativeHubspotWrapper';
|
|
2
|
+
|
|
3
|
+
export type { HubspotProperty };
|
|
4
|
+
|
|
5
|
+
export type SetIdentityParams = {
|
|
6
|
+
identityToken: string;
|
|
7
|
+
email?: string | null;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function ensureNonEmpty(value: string, fieldName: string): void {
|
|
11
|
+
if (!value || !value.trim()) {
|
|
12
|
+
throw new Error(`\`${fieldName}\` must be a non-empty string.`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const HubspotWrapper = {
|
|
17
|
+
initialize(): Promise<void> {
|
|
18
|
+
return NativeHubspotWrapper.initialize();
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
openChat(chatflow: string): Promise<void> {
|
|
22
|
+
ensureNonEmpty(chatflow, 'chatflow');
|
|
23
|
+
return NativeHubspotWrapper.openChat(chatflow);
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
setIdentity(params: SetIdentityParams): Promise<void> {
|
|
27
|
+
ensureNonEmpty(params.identityToken, 'identityToken');
|
|
28
|
+
const email = params.email?.trim() || null;
|
|
29
|
+
return NativeHubspotWrapper.setIdentity(params.identityToken, email);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
setProperties(properties: HubspotProperty[]): Promise<void> {
|
|
33
|
+
return NativeHubspotWrapper.setProperties(properties);
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
clearUserData(): Promise<void> {
|
|
37
|
+
return NativeHubspotWrapper.clearUserData();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default HubspotWrapper;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native';
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export type HubspotProperty = {
|
|
5
|
+
name: string;
|
|
6
|
+
value: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export interface Spec extends TurboModule {
|
|
10
|
+
initialize(): Promise<void>;
|
|
11
|
+
openChat(chatflow: string): Promise<void>;
|
|
12
|
+
setIdentity(identityToken: string, email: string | null): Promise<void>;
|
|
13
|
+
setProperties(properties: ReadonlyArray<HubspotProperty>): Promise<void>;
|
|
14
|
+
clearUserData(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('NativeHubspotWrapper');
|