@sagepilot-ai/react-native-sdk 0.2.2 → 0.2.4
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/README.md +34 -6
- package/android/build.gradle +53 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/ai/sagepilot/reactnativesdk/SagepilotInsetsChangeEvent.java +26 -0
- package/android/src/main/java/ai/sagepilot/reactnativesdk/SagepilotInsetsView.java +78 -0
- package/android/src/main/java/ai/sagepilot/reactnativesdk/SagepilotInsetsViewManager.java +59 -0
- package/android/src/main/java/ai/sagepilot/reactnativesdk/SagepilotReactNativeSdkPackage.java +20 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/SagepilotInsetsViewManagerDelegate.java +25 -0
- package/android/src/paper/java/com/facebook/react/viewmanagers/SagepilotInsetsViewManagerInterface.java +10 -0
- package/dist/{index.d.cts → index.d.mts} +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +299 -96
- package/dist/{index.cjs → index.mjs} +267 -119
- package/package.json +18 -8
- package/react-native.config.js +5 -1
- package/src/specs/SagepilotInsetsViewNativeComponent.ts +17 -0
- package/android/.gitkeep +0 -1
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
SagepilotChat: () => SagepilotChat,
|
|
24
|
-
SagepilotChatError: () => SagepilotChatError,
|
|
25
|
-
SagepilotChatProvider: () => SagepilotChatProvider,
|
|
26
|
-
createAsyncStorageCacheStorage: () => createAsyncStorageCacheStorage,
|
|
27
|
-
createKeychainTokenStorage: () => createKeychainTokenStorage,
|
|
28
|
-
useSagepilotChat: () => useSagepilotChat
|
|
29
|
-
});
|
|
30
|
-
module.exports = __toCommonJS(index_exports);
|
|
31
|
-
|
|
32
1
|
// src/core/errors/SagepilotChatError.ts
|
|
33
2
|
var SagepilotChatError = class extends Error {
|
|
34
3
|
constructor(code, message, options = {}) {
|
|
@@ -46,7 +15,7 @@ var SagepilotChatError = class extends Error {
|
|
|
46
15
|
|
|
47
16
|
// src/core/config/constants.ts
|
|
48
17
|
var SDK_NAME = "@sagepilot-ai/react-native-sdk";
|
|
49
|
-
var SDK_VERSION = "0.2.
|
|
18
|
+
var SDK_VERSION = "0.2.4";
|
|
50
19
|
var DEFAULT_HOST = "https://app.sagepilot.ai";
|
|
51
20
|
var DEFAULT_WIDGET_HOST = "https://app.sagepilot.ai";
|
|
52
21
|
var CUSTOMER_API_PREFIX = "/customer-api/v1";
|
|
@@ -495,6 +464,18 @@ function normalizeIdentity(identity) {
|
|
|
495
464
|
user_hash: identity.userHash ?? identity.user_hash
|
|
496
465
|
};
|
|
497
466
|
}
|
|
467
|
+
function readStringField(input, key) {
|
|
468
|
+
const value = input[key];
|
|
469
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
470
|
+
}
|
|
471
|
+
function normalizeOptionalString(value) {
|
|
472
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
473
|
+
}
|
|
474
|
+
function readRecordField(input, key) {
|
|
475
|
+
const value = input[key];
|
|
476
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
498
479
|
function toPublicSessionState(session) {
|
|
499
480
|
return {
|
|
500
481
|
session_id: session.session_id,
|
|
@@ -528,6 +509,7 @@ var SagepilotReactNativeChat = class {
|
|
|
528
509
|
this.unreadPollTimer = null;
|
|
529
510
|
this.stateCallbacks = /* @__PURE__ */ new Set();
|
|
530
511
|
this.identifyCallbacks = /* @__PURE__ */ new Set();
|
|
512
|
+
this.conversationCreatedCallbacks = /* @__PURE__ */ new Set();
|
|
531
513
|
this.unreadCallbacks = /* @__PURE__ */ new Set();
|
|
532
514
|
this.readyCallbacks = /* @__PURE__ */ new Set();
|
|
533
515
|
this.presentCallbacks = /* @__PURE__ */ new Set();
|
|
@@ -732,9 +714,17 @@ var SagepilotReactNativeChat = class {
|
|
|
732
714
|
this.hostedChatView = { screen: "messages" };
|
|
733
715
|
return this.showHostedChat();
|
|
734
716
|
}
|
|
735
|
-
presentMessageComposer(message) {
|
|
717
|
+
presentMessageComposer(message, options) {
|
|
736
718
|
this.requireConfigured();
|
|
737
|
-
|
|
719
|
+
const chatId = normalizeOptionalString(options?.chatId);
|
|
720
|
+
this.hostedChatView = {
|
|
721
|
+
screen: "composer",
|
|
722
|
+
message,
|
|
723
|
+
mode: options?.mode ?? "auto",
|
|
724
|
+
chatId,
|
|
725
|
+
metadata: options?.metadata,
|
|
726
|
+
onConversationCreated: options?.onConversationCreated
|
|
727
|
+
};
|
|
738
728
|
return this.showHostedChat();
|
|
739
729
|
}
|
|
740
730
|
dismiss() {
|
|
@@ -783,6 +773,13 @@ var SagepilotReactNativeChat = class {
|
|
|
783
773
|
this.dismissCallbacks.delete(callback);
|
|
784
774
|
};
|
|
785
775
|
}
|
|
776
|
+
onConversationCreated(callback) {
|
|
777
|
+
if (typeof callback !== "function") return () => void 0;
|
|
778
|
+
this.conversationCreatedCallbacks.add(callback);
|
|
779
|
+
return () => {
|
|
780
|
+
this.conversationCreatedCallbacks.delete(callback);
|
|
781
|
+
};
|
|
782
|
+
}
|
|
786
783
|
onError(callback) {
|
|
787
784
|
if (typeof callback !== "function") return () => void 0;
|
|
788
785
|
this.errorCallbacks.add(callback);
|
|
@@ -834,7 +831,12 @@ var SagepilotReactNativeChat = class {
|
|
|
834
831
|
url.searchParams.set("jwt", this.legacyWidgetJwt);
|
|
835
832
|
}
|
|
836
833
|
if (this.hostedChatView.screen === "composer") {
|
|
837
|
-
|
|
834
|
+
if (this.hostedChatView.chatId) {
|
|
835
|
+
url.searchParams.set("chat_id", this.hostedChatView.chatId);
|
|
836
|
+
}
|
|
837
|
+
if (this.hostedChatView.mode === "new" && !this.hostedChatView.chatId) {
|
|
838
|
+
url.searchParams.set("new", "true");
|
|
839
|
+
}
|
|
838
840
|
if (this.hostedChatView.message) {
|
|
839
841
|
url.searchParams.set("topic", this.hostedChatView.message);
|
|
840
842
|
}
|
|
@@ -860,13 +862,19 @@ var SagepilotReactNativeChat = class {
|
|
|
860
862
|
"})();"
|
|
861
863
|
].join("\n");
|
|
862
864
|
}
|
|
865
|
+
getActiveHostedChatId() {
|
|
866
|
+
if (this.hostedChatView.screen === "composer" && this.hostedChatView.chatId) {
|
|
867
|
+
return this.hostedChatView.chatId;
|
|
868
|
+
}
|
|
869
|
+
return this.session?.conversation_id ?? void 0;
|
|
870
|
+
}
|
|
863
871
|
getHostedIdentityMessage() {
|
|
864
872
|
if (!this.legacyWidgetJwt) return null;
|
|
865
873
|
return {
|
|
866
874
|
type: "identity_update",
|
|
867
875
|
data: {
|
|
868
876
|
jwt: this.legacyWidgetJwt,
|
|
869
|
-
chat_id: this.
|
|
877
|
+
chat_id: this.getActiveHostedChatId()
|
|
870
878
|
}
|
|
871
879
|
};
|
|
872
880
|
}
|
|
@@ -885,17 +893,62 @@ var SagepilotReactNativeChat = class {
|
|
|
885
893
|
}
|
|
886
894
|
return true;
|
|
887
895
|
}
|
|
896
|
+
if (message.type === "sagepilot:conversation_created") {
|
|
897
|
+
this.handleConversationCreated(message);
|
|
898
|
+
return true;
|
|
899
|
+
}
|
|
888
900
|
if (message.type === "sagepilot:error") {
|
|
889
901
|
this.emitError(message);
|
|
890
902
|
return true;
|
|
891
903
|
}
|
|
892
904
|
return true;
|
|
893
905
|
}
|
|
906
|
+
handleConversationCreated(message) {
|
|
907
|
+
const chatId = readStringField(message, "chat_id") ?? readStringField(message, "conversation_id");
|
|
908
|
+
if (!chatId) return;
|
|
909
|
+
void this.persistConversationId(chatId).catch((error) => this.emitError(error));
|
|
910
|
+
const bridgeMetadata = readRecordField(message, "metadata");
|
|
911
|
+
const composerMetadata = this.hostedChatView.screen === "composer" ? this.hostedChatView.metadata : void 0;
|
|
912
|
+
const metadata = {
|
|
913
|
+
...composerMetadata ?? {},
|
|
914
|
+
...bridgeMetadata ?? {}
|
|
915
|
+
};
|
|
916
|
+
const workspaceId = readStringField(message, "workspace_id") ?? this.workspaceId;
|
|
917
|
+
const channelId = readStringField(message, "channel_id") ?? this.channelId;
|
|
918
|
+
const sessionId = readStringField(message, "session_id") ?? this.session?.session_id;
|
|
919
|
+
const customerId = readStringField(message, "customer_id");
|
|
920
|
+
const messageId = readStringField(message, "message_id");
|
|
921
|
+
const createdAt = readStringField(message, "created_at");
|
|
922
|
+
const event = {
|
|
923
|
+
chat_id: chatId,
|
|
924
|
+
...workspaceId ? { workspace_id: workspaceId } : {},
|
|
925
|
+
...channelId ? { channel_id: channelId } : {},
|
|
926
|
+
...sessionId ? { session_id: sessionId } : {},
|
|
927
|
+
...customerId ? { customer_id: customerId } : {},
|
|
928
|
+
...messageId ? { message_id: messageId } : {},
|
|
929
|
+
...createdAt ? { created_at: createdAt } : {},
|
|
930
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
931
|
+
};
|
|
932
|
+
if (this.hostedChatView.screen === "composer") {
|
|
933
|
+
this.hostedChatView.onConversationCreated?.(event);
|
|
934
|
+
}
|
|
935
|
+
this.conversationCreatedCallbacks.forEach((callback) => callback(event));
|
|
936
|
+
}
|
|
937
|
+
async persistConversationId(conversationId) {
|
|
938
|
+
if (!this.session || !this.sessionManager) return;
|
|
939
|
+
if (this.session.conversation_id === conversationId) return;
|
|
940
|
+
this.session = await this.sessionManager.setSession({
|
|
941
|
+
...this.session,
|
|
942
|
+
conversation_id: conversationId
|
|
943
|
+
});
|
|
944
|
+
this.emitState();
|
|
945
|
+
}
|
|
894
946
|
destroy() {
|
|
895
947
|
this.stopUnreadPolling();
|
|
896
948
|
this.resetRuntimeState();
|
|
897
949
|
this.emitState();
|
|
898
950
|
this.identifyCallbacks.clear();
|
|
951
|
+
this.conversationCreatedCallbacks.clear();
|
|
899
952
|
this.unreadCallbacks.clear();
|
|
900
953
|
this.readyCallbacks.clear();
|
|
901
954
|
this.presentCallbacks.clear();
|
|
@@ -1058,13 +1111,18 @@ var SagepilotChat = {
|
|
|
1058
1111
|
logout: () => internalSagepilotChat.logout(),
|
|
1059
1112
|
getIdentityState: () => internalSagepilotChat.getIdentityState(),
|
|
1060
1113
|
onIdentify: (callback) => internalSagepilotChat.onIdentify(callback),
|
|
1114
|
+
onConversationCreated: (callback) => {
|
|
1115
|
+
return internalSagepilotChat.onConversationCreated(callback);
|
|
1116
|
+
},
|
|
1061
1117
|
getUnreadCount: () => internalSagepilotChat.getUnreadCount(),
|
|
1062
1118
|
onUnreadChange: (callback) => internalSagepilotChat.onUnreadChange(callback),
|
|
1063
1119
|
startUnreadPolling: (intervalMs) => internalSagepilotChat.startUnreadPolling(intervalMs),
|
|
1064
1120
|
stopUnreadPolling: () => internalSagepilotChat.stopUnreadPolling(),
|
|
1065
1121
|
present: () => internalSagepilotChat.present(),
|
|
1066
1122
|
presentMessages: () => internalSagepilotChat.presentMessages(),
|
|
1067
|
-
presentMessageComposer: (message) =>
|
|
1123
|
+
presentMessageComposer: (message, options) => {
|
|
1124
|
+
return internalSagepilotChat.presentMessageComposer(message, options);
|
|
1125
|
+
},
|
|
1068
1126
|
dismiss: () => internalSagepilotChat.dismiss(),
|
|
1069
1127
|
hide: () => internalSagepilotChat.hide(),
|
|
1070
1128
|
toggle: () => internalSagepilotChat.toggle(),
|
|
@@ -1090,9 +1148,19 @@ function createAsyncStorageCacheStorage(asyncStorage) {
|
|
|
1090
1148
|
}
|
|
1091
1149
|
|
|
1092
1150
|
// src/ui/SagepilotChatProvider.ts
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1151
|
+
import { createElement, useCallback, useEffect, useRef, useState } from "react";
|
|
1152
|
+
import {
|
|
1153
|
+
ActivityIndicator,
|
|
1154
|
+
KeyboardAvoidingView,
|
|
1155
|
+
Modal,
|
|
1156
|
+
Platform,
|
|
1157
|
+
Pressable,
|
|
1158
|
+
SafeAreaView,
|
|
1159
|
+
StyleSheet,
|
|
1160
|
+
Text,
|
|
1161
|
+
View
|
|
1162
|
+
} from "react-native";
|
|
1163
|
+
import { WebView } from "react-native-webview";
|
|
1096
1164
|
|
|
1097
1165
|
// src/core/webview/mobileBridge.ts
|
|
1098
1166
|
function isHostedBridgeMessage(value) {
|
|
@@ -1173,6 +1241,28 @@ var mobileWebViewBridgeScript = `
|
|
|
1173
1241
|
} catch (error) {}
|
|
1174
1242
|
}, true);
|
|
1175
1243
|
|
|
1244
|
+
document.addEventListener("focusin", function (event) {
|
|
1245
|
+
try {
|
|
1246
|
+
var target = event.target && event.target.closest
|
|
1247
|
+
? event.target
|
|
1248
|
+
: event.target && event.target.parentElement;
|
|
1249
|
+
if (target && target.closest && target.closest("input, textarea, [contenteditable='true']")) {
|
|
1250
|
+
sendToReactNative({ type: "sagepilot:keyboard_focus" });
|
|
1251
|
+
}
|
|
1252
|
+
} catch (error) {}
|
|
1253
|
+
}, true);
|
|
1254
|
+
|
|
1255
|
+
document.addEventListener("focusout", function (event) {
|
|
1256
|
+
try {
|
|
1257
|
+
var target = event.target && event.target.closest
|
|
1258
|
+
? event.target
|
|
1259
|
+
: event.target && event.target.parentElement;
|
|
1260
|
+
if (target && target.closest && target.closest("input, textarea, [contenteditable='true']")) {
|
|
1261
|
+
sendToReactNative({ type: "sagepilot:keyboard_blur" });
|
|
1262
|
+
}
|
|
1263
|
+
} catch (error) {}
|
|
1264
|
+
}, true);
|
|
1265
|
+
|
|
1176
1266
|
ensureViewport();
|
|
1177
1267
|
injectMobileStyles();
|
|
1178
1268
|
sendToReactNative({ type: "sagepilot:ready" });
|
|
@@ -1180,6 +1270,10 @@ var mobileWebViewBridgeScript = `
|
|
|
1180
1270
|
})();
|
|
1181
1271
|
`;
|
|
1182
1272
|
|
|
1273
|
+
// src/specs/SagepilotInsetsViewNativeComponent.ts
|
|
1274
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
1275
|
+
var SagepilotInsetsViewNativeComponent_default = codegenNativeComponent("SagepilotInsetsView");
|
|
1276
|
+
|
|
1183
1277
|
// src/ui/SagepilotChatProvider.ts
|
|
1184
1278
|
function readPresentationState() {
|
|
1185
1279
|
return {
|
|
@@ -1222,30 +1316,68 @@ function readUrlOrigin(url) {
|
|
|
1222
1316
|
var hostedChatWebViewProps = {
|
|
1223
1317
|
allowFileAccess: true,
|
|
1224
1318
|
allowFileAccessFromFileURLs: true,
|
|
1319
|
+
...Platform.OS === "ios" ? {
|
|
1320
|
+
automaticallyAdjustContentInsets: false,
|
|
1321
|
+
contentInsetAdjustmentBehavior: "never",
|
|
1322
|
+
hideKeyboardAccessoryView: true
|
|
1323
|
+
} : null,
|
|
1324
|
+
bounces: false,
|
|
1225
1325
|
domStorageEnabled: true,
|
|
1226
1326
|
javaScriptEnabled: true,
|
|
1327
|
+
overScrollMode: "never",
|
|
1328
|
+
// The hosted widget owns feed scrolling internally; outer WebView scrolling lets iOS focus-scroll the page over the keyboard.
|
|
1329
|
+
scrollEnabled: false,
|
|
1227
1330
|
setSupportMultipleWindows: false,
|
|
1228
1331
|
sharedCookiesEnabled: true,
|
|
1229
1332
|
thirdPartyCookiesEnabled: true
|
|
1230
1333
|
};
|
|
1334
|
+
var AndroidInsetsView = Platform.OS === "android" ? SagepilotInsetsViewNativeComponent_default : View;
|
|
1335
|
+
var emptyAndroidInsets = { top: 0, bottom: 0 };
|
|
1231
1336
|
function SagepilotChatProvider({
|
|
1232
1337
|
children,
|
|
1233
1338
|
closeLabel = "Close",
|
|
1234
1339
|
loadingLabel = "Loading chat"
|
|
1235
1340
|
}) {
|
|
1236
|
-
const [state, setState] =
|
|
1237
|
-
const
|
|
1238
|
-
const
|
|
1239
|
-
|
|
1341
|
+
const [state, setState] = useState(readPresentationState);
|
|
1342
|
+
const [androidModalInsets, setAndroidModalInsets] = useState(emptyAndroidInsets);
|
|
1343
|
+
const webFrameRef = useRef(null);
|
|
1344
|
+
const nativeWebViewRef = useRef(null);
|
|
1345
|
+
useEffect(() => {
|
|
1240
1346
|
return internalSagepilotChat.onStateChange(() => {
|
|
1241
1347
|
setState(readPresentationState());
|
|
1242
1348
|
});
|
|
1243
1349
|
}, []);
|
|
1350
|
+
const handleAndroidInsetsChange = useCallback((event) => {
|
|
1351
|
+
const nextBottomInset = event.nativeEvent?.bottom;
|
|
1352
|
+
const nextTopInset = event.nativeEvent?.top;
|
|
1353
|
+
if (typeof nextBottomInset !== "number" || typeof nextTopInset !== "number" || !Number.isFinite(nextBottomInset) || !Number.isFinite(nextTopInset)) return;
|
|
1354
|
+
setAndroidModalInsets({
|
|
1355
|
+
top: Math.max(0, nextTopInset),
|
|
1356
|
+
bottom: Math.max(0, nextBottomInset)
|
|
1357
|
+
});
|
|
1358
|
+
}, []);
|
|
1244
1359
|
const showCloseButton = state.presentation?.showCloseButton ?? false;
|
|
1245
1360
|
const presentationStyle = state.presentation?.style ?? "sheet";
|
|
1246
1361
|
const isFullScreenModal = presentationStyle === "fullScreen";
|
|
1247
1362
|
const animationType = presentationStyle === "fullScreen" || presentationStyle === "push" ? "slide" : "fade";
|
|
1248
|
-
const ModalContainer =
|
|
1363
|
+
const ModalContainer = Platform.OS === "ios" && isFullScreenModal ? SafeAreaView : View;
|
|
1364
|
+
const NativeModalContainer = Platform.OS === "android" ? AndroidInsetsView : ModalContainer;
|
|
1365
|
+
const ChatContentContainer = Platform.OS === "ios" ? KeyboardAvoidingView : View;
|
|
1366
|
+
const nativeModalContainerProps = Platform.OS === "android" ? { style: styles.container, onInsetsChange: handleAndroidInsetsChange } : { style: styles.container };
|
|
1367
|
+
const chatContentContainerProps = Platform.OS === "ios" ? {
|
|
1368
|
+
behavior: "padding",
|
|
1369
|
+
enabled: true,
|
|
1370
|
+
keyboardVerticalOffset: 0,
|
|
1371
|
+
style: styles.modalContent
|
|
1372
|
+
} : {
|
|
1373
|
+
style: [
|
|
1374
|
+
styles.modalContent,
|
|
1375
|
+
Platform.OS === "android" ? {
|
|
1376
|
+
paddingTop: androidModalInsets.top,
|
|
1377
|
+
paddingBottom: androidModalInsets.bottom
|
|
1378
|
+
} : null
|
|
1379
|
+
].filter(Boolean)
|
|
1380
|
+
};
|
|
1249
1381
|
const handleWebViewMessage = (event) => {
|
|
1250
1382
|
internalSagepilotChat.handleHostedBridgeMessage(parseHostedBridgeMessage(event.nativeEvent?.data));
|
|
1251
1383
|
};
|
|
@@ -1260,8 +1392,8 @@ function SagepilotChatProvider({
|
|
|
1260
1392
|
if (!script || !nativeWebViewRef.current) return;
|
|
1261
1393
|
nativeWebViewRef.current.injectJavaScript(script);
|
|
1262
1394
|
};
|
|
1263
|
-
|
|
1264
|
-
if (
|
|
1395
|
+
useEffect(() => {
|
|
1396
|
+
if (Platform.OS !== "web" || typeof window === "undefined") return;
|
|
1265
1397
|
const trustedWidgetOrigin = readUrlOrigin(state.conversationUrl);
|
|
1266
1398
|
if (!trustedWidgetOrigin) return;
|
|
1267
1399
|
const handleWindowMessage = (event) => {
|
|
@@ -1271,41 +1403,41 @@ function SagepilotChatProvider({
|
|
|
1271
1403
|
window.addEventListener("message", handleWindowMessage);
|
|
1272
1404
|
return () => window.removeEventListener("message", handleWindowMessage);
|
|
1273
1405
|
}, [state.conversationUrl]);
|
|
1274
|
-
|
|
1275
|
-
if (
|
|
1406
|
+
useEffect(() => {
|
|
1407
|
+
if (Platform.OS !== "web" || !state.isPresented) return;
|
|
1276
1408
|
postIdentityToWebFrame();
|
|
1277
1409
|
}, [state.isPresented, state.conversationUrl, state.configured]);
|
|
1278
|
-
|
|
1279
|
-
if (
|
|
1410
|
+
useEffect(() => {
|
|
1411
|
+
if (Platform.OS === "web" || !state.isPresented) return;
|
|
1280
1412
|
postIdentityToNativeWebView();
|
|
1281
1413
|
}, [state.isPresented, state.conversationUrl, state.configured]);
|
|
1282
|
-
if (
|
|
1283
|
-
return
|
|
1284
|
-
|
|
1414
|
+
if (Platform.OS === "web") {
|
|
1415
|
+
return createElement(
|
|
1416
|
+
View,
|
|
1285
1417
|
{ style: styles.root },
|
|
1286
1418
|
children,
|
|
1287
|
-
state.configured && !state.isPresented && state.shouldPreload && state.preloadUrl ?
|
|
1419
|
+
state.configured && !state.isPresented && state.shouldPreload && state.preloadUrl ? createElement("iframe", {
|
|
1288
1420
|
src: state.preloadUrl,
|
|
1289
1421
|
style: styles.webPreloadFrame,
|
|
1290
1422
|
title: "Sagepilot chat preload"
|
|
1291
1423
|
}) : null,
|
|
1292
|
-
state.configured && state.isPresented && state.conversationUrl ?
|
|
1293
|
-
|
|
1424
|
+
state.configured && state.isPresented && state.conversationUrl ? createElement(
|
|
1425
|
+
View,
|
|
1294
1426
|
{ style: styles.webOverlay },
|
|
1295
|
-
|
|
1296
|
-
|
|
1427
|
+
createElement(
|
|
1428
|
+
View,
|
|
1297
1429
|
{ style: styles.webPanel },
|
|
1298
|
-
showCloseButton ?
|
|
1299
|
-
|
|
1430
|
+
showCloseButton ? createElement(
|
|
1431
|
+
Pressable,
|
|
1300
1432
|
{
|
|
1301
1433
|
accessibilityRole: "button",
|
|
1302
1434
|
accessibilityLabel: closeLabel,
|
|
1303
1435
|
onPress: () => internalSagepilotChat.dismiss(),
|
|
1304
1436
|
style: styles.webCloseButton
|
|
1305
1437
|
},
|
|
1306
|
-
|
|
1438
|
+
createElement(Text, { style: styles.closeText }, closeLabel)
|
|
1307
1439
|
) : null,
|
|
1308
|
-
|
|
1440
|
+
createElement("iframe", {
|
|
1309
1441
|
ref: webFrameRef,
|
|
1310
1442
|
src: state.conversationUrl,
|
|
1311
1443
|
style: styles.webFrame,
|
|
@@ -1316,63 +1448,69 @@ function SagepilotChatProvider({
|
|
|
1316
1448
|
) : null
|
|
1317
1449
|
);
|
|
1318
1450
|
}
|
|
1319
|
-
return
|
|
1320
|
-
|
|
1451
|
+
return createElement(
|
|
1452
|
+
View,
|
|
1321
1453
|
{ style: styles.root },
|
|
1322
1454
|
children,
|
|
1323
|
-
state.configured && !state.isPresented && state.shouldPreload && state.preloadUrl ?
|
|
1455
|
+
state.configured && !state.isPresented && state.shouldPreload && state.preloadUrl ? createElement(WebView, {
|
|
1324
1456
|
...hostedChatWebViewProps,
|
|
1325
1457
|
source: { uri: state.preloadUrl },
|
|
1326
1458
|
style: styles.preloadWebview,
|
|
1327
1459
|
injectedJavaScriptBeforeContentLoaded: getInjectedWebViewScript(),
|
|
1328
1460
|
onMessage: handleWebViewMessage
|
|
1329
1461
|
}) : null,
|
|
1330
|
-
|
|
1331
|
-
|
|
1462
|
+
createElement(
|
|
1463
|
+
Modal,
|
|
1332
1464
|
{
|
|
1333
1465
|
visible: state.configured && state.isPresented,
|
|
1334
1466
|
animationType,
|
|
1335
1467
|
presentationStyle: isFullScreenModal ? "fullScreen" : "pageSheet",
|
|
1468
|
+
statusBarTranslucent: Platform.OS === "android",
|
|
1469
|
+
navigationBarTranslucent: Platform.OS === "android",
|
|
1336
1470
|
onRequestClose: () => internalSagepilotChat.dismiss()
|
|
1337
1471
|
},
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
{
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
(
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1472
|
+
createElement(
|
|
1473
|
+
NativeModalContainer,
|
|
1474
|
+
nativeModalContainerProps,
|
|
1475
|
+
createElement(
|
|
1476
|
+
ChatContentContainer,
|
|
1477
|
+
chatContentContainerProps,
|
|
1478
|
+
showCloseButton ? createElement(
|
|
1479
|
+
View,
|
|
1480
|
+
{ style: styles.header },
|
|
1481
|
+
createElement(
|
|
1482
|
+
Pressable,
|
|
1483
|
+
{
|
|
1484
|
+
accessibilityRole: "button",
|
|
1485
|
+
accessibilityLabel: closeLabel,
|
|
1486
|
+
onPress: () => internalSagepilotChat.dismiss(),
|
|
1487
|
+
style: styles.closeButton
|
|
1488
|
+
},
|
|
1489
|
+
createElement(Text, { style: styles.closeText }, closeLabel)
|
|
1490
|
+
)
|
|
1491
|
+
) : null,
|
|
1492
|
+
state.conversationUrl ? createElement(WebView, {
|
|
1493
|
+
...hostedChatWebViewProps,
|
|
1494
|
+
ref: nativeWebViewRef,
|
|
1495
|
+
source: { uri: state.conversationUrl },
|
|
1496
|
+
style: styles.webview,
|
|
1497
|
+
startInLoadingState: true,
|
|
1498
|
+
injectedJavaScriptBeforeContentLoaded: getInjectedWebViewScript(),
|
|
1499
|
+
onMessage: handleWebViewMessage,
|
|
1500
|
+
onLoadEnd: postIdentityToNativeWebView,
|
|
1501
|
+
renderLoading: () => createElement(
|
|
1502
|
+
View,
|
|
1503
|
+
{ style: styles.loading },
|
|
1504
|
+
createElement(ActivityIndicator, null),
|
|
1505
|
+
createElement(Text, { style: styles.loadingText }, loadingLabel)
|
|
1506
|
+
)
|
|
1507
|
+
}) : null
|
|
1508
|
+
)
|
|
1371
1509
|
)
|
|
1372
1510
|
)
|
|
1373
1511
|
);
|
|
1374
1512
|
}
|
|
1375
|
-
var styles =
|
|
1513
|
+
var styles = StyleSheet.create({
|
|
1376
1514
|
root: {
|
|
1377
1515
|
flex: 1
|
|
1378
1516
|
},
|
|
@@ -1380,6 +1518,11 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
1380
1518
|
flex: 1,
|
|
1381
1519
|
backgroundColor: "#ffffff"
|
|
1382
1520
|
},
|
|
1521
|
+
modalContent: {
|
|
1522
|
+
flex: 1,
|
|
1523
|
+
width: "100%",
|
|
1524
|
+
backgroundColor: "#ffffff"
|
|
1525
|
+
},
|
|
1383
1526
|
header: {
|
|
1384
1527
|
minHeight: 48,
|
|
1385
1528
|
alignItems: "flex-end",
|
|
@@ -1453,7 +1596,7 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
1453
1596
|
borderStyle: "none"
|
|
1454
1597
|
},
|
|
1455
1598
|
loading: {
|
|
1456
|
-
...
|
|
1599
|
+
...StyleSheet.absoluteFillObject,
|
|
1457
1600
|
alignItems: "center",
|
|
1458
1601
|
justifyContent: "center",
|
|
1459
1602
|
backgroundColor: "#ffffff"
|
|
@@ -1466,7 +1609,7 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
1466
1609
|
});
|
|
1467
1610
|
|
|
1468
1611
|
// src/hooks/useSagepilotChat.ts
|
|
1469
|
-
|
|
1612
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
1470
1613
|
function readState() {
|
|
1471
1614
|
const state = SagepilotChat.getState();
|
|
1472
1615
|
return {
|
|
@@ -1478,23 +1621,28 @@ function readState() {
|
|
|
1478
1621
|
};
|
|
1479
1622
|
}
|
|
1480
1623
|
function useSagepilotChat() {
|
|
1481
|
-
const [state, setState] = (
|
|
1482
|
-
(
|
|
1624
|
+
const [state, setState] = useState2(readState);
|
|
1625
|
+
useEffect2(() => {
|
|
1483
1626
|
return SagepilotChat.onStateChange(() => {
|
|
1484
1627
|
setState(readState());
|
|
1485
1628
|
});
|
|
1486
1629
|
}, []);
|
|
1487
|
-
const present = (
|
|
1488
|
-
const presentMessages = (
|
|
1489
|
-
const presentMessageComposer = (
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
const
|
|
1493
|
-
const
|
|
1630
|
+
const present = useCallback2(() => SagepilotChat.present(), []);
|
|
1631
|
+
const presentMessages = useCallback2(() => SagepilotChat.presentMessages(), []);
|
|
1632
|
+
const presentMessageComposer = useCallback2((message, options) => {
|
|
1633
|
+
return SagepilotChat.presentMessageComposer(message, options);
|
|
1634
|
+
}, []);
|
|
1635
|
+
const dismiss = useCallback2(() => SagepilotChat.dismiss(), []);
|
|
1636
|
+
const hide = useCallback2(() => SagepilotChat.hide(), []);
|
|
1637
|
+
const toggle = useCallback2(() => SagepilotChat.toggle(), []);
|
|
1638
|
+
const identify = useCallback2((identity) => {
|
|
1494
1639
|
return SagepilotChat.identify(identity);
|
|
1495
1640
|
}, []);
|
|
1496
|
-
const logout = (
|
|
1497
|
-
const getUnreadCount = (
|
|
1641
|
+
const logout = useCallback2(() => SagepilotChat.logout(), []);
|
|
1642
|
+
const getUnreadCount = useCallback2(() => SagepilotChat.getUnreadCount(), []);
|
|
1643
|
+
const onConversationCreated = useCallback2((callback) => {
|
|
1644
|
+
return SagepilotChat.onConversationCreated(callback);
|
|
1645
|
+
}, []);
|
|
1498
1646
|
return {
|
|
1499
1647
|
...state,
|
|
1500
1648
|
present,
|
|
@@ -1505,15 +1653,15 @@ function useSagepilotChat() {
|
|
|
1505
1653
|
toggle,
|
|
1506
1654
|
identify,
|
|
1507
1655
|
logout,
|
|
1508
|
-
getUnreadCount
|
|
1656
|
+
getUnreadCount,
|
|
1657
|
+
onConversationCreated
|
|
1509
1658
|
};
|
|
1510
1659
|
}
|
|
1511
|
-
|
|
1512
|
-
0 && (module.exports = {
|
|
1660
|
+
export {
|
|
1513
1661
|
SagepilotChat,
|
|
1514
1662
|
SagepilotChatError,
|
|
1515
1663
|
SagepilotChatProvider,
|
|
1516
1664
|
createAsyncStorageCacheStorage,
|
|
1517
1665
|
createKeychainTokenStorage,
|
|
1518
1666
|
useSagepilotChat
|
|
1519
|
-
}
|
|
1667
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sagepilot-ai/react-native-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Sagepilot AI React Native chat SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sagepilot",
|
|
@@ -11,28 +11,38 @@
|
|
|
11
11
|
"sdk"
|
|
12
12
|
],
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"module": "./dist/index.mjs",
|
|
16
|
+
"react-native": "./dist/index.js",
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/index.d.ts",
|
|
21
|
-
"import": "./dist/index.
|
|
22
|
-
"require": "./dist/index.
|
|
21
|
+
"import": "./dist/index.mjs",
|
|
22
|
+
"require": "./dist/index.js"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
26
|
"LICENSE.md",
|
|
27
|
-
"android",
|
|
27
|
+
"android/build.gradle",
|
|
28
|
+
"android/src",
|
|
28
29
|
"dist",
|
|
29
30
|
"ios",
|
|
30
31
|
"react-native.config.js",
|
|
32
|
+
"src/specs",
|
|
31
33
|
"README.md"
|
|
32
34
|
],
|
|
35
|
+
"codegenConfig": {
|
|
36
|
+
"name": "SagepilotReactNativeSdkSpec",
|
|
37
|
+
"type": "components",
|
|
38
|
+
"jsSrcsDir": "./src/specs",
|
|
39
|
+
"android": {
|
|
40
|
+
"javaPackageName": "ai.sagepilot.reactnativesdk"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
33
43
|
"sideEffects": false,
|
|
34
44
|
"scripts": {
|
|
35
|
-
"build": "tsup
|
|
45
|
+
"build": "tsup",
|
|
36
46
|
"typecheck": "tsc --noEmit",
|
|
37
47
|
"prepublishOnly": "npm run typecheck && npm run build"
|
|
38
48
|
},
|