vdb-ai-chat 1.0.3 → 1.0.5
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/dist/chat-widget.js +1 -1
- package/lib/commonjs/api.js +19 -4
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/components/ChatWidget.js +27 -13
- package/lib/commonjs/components/ChatWidget.js.map +1 -1
- package/lib/commonjs/components/LazyProductsFetcher.js +3 -2
- package/lib/commonjs/components/LazyProductsFetcher.js.map +1 -1
- package/lib/commonjs/components/utils.js +38 -2
- package/lib/commonjs/components/utils.js.map +1 -1
- package/lib/commonjs/storage.js +13 -0
- package/lib/commonjs/storage.js.map +1 -1
- package/lib/module/api.js +19 -4
- package/lib/module/api.js.map +1 -1
- package/lib/module/components/ChatWidget.js +28 -14
- package/lib/module/components/ChatWidget.js.map +1 -1
- package/lib/module/components/LazyProductsFetcher.js +3 -2
- package/lib/module/components/LazyProductsFetcher.js.map +1 -1
- package/lib/module/components/utils.js +34 -0
- package/lib/module/components/utils.js.map +1 -1
- package/lib/module/storage.js +13 -0
- package/lib/module/storage.js.map +1 -1
- package/lib/typescript/api.d.ts +1 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/components/ChatWidget.d.ts.map +1 -1
- package/lib/typescript/components/LazyProductsFetcher.d.ts +1 -0
- package/lib/typescript/components/LazyProductsFetcher.d.ts.map +1 -1
- package/lib/typescript/components/utils.d.ts +9 -0
- package/lib/typescript/components/utils.d.ts.map +1 -1
- package/lib/typescript/storage.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/api.ts +31 -4
- package/src/components/ChatWidget.tsx +30 -8
- package/src/components/LazyProductsFetcher.tsx +3 -1
- package/src/components/utils.ts +34 -4
- package/src/storage.ts +13 -0
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
FeedbackAction,
|
|
39
39
|
formatToTime,
|
|
40
40
|
getUserDetails,
|
|
41
|
+
useDeviceType,
|
|
41
42
|
UserDetails,
|
|
42
43
|
} from "./utils";
|
|
43
44
|
import { useUserAnalytics } from "../hooks/useAnalytics";
|
|
@@ -86,13 +87,19 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
86
87
|
const theme = useMemo(() => mergeTheme(themeOverrides), [themeOverrides]);
|
|
87
88
|
const { _identify } = useUserAnalytics();
|
|
88
89
|
const betaActive = Boolean(isBetaModeProp);
|
|
90
|
+
const { isTablet } = useDeviceType();
|
|
89
91
|
const noResultsText =
|
|
90
92
|
"No results found for your search. Try adjusting your filters or query.";
|
|
91
93
|
useEffect(() => {
|
|
92
94
|
const loadAuthData = async () => {
|
|
93
95
|
try {
|
|
94
96
|
if (!userTokenProp) {
|
|
95
|
-
const
|
|
97
|
+
const userInfo = await Storage.getJSON<UserDetails>(
|
|
98
|
+
"persist:userInfo",
|
|
99
|
+
{}
|
|
100
|
+
);
|
|
101
|
+
const userData = JSON.parse(userInfo?.user || "{}");
|
|
102
|
+
const token = userData?.token || "";
|
|
96
103
|
if (token) {
|
|
97
104
|
setUserToken(token);
|
|
98
105
|
}
|
|
@@ -305,7 +312,8 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
305
312
|
Object.keys(latestAssistant.search_payload).length > 0
|
|
306
313
|
) {
|
|
307
314
|
const productsResult = await getProducts(
|
|
308
|
-
latestAssistant.search_payload
|
|
315
|
+
latestAssistant.search_payload,
|
|
316
|
+
priceMode as string
|
|
309
317
|
);
|
|
310
318
|
|
|
311
319
|
const hasDiamonds =
|
|
@@ -425,7 +433,7 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
425
433
|
setReloadLoadingIds((prev) => new Set(prev).add(id));
|
|
426
434
|
const payload = msg?.search_payload;
|
|
427
435
|
if (!payload || Object.keys(payload).length === 0) return;
|
|
428
|
-
const productsResult = await getProducts(payload);
|
|
436
|
+
const productsResult = await getProducts(payload, priceMode as string);
|
|
429
437
|
setProductsByMsg((prev) => ({ ...prev, [id]: productsResult }));
|
|
430
438
|
} catch (e) {
|
|
431
439
|
console.error("Reload results failed", e);
|
|
@@ -598,13 +606,13 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
598
606
|
<View
|
|
599
607
|
style={[styles.container, { backgroundColor: theme.backgroundColor }]}
|
|
600
608
|
>
|
|
601
|
-
{Platform.OS === "web" && (
|
|
609
|
+
{/* {Platform.OS === "web" && (
|
|
602
610
|
<ChatHeader
|
|
603
611
|
onClose={onClose}
|
|
604
612
|
onClearChat={handleClearChat}
|
|
605
613
|
isBetaMode={betaActive}
|
|
606
614
|
/>
|
|
607
|
-
)}
|
|
615
|
+
)} */}
|
|
608
616
|
<KeyboardAvoidingView
|
|
609
617
|
style={{ flex: 1 }}
|
|
610
618
|
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
@@ -625,6 +633,9 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
625
633
|
...styles.listContent,
|
|
626
634
|
justifyContent: messages.length === 0 ? "center" : "flex-end",
|
|
627
635
|
minHeight: modalHeight ? modalHeight : undefined,
|
|
636
|
+
...(isTablet
|
|
637
|
+
? { maxWidth: 608, alignSelf: "center", width: "100%" }
|
|
638
|
+
: {}),
|
|
628
639
|
}}
|
|
629
640
|
onContentSizeChange={() => {
|
|
630
641
|
scrollRef.current?.scrollToEnd({ animated: false });
|
|
@@ -673,6 +684,7 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
673
684
|
Object.keys(item.search_payload).length > 0 &&
|
|
674
685
|
!productsByMsg[item.id] && (
|
|
675
686
|
<LazyProductsFetcher
|
|
687
|
+
priceMode={priceMode as string}
|
|
676
688
|
messageId={item.id}
|
|
677
689
|
payload={item.search_payload}
|
|
678
690
|
onFetched={(id, result) => {
|
|
@@ -735,7 +747,15 @@ export const ChatWidget = forwardRef<ChatWidgetRef, ChatWidgetProps>(
|
|
|
735
747
|
});
|
|
736
748
|
})()}
|
|
737
749
|
</ScrollView>
|
|
738
|
-
<View style={styles.
|
|
750
|
+
<View style={styles.borderTop} />
|
|
751
|
+
<View
|
|
752
|
+
style={[
|
|
753
|
+
styles.bottomContainer,
|
|
754
|
+
isTablet
|
|
755
|
+
? { maxWidth: 608, alignSelf: "center", width: "100%" }
|
|
756
|
+
: {},
|
|
757
|
+
]}
|
|
758
|
+
>
|
|
739
759
|
<ChatInput
|
|
740
760
|
value={input}
|
|
741
761
|
onChangeText={setInput}
|
|
@@ -783,12 +803,14 @@ const styles = StyleSheet.create({
|
|
|
783
803
|
bottomContainer: {
|
|
784
804
|
paddingVertical: 12,
|
|
785
805
|
paddingHorizontal: 16,
|
|
786
|
-
borderTopColor: "#E0E0E0",
|
|
787
|
-
borderTopWidth: 1,
|
|
788
806
|
flexDirection: "column",
|
|
789
807
|
justifyContent: "space-between",
|
|
790
808
|
alignItems: "center",
|
|
791
809
|
alignSelf: "stretch",
|
|
792
810
|
gap: 12,
|
|
793
811
|
},
|
|
812
|
+
borderTop: {
|
|
813
|
+
borderTopColor: "#E0E0E0",
|
|
814
|
+
borderTopWidth: 1,
|
|
815
|
+
},
|
|
794
816
|
});
|
|
@@ -7,12 +7,14 @@ interface LazyProductsFetcherProps {
|
|
|
7
7
|
messageId: string;
|
|
8
8
|
payload: Record<string, any> | undefined | null;
|
|
9
9
|
onFetched: (messageId: string, data: any) => void;
|
|
10
|
+
priceMode: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const LazyProductsFetcher: React.FC<LazyProductsFetcherProps> = ({
|
|
13
14
|
messageId,
|
|
14
15
|
payload,
|
|
15
16
|
onFetched,
|
|
17
|
+
priceMode,
|
|
16
18
|
}) => {
|
|
17
19
|
const { ref, inView } = useInViewport<HTMLDivElement>();
|
|
18
20
|
const fetchedRef = useRef(false);
|
|
@@ -25,7 +27,7 @@ const LazyProductsFetcher: React.FC<LazyProductsFetcherProps> = ({
|
|
|
25
27
|
fetchedRef.current = true;
|
|
26
28
|
(async () => {
|
|
27
29
|
try {
|
|
28
|
-
const result = await getProducts(payload);
|
|
30
|
+
const result = await getProducts(payload, priceMode as string);
|
|
29
31
|
onFetched(messageId, result);
|
|
30
32
|
} catch (e) {
|
|
31
33
|
// eslint-disable-next-line no-console
|
package/src/components/utils.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { Dimensions } from "react-native";
|
|
1
2
|
import { Storage } from "../storage";
|
|
3
|
+
import { useMediaQuery } from "react-responsive";
|
|
4
|
+
|
|
5
|
+
export const DEVICE_SIZE = Dimensions.get("window");
|
|
2
6
|
|
|
3
7
|
export function formatToTime(timestamp: number): string {
|
|
4
8
|
const date = new Date(timestamp);
|
|
@@ -32,10 +36,7 @@ export const fetchConversationId = async (
|
|
|
32
36
|
|
|
33
37
|
let priceMode = _priceMode;
|
|
34
38
|
if (priceMode === undefined) {
|
|
35
|
-
const userInfo = await Storage.getJSON<UserDetails>(
|
|
36
|
-
"persist:userInfo",
|
|
37
|
-
{}
|
|
38
|
-
);
|
|
39
|
+
const userInfo = await Storage.getJSON<UserDetails>("persist:userInfo", {});
|
|
39
40
|
const userData = userInfo?.user as UserDetails;
|
|
40
41
|
priceMode = String(userData?.price_mode) || "";
|
|
41
42
|
}
|
|
@@ -53,6 +54,7 @@ export interface UserDetails {
|
|
|
53
54
|
price_mode?: string | number;
|
|
54
55
|
plan_details?: any;
|
|
55
56
|
user?: any;
|
|
57
|
+
searchResultViewType?: string;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
export const getUserDetails = async (): Promise<UserDetails | null> => {
|
|
@@ -102,3 +104,31 @@ export enum AnalyticsEventNames {
|
|
|
102
104
|
WIDGET_CLOSED = "ai_chat_widget_closed",
|
|
103
105
|
CHAT_CLEARED = "ai_chat_cleared",
|
|
104
106
|
}
|
|
107
|
+
|
|
108
|
+
export const isIpad = () => {
|
|
109
|
+
// const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
|
110
|
+
// return (
|
|
111
|
+
// /iPad/.test(userAgent) ||
|
|
112
|
+
// (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)
|
|
113
|
+
// );
|
|
114
|
+
const userAgent =
|
|
115
|
+
navigator.userAgent || navigator.vendor || (window as any).opera;
|
|
116
|
+
return (
|
|
117
|
+
/iPad/.test(userAgent) ||
|
|
118
|
+
(/\bMac/.test(userAgent) &&
|
|
119
|
+
navigator.maxTouchPoints > 0 &&
|
|
120
|
+
!/iPhone/.test(userAgent))
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const useDeviceType = () => {
|
|
125
|
+
const { width } = DEVICE_SIZE;
|
|
126
|
+
const isMobile = useMediaQuery({ maxWidth: 767 }) || width < 767;
|
|
127
|
+
const isTablet =
|
|
128
|
+
useMediaQuery({ minWidth: 767, maxWidth: 1279 }) ||
|
|
129
|
+
(width > 767 && width <= 1279) ||
|
|
130
|
+
isIpad();
|
|
131
|
+
const isDesktop = useMediaQuery({ minWidth: 1279 }) || width > 1279;
|
|
132
|
+
const isLargeScreen = isDesktop && !isTablet && !isMobile;
|
|
133
|
+
return { isMobile, isTablet, isDesktop, isLargeScreen };
|
|
134
|
+
};
|
package/src/storage.ts
CHANGED
|
@@ -15,10 +15,23 @@ function getLocalStorage(): Storage | null {
|
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
// Helper to safely get sessionStorage (only available on web)
|
|
19
|
+
function getSessionStorage(): Storage | null {
|
|
20
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
21
|
+
return window.sessionStorage;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
18
26
|
// Web storage implementation using localStorage (lazy access)
|
|
19
27
|
const webStorage: StorageInterface = {
|
|
20
28
|
getItem: async (key: string) => {
|
|
21
29
|
try {
|
|
30
|
+
// Use sessionStorage for persist:searchFilters key
|
|
31
|
+
if (key === "persist:searchFilters") {
|
|
32
|
+
const sessionStore = getSessionStorage();
|
|
33
|
+
return sessionStore ? sessionStore.getItem(key) : null;
|
|
34
|
+
}
|
|
22
35
|
const storage = getLocalStorage();
|
|
23
36
|
return storage ? storage.getItem(key) : null;
|
|
24
37
|
} catch {
|