vdb-ai-chat 1.0.4 → 1.0.6
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 +37 -5
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/components/BetaNotice.js +5 -2
- package/lib/commonjs/components/BetaNotice.js.map +1 -1
- package/lib/commonjs/components/ChatHeader.js +20 -5
- package/lib/commonjs/components/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/ChatWidget.js +58 -23
- package/lib/commonjs/components/ChatWidget.js.map +1 -1
- package/lib/commonjs/components/LazyProductsFetcher.js +4 -3
- package/lib/commonjs/components/LazyProductsFetcher.js.map +1 -1
- package/lib/commonjs/components/MessageMetaRow.js +18 -8
- package/lib/commonjs/components/MessageMetaRow.js.map +1 -1
- package/lib/commonjs/components/ProductsList.js +12 -5
- package/lib/commonjs/components/ProductsList.js.map +1 -1
- package/lib/commonjs/components/ProductsListView.js +142 -29
- package/lib/commonjs/components/ProductsListView.js.map +1 -1
- package/lib/commonjs/components/utils.js +44 -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 +37 -5
- package/lib/module/api.js.map +1 -1
- package/lib/module/components/BetaNotice.js +5 -2
- package/lib/module/components/BetaNotice.js.map +1 -1
- package/lib/module/components/ChatHeader.js +20 -5
- package/lib/module/components/ChatHeader.js.map +1 -1
- package/lib/module/components/ChatWidget.js +59 -24
- package/lib/module/components/ChatWidget.js.map +1 -1
- package/lib/module/components/LazyProductsFetcher.js +4 -3
- package/lib/module/components/LazyProductsFetcher.js.map +1 -1
- package/lib/module/components/MessageMetaRow.js +18 -8
- package/lib/module/components/MessageMetaRow.js.map +1 -1
- package/lib/module/components/ProductsList.js +12 -5
- package/lib/module/components/ProductsList.js.map +1 -1
- package/lib/module/components/ProductsListView.js +144 -31
- package/lib/module/components/ProductsListView.js.map +1 -1
- package/lib/module/components/utils.js +39 -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/BetaNotice.d.ts.map +1 -1
- package/lib/typescript/components/ChatHeader.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/MessageMetaRow.d.ts.map +1 -1
- package/lib/typescript/components/ProductsList.d.ts +2 -1
- package/lib/typescript/components/ProductsList.d.ts.map +1 -1
- package/lib/typescript/components/ProductsListView.d.ts +2 -1
- package/lib/typescript/components/ProductsListView.d.ts.map +1 -1
- package/lib/typescript/components/utils.d.ts +11 -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 +57 -6
- package/src/components/BetaNotice.tsx +3 -0
- package/src/components/ChatHeader.tsx +18 -3
- package/src/components/ChatWidget.tsx +52 -19
- package/src/components/LazyProductsFetcher.tsx +4 -2
- package/src/components/MessageMetaRow.tsx +14 -14
- package/src/components/ProductsList.tsx +14 -3
- package/src/components/ProductsListView.tsx +288 -134
- package/src/components/utils.ts +44 -4
- package/src/storage.ts +13 -0
|
@@ -1,148 +1,302 @@
|
|
|
1
|
-
import React, { memo, useState } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import React, { memo, useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
View,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
ScrollView,
|
|
8
|
+
Platform,
|
|
9
|
+
Image,
|
|
10
|
+
Pressable,
|
|
11
|
+
} from "react-native";
|
|
12
|
+
import { getUserCurrencySymbol } from "./utils";
|
|
3
13
|
|
|
4
14
|
let ImageComponent: typeof Image = Image;
|
|
5
15
|
if (Platform.OS !== "web") {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
try {
|
|
17
|
+
const ExpoImage = require("expo-image").Image;
|
|
18
|
+
if (ExpoImage) ImageComponent = ExpoImage;
|
|
19
|
+
} catch {
|
|
20
|
+
// expo-image not installed, use React Native Image
|
|
21
|
+
}
|
|
12
22
|
}
|
|
13
23
|
|
|
14
24
|
interface ProductsListViewProps {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
data: any[];
|
|
26
|
+
totalResults?: number;
|
|
27
|
+
onViewAll: (item: any) => void;
|
|
28
|
+
onItemPress?: (item: any) => void;
|
|
29
|
+
item: any;
|
|
19
30
|
}
|
|
20
31
|
|
|
21
|
-
const ProductsListViewComponent: React.FC<ProductsListViewProps> = ({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
32
|
+
const ProductsListViewComponent: React.FC<ProductsListViewProps> = ({
|
|
33
|
+
data,
|
|
34
|
+
totalResults,
|
|
35
|
+
onViewAll,
|
|
36
|
+
onItemPress,
|
|
37
|
+
item,
|
|
38
|
+
}) => {
|
|
39
|
+
if (!data || !data.length) return null;
|
|
40
|
+
|
|
41
|
+
const [userCurrency, setUserCurrency] = useState<string | null>(null);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const fetchCurrency = async () => {
|
|
45
|
+
const currency = await getUserCurrencySymbol();
|
|
46
|
+
setUserCurrency(currency);
|
|
47
|
+
};
|
|
48
|
+
fetchCurrency();
|
|
49
|
+
}, []);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<View style={styles.wrapper}>
|
|
53
|
+
<ScrollView
|
|
54
|
+
showsVerticalScrollIndicator={false}
|
|
55
|
+
contentContainerStyle={styles.listContent}
|
|
56
|
+
>
|
|
57
|
+
{data.map((item: any, index: number) => (
|
|
58
|
+
<Pressable
|
|
59
|
+
key={item.id}
|
|
60
|
+
onPress={() => onItemPress?.(item)}
|
|
61
|
+
// @ts-ignore - hovered is available on web
|
|
62
|
+
style={({ hovered }) => [
|
|
63
|
+
styles.itemContainer,
|
|
64
|
+
hovered && styles.itemHover,
|
|
65
|
+
]}
|
|
66
|
+
>
|
|
67
|
+
<View>
|
|
68
|
+
<View style={styles.left}>
|
|
69
|
+
<View style={styles.serialContainer}>
|
|
70
|
+
<Text style={styles.serial}>{index + 1}.</Text>
|
|
71
|
+
</View>
|
|
72
|
+
<View style={styles.tokens}>
|
|
73
|
+
{/* Shape */}
|
|
74
|
+
<Text style={styles.textStyleOne}>
|
|
75
|
+
{item.shape_long ?? "-"}
|
|
76
|
+
</Text>
|
|
77
|
+
{/* Carat size */}
|
|
78
|
+
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
|
79
|
+
<Text style={styles.textStyleTwo}>{item.size ?? "-"}</Text>
|
|
80
|
+
{item.price_per_carat ? (
|
|
81
|
+
<Text style={styles.textStyleOne}>ct</Text>
|
|
82
|
+
) : (
|
|
83
|
+
<></>
|
|
84
|
+
)}
|
|
85
|
+
</View>
|
|
86
|
+
{/* Color */}
|
|
87
|
+
<Text style={styles.textStyleOne}>{item.color ?? "-"}</Text>
|
|
88
|
+
{/* Clarity */}
|
|
89
|
+
<Text style={styles.textStyleOne}>
|
|
90
|
+
{item.clarity_short ?? "-"}
|
|
91
|
+
</Text>
|
|
92
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
93
|
+
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
|
94
|
+
{/* Cut */}
|
|
95
|
+
<Text style={styles.textStyleOne}>
|
|
96
|
+
{item.cut_short ?? "-"}
|
|
97
|
+
</Text>
|
|
98
|
+
<Text style={styles.textStyleOne}>{"/"}</Text>
|
|
99
|
+
{/* Polish */}
|
|
100
|
+
<Text style={styles.textStyleOne}>
|
|
101
|
+
{item.polish_short ?? "-"}
|
|
102
|
+
</Text>
|
|
103
|
+
<Text style={styles.textStyleOne}>{"/"}</Text>
|
|
104
|
+
{/* Symmetry */}
|
|
105
|
+
<Text style={styles.textStyleOne}>
|
|
106
|
+
{item.symmetry_short ?? "-"}
|
|
107
|
+
</Text>
|
|
108
|
+
</View>
|
|
109
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
110
|
+
{/* Fluorescence */}
|
|
111
|
+
<Text style={styles.textStyleOne}>
|
|
112
|
+
{item.fluorescence_intensity_short ?? "-"}
|
|
113
|
+
</Text>
|
|
114
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
115
|
+
{/* LAB */}
|
|
116
|
+
<Text style={styles.textStyleOne}>
|
|
117
|
+
{item.lab_short ?? "-"}
|
|
118
|
+
</Text>
|
|
119
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
120
|
+
{/* Discount */}
|
|
121
|
+
<Text style={styles.textStyleTwo}>
|
|
122
|
+
{item.discount_percent ? item.discount_percent + "%" : "-"}
|
|
123
|
+
</Text>
|
|
124
|
+
<View style={styles.lineBreak} />
|
|
125
|
+
{/* Depth */}
|
|
126
|
+
<Text style={styles.textStyleOne}>{"D"}</Text>
|
|
127
|
+
<Text style={styles.textStyleTwo}>
|
|
128
|
+
{item.depth_percent ? item.depth_percent + "%" : "-"}
|
|
129
|
+
</Text>
|
|
130
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
131
|
+
{/* Table */}
|
|
132
|
+
<Text style={styles.textStyleOne}>{"T"}</Text>
|
|
133
|
+
<Text style={styles.textStyleTwo}>
|
|
134
|
+
{item.table_percent ? item.table_percent + "%" : "-"}
|
|
135
|
+
</Text>
|
|
136
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
137
|
+
{/* Meas */}
|
|
138
|
+
<Text style={styles.textStyleTwo}>
|
|
139
|
+
{item.measurement ?? "-"}
|
|
140
|
+
</Text>
|
|
141
|
+
<Text style={styles.textStyleOne}>{"·"}</Text>
|
|
142
|
+
{/* Price Per Carat */}
|
|
143
|
+
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
|
144
|
+
{item.price_per_carat ? (
|
|
145
|
+
<Text style={styles.textStyleTwo}>
|
|
146
|
+
{userCurrency ? userCurrency : "$"}
|
|
147
|
+
</Text>
|
|
148
|
+
) : (
|
|
149
|
+
<></>
|
|
150
|
+
)}
|
|
151
|
+
<Text style={styles.textStyleTwo}>
|
|
152
|
+
{item.price_per_carat ?? "-"}
|
|
153
|
+
</Text>
|
|
154
|
+
<Text style={styles.textStyleOne}>{"PC"}</Text>
|
|
155
|
+
</View>
|
|
156
|
+
{/* Total Sales Price */}
|
|
157
|
+
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
|
158
|
+
<Text style={styles.textStyleOne}>{" ="}</Text>
|
|
159
|
+
{item.total_sales_price ? (
|
|
160
|
+
<Text style={styles.textStyleTwo}>
|
|
161
|
+
{userCurrency ? userCurrency : "$"}
|
|
162
|
+
</Text>
|
|
163
|
+
) : (
|
|
164
|
+
<></>
|
|
165
|
+
)}
|
|
166
|
+
<Text style={styles.textStyleTwo}>
|
|
167
|
+
{item.total_sales_price ?? "-"}
|
|
168
|
+
</Text>
|
|
169
|
+
</View>
|
|
170
|
+
</View>
|
|
171
|
+
</View>
|
|
172
|
+
</View>
|
|
173
|
+
</Pressable>
|
|
174
|
+
))}
|
|
175
|
+
</ScrollView>
|
|
176
|
+
|
|
177
|
+
<TouchableOpacity
|
|
178
|
+
style={styles.button}
|
|
179
|
+
activeOpacity={0.8}
|
|
180
|
+
onPress={() => onViewAll(item)}
|
|
181
|
+
>
|
|
182
|
+
<Text
|
|
183
|
+
style={styles.buttonText}
|
|
184
|
+
>{`View All ${totalResults} Results`}</Text>
|
|
185
|
+
<Image
|
|
186
|
+
source={{
|
|
187
|
+
uri: "https://cdn.vdbapp.com/ai/chat-widget/assets/img/right.svg",
|
|
188
|
+
}}
|
|
189
|
+
resizeMode="contain"
|
|
190
|
+
style={{ width: 20, height: 20, tintColor: "#fff" }}
|
|
191
|
+
/>
|
|
192
|
+
</TouchableOpacity>
|
|
193
|
+
</View>
|
|
194
|
+
);
|
|
74
195
|
};
|
|
75
196
|
|
|
76
197
|
const styles = StyleSheet.create({
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
198
|
+
wrapper: {
|
|
199
|
+
paddingHorizontal: 8,
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
listContent: {
|
|
203
|
+
gap: 8,
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
row: {
|
|
207
|
+
flexDirection: "row",
|
|
208
|
+
justifyContent: "space-between",
|
|
209
|
+
alignItems: "center",
|
|
210
|
+
paddingVertical: 6,
|
|
211
|
+
backgroundColor: "#fff",
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
left: {
|
|
215
|
+
flexDirection: "row",
|
|
216
|
+
alignItems: "flex-start",
|
|
217
|
+
minWidth: 0,
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
serialContainer: {
|
|
221
|
+
alignItems: "flex-start",
|
|
222
|
+
justifyContent: "center",
|
|
223
|
+
marginRight: 4,
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
tokens: {
|
|
227
|
+
flexDirection: "row",
|
|
228
|
+
flexWrap: "wrap",
|
|
229
|
+
gap: 2,
|
|
230
|
+
flex: 1,
|
|
231
|
+
minWidth: 0,
|
|
232
|
+
},
|
|
233
|
+
lineBreak: {
|
|
234
|
+
width: "100%",
|
|
235
|
+
height: 0,
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
serial: {
|
|
239
|
+
fontSize: 13,
|
|
240
|
+
color: "#020001",
|
|
241
|
+
fontWeight: "500",
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
textStyleOne: {
|
|
245
|
+
fontFamily: "Roboto",
|
|
246
|
+
fontSize: 13,
|
|
247
|
+
fontStyle: "normal",
|
|
248
|
+
fontWeight: "400",
|
|
249
|
+
color: "#4F4E57",
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
textStyleTwo: {
|
|
253
|
+
fontFamily: "Roboto",
|
|
254
|
+
fontSize: 13,
|
|
255
|
+
fontStyle: "normal",
|
|
256
|
+
fontWeight: "500",
|
|
257
|
+
color: "#020001",
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
price: {
|
|
261
|
+
fontSize: 13,
|
|
262
|
+
fontWeight: "500",
|
|
263
|
+
color: "#020001",
|
|
264
|
+
textAlign: "left",
|
|
265
|
+
},
|
|
266
|
+
priceContainer: {
|
|
267
|
+
alignItems: "flex-start",
|
|
268
|
+
justifyContent: "center",
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
itemContainer: {
|
|
272
|
+
paddingVertical: 2,
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
itemHover: {
|
|
276
|
+
backgroundColor: "#EDEDF2",
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
button: {
|
|
280
|
+
marginTop: 12,
|
|
281
|
+
marginHorizontal: 12,
|
|
282
|
+
alignSelf: "center",
|
|
283
|
+
paddingHorizontal: 16,
|
|
284
|
+
paddingVertical: 6,
|
|
285
|
+
backgroundColor: "#292735",
|
|
286
|
+
borderRadius: 8,
|
|
287
|
+
alignItems: "center",
|
|
288
|
+
gap: 16,
|
|
289
|
+
width: "100%",
|
|
290
|
+
flexDirection: "row",
|
|
291
|
+
justifyContent: "center",
|
|
292
|
+
alignContent: "center",
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
buttonText: {
|
|
296
|
+
color: "#fff",
|
|
297
|
+
fontSize: 14,
|
|
298
|
+
fontWeight: "600",
|
|
299
|
+
},
|
|
146
300
|
});
|
|
147
301
|
|
|
148
302
|
const ProductsListView = memo(ProductsListViewComponent);
|
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,16 +36,22 @@ 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
|
}
|
|
42
43
|
return conversations[priceMode]?.conversation_id || null;
|
|
43
44
|
};
|
|
44
45
|
|
|
46
|
+
export const getUserCurrencySymbol = async (): Promise<string | null> => {
|
|
47
|
+
const userInfo = await Storage.getJSON<UserDetails>(
|
|
48
|
+
"persist:userInfo",
|
|
49
|
+
{}
|
|
50
|
+
);
|
|
51
|
+
const userData = userInfo?.user as UserDetails;
|
|
52
|
+
return userData.currency_symbol || "$";
|
|
53
|
+
};
|
|
54
|
+
|
|
45
55
|
export interface UserDetails {
|
|
46
56
|
id?: string | number;
|
|
47
57
|
email?: string;
|
|
@@ -53,6 +63,8 @@ export interface UserDetails {
|
|
|
53
63
|
price_mode?: string | number;
|
|
54
64
|
plan_details?: any;
|
|
55
65
|
user?: any;
|
|
66
|
+
searchResultViewType?: string;
|
|
67
|
+
currency_symbol?: string;
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
export const getUserDetails = async (): Promise<UserDetails | null> => {
|
|
@@ -102,3 +114,31 @@ export enum AnalyticsEventNames {
|
|
|
102
114
|
WIDGET_CLOSED = "ai_chat_widget_closed",
|
|
103
115
|
CHAT_CLEARED = "ai_chat_cleared",
|
|
104
116
|
}
|
|
117
|
+
|
|
118
|
+
export const isIpad = () => {
|
|
119
|
+
// const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
|
120
|
+
// return (
|
|
121
|
+
// /iPad/.test(userAgent) ||
|
|
122
|
+
// (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1)
|
|
123
|
+
// );
|
|
124
|
+
const userAgent =
|
|
125
|
+
navigator.userAgent || navigator.vendor || (window as any).opera;
|
|
126
|
+
return (
|
|
127
|
+
/iPad/.test(userAgent) ||
|
|
128
|
+
(/\bMac/.test(userAgent) &&
|
|
129
|
+
navigator.maxTouchPoints > 0 &&
|
|
130
|
+
!/iPhone/.test(userAgent))
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const useDeviceType = () => {
|
|
135
|
+
const { width } = DEVICE_SIZE;
|
|
136
|
+
const isMobile = useMediaQuery({ maxWidth: 767 }) || width < 767;
|
|
137
|
+
const isTablet =
|
|
138
|
+
useMediaQuery({ minWidth: 767, maxWidth: 1279 }) ||
|
|
139
|
+
(width > 767 && width <= 1279) ||
|
|
140
|
+
isIpad();
|
|
141
|
+
const isDesktop = useMediaQuery({ minWidth: 1279 }) || width > 1279;
|
|
142
|
+
const isLargeScreen = isDesktop && !isTablet && !isMobile;
|
|
143
|
+
return { isMobile, isTablet, isDesktop, isLargeScreen };
|
|
144
|
+
};
|
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 {
|