stream-chat-react-native-core 5.28.0-beta.3 → 5.28.0-beta.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/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js +10 -43
- package/lib/commonjs/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/{AttachmentSelectionBar.js → AttachmentPickerSelectionBar.js} +6 -6
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/ImageGallery.js +29 -53
- package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js +2 -6
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
- package/lib/commonjs/components/MessageInput/MessageInput.js +6 -3
- package/lib/commonjs/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/commonjs/components/MessageInput/hooks/useCountdown.js.map +1 -1
- package/lib/commonjs/components/MessageList/MessageList.js.map +1 -1
- package/lib/commonjs/components/index.js +4 -4
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/attachmentPickerContext/AttachmentPickerContext.js +1 -2
- package/lib/commonjs/contexts/attachmentPickerContext/AttachmentPickerContext.js.map +1 -1
- package/lib/commonjs/contexts/overlayContext/OverlayContext.js.map +1 -1
- package/lib/commonjs/contexts/overlayContext/OverlayProvider.js +18 -9
- package/lib/commonjs/contexts/overlayContext/OverlayProvider.js.map +1 -1
- package/lib/commonjs/hooks/index.js +11 -0
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useScreenDimensions.js +47 -0
- package/lib/commonjs/hooks/useScreenDimensions.js.map +1 -0
- package/lib/commonjs/i18n/es.json +17 -17
- package/lib/commonjs/i18n/fr.json +17 -17
- package/lib/commonjs/i18n/he.json +17 -17
- package/lib/commonjs/i18n/hi.json +17 -17
- package/lib/commonjs/i18n/it.json +17 -17
- package/lib/commonjs/i18n/ja.json +17 -17
- package/lib/commonjs/i18n/ko.json +17 -17
- package/lib/commonjs/i18n/nl.json +17 -17
- package/lib/commonjs/i18n/pt-BR.json +14 -14
- package/lib/commonjs/i18n/ru.json +17 -17
- package/lib/commonjs/i18n/tr.json +14 -14
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/AttachmentPicker/AttachmentPicker.js +10 -43
- package/lib/module/components/AttachmentPicker/AttachmentPicker.js.map +1 -1
- package/lib/module/components/AttachmentPicker/components/{AttachmentSelectionBar.js → AttachmentPickerSelectionBar.js} +6 -6
- package/lib/module/components/AttachmentPicker/components/AttachmentPickerSelectionBar.js.map +1 -0
- package/lib/module/components/ImageGallery/ImageGallery.js +29 -53
- package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js +2 -6
- package/lib/module/components/ImageGallery/components/ImageGalleryHeader.js.map +1 -1
- package/lib/module/components/MessageInput/MessageInput.js +6 -3
- package/lib/module/components/MessageInput/MessageInput.js.map +1 -1
- package/lib/module/components/MessageInput/hooks/useCountdown.js.map +1 -1
- package/lib/module/components/MessageList/MessageList.js.map +1 -1
- package/lib/module/components/index.js +4 -4
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/attachmentPickerContext/AttachmentPickerContext.js +1 -2
- package/lib/module/contexts/attachmentPickerContext/AttachmentPickerContext.js.map +1 -1
- package/lib/module/contexts/overlayContext/OverlayContext.js.map +1 -1
- package/lib/module/contexts/overlayContext/OverlayProvider.js +18 -9
- package/lib/module/contexts/overlayContext/OverlayProvider.js.map +1 -1
- package/lib/module/hooks/index.js +11 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useScreenDimensions.js +47 -0
- package/lib/module/hooks/useScreenDimensions.js.map +1 -0
- package/lib/module/i18n/es.json +17 -17
- package/lib/module/i18n/fr.json +17 -17
- package/lib/module/i18n/he.json +17 -17
- package/lib/module/i18n/hi.json +17 -17
- package/lib/module/i18n/it.json +17 -17
- package/lib/module/i18n/ja.json +17 -17
- package/lib/module/i18n/ko.json +17 -17
- package/lib/module/i18n/nl.json +17 -17
- package/lib/module/i18n/pt-BR.json +14 -14
- package/lib/module/i18n/ru.json +17 -17
- package/lib/module/i18n/tr.json +14 -14
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts +30 -12
- package/lib/typescript/components/AttachmentPicker/AttachmentPicker.d.ts.map +1 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerSelectionBar.d.ts +3 -0
- package/lib/typescript/components/AttachmentPicker/components/AttachmentPickerSelectionBar.d.ts.map +1 -0
- package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +1 -1
- package/lib/typescript/components/ImageGallery/ImageGallery.d.ts.map +1 -1
- package/lib/typescript/components/ImageGallery/components/ImageGalleryHeader.d.ts.map +1 -1
- package/lib/typescript/components/MessageInput/MessageInput.d.ts +2 -1
- package/lib/typescript/components/MessageInput/MessageInput.d.ts.map +1 -1
- package/lib/typescript/components/index.d.ts +1 -1
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/contexts/attachmentPickerContext/AttachmentPickerContext.d.ts +32 -3
- package/lib/typescript/contexts/attachmentPickerContext/AttachmentPickerContext.d.ts.map +1 -1
- package/lib/typescript/contexts/overlayContext/OverlayContext.d.ts +2 -3
- package/lib/typescript/contexts/overlayContext/OverlayContext.d.ts.map +1 -1
- package/lib/typescript/contexts/overlayContext/OverlayProvider.d.ts.map +1 -1
- package/lib/typescript/hooks/index.d.ts +1 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -1
- package/lib/typescript/hooks/useScreenDimensions.d.ts +12 -0
- package/lib/typescript/hooks/useScreenDimensions.d.ts.map +1 -0
- package/lib/typescript/i18n/es.json +17 -17
- package/lib/typescript/i18n/fr.json +17 -17
- package/lib/typescript/i18n/he.json +17 -17
- package/lib/typescript/i18n/hi.json +17 -17
- package/lib/typescript/i18n/it.json +17 -17
- package/lib/typescript/i18n/ja.json +17 -17
- package/lib/typescript/i18n/ko.json +17 -17
- package/lib/typescript/i18n/nl.json +17 -17
- package/lib/typescript/i18n/pt-BR.json +14 -14
- package/lib/typescript/i18n/ru.json +17 -17
- package/lib/typescript/i18n/tr.json +14 -14
- package/package.json +1 -1
- package/src/components/AttachmentPicker/AttachmentPicker.tsx +21 -69
- package/src/components/AttachmentPicker/components/{AttachmentSelectionBar.tsx → AttachmentPickerSelectionBar.tsx} +2 -2
- package/src/components/ImageGallery/ImageGallery.tsx +31 -79
- package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +3 -19
- package/src/components/MessageInput/MessageInput.tsx +11 -7
- package/src/components/MessageInput/__tests__/MessageInput.test.js +2 -0
- package/src/components/MessageInput/hooks/useCountdown.ts +1 -1
- package/src/components/MessageList/MessageList.tsx +4 -4
- package/src/components/index.ts +1 -1
- package/src/contexts/attachmentPickerContext/AttachmentPickerContext.tsx +34 -10
- package/src/contexts/overlayContext/OverlayContext.tsx +5 -4
- package/src/contexts/overlayContext/OverlayProvider.tsx +11 -8
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useScreenDimensions.ts +41 -0
- package/src/i18n/es.json +17 -17
- package/src/i18n/fr.json +17 -17
- package/src/i18n/he.json +17 -17
- package/src/i18n/hi.json +17 -17
- package/src/i18n/it.json +17 -17
- package/src/i18n/ja.json +17 -17
- package/src/i18n/ko.json +17 -17
- package/src/i18n/nl.json +17 -17
- package/src/i18n/pt-BR.json +14 -14
- package/src/i18n/ru.json +17 -17
- package/src/i18n/tr.json +14 -14
- package/src/version.json +1 -1
- package/lib/commonjs/components/AttachmentPicker/components/AttachmentSelectionBar.js.map +0 -1
- package/lib/module/components/AttachmentPicker/components/AttachmentSelectionBar.js.map +0 -1
- package/lib/typescript/components/AttachmentPicker/components/AttachmentSelectionBar.d.ts +0 -3
- package/lib/typescript/components/AttachmentPicker/components/AttachmentSelectionBar.d.ts.map +0 -1
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Dimensions,
|
|
4
|
-
Image,
|
|
5
|
-
ImageStyle,
|
|
6
|
-
Keyboard,
|
|
7
|
-
Platform,
|
|
8
|
-
StatusBar,
|
|
9
|
-
StyleSheet,
|
|
10
|
-
ViewStyle,
|
|
11
|
-
} from 'react-native';
|
|
2
|
+
import { Image, ImageStyle, Keyboard, Platform, StyleSheet, ViewStyle } from 'react-native';
|
|
12
3
|
|
|
13
4
|
import {
|
|
14
5
|
PanGestureHandler,
|
|
@@ -26,7 +17,7 @@ import Animated, {
|
|
|
26
17
|
withTiming,
|
|
27
18
|
} from 'react-native-reanimated';
|
|
28
19
|
|
|
29
|
-
import { BottomSheetModal, BottomSheetModalProvider
|
|
20
|
+
import { BottomSheetModal, BottomSheetModalProvider } from '@gorhom/bottom-sheet';
|
|
30
21
|
|
|
31
22
|
import type { UserResponse } from 'stream-chat';
|
|
32
23
|
|
|
@@ -63,7 +54,6 @@ import { getUrlOfImageAttachment } from '../../utils/getUrlOfImageAttachment';
|
|
|
63
54
|
import { getGiphyMimeType } from '../Attachment/utils/getGiphyMimeType';
|
|
64
55
|
|
|
65
56
|
const isAndroid = Platform.OS === 'android';
|
|
66
|
-
const fullScreenHeight = Dimensions.get('screen').height;
|
|
67
57
|
|
|
68
58
|
const MARGIN = 32;
|
|
69
59
|
|
|
@@ -132,29 +122,6 @@ type Props<StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamC
|
|
|
132
122
|
| 'autoPlayVideo'
|
|
133
123
|
>;
|
|
134
124
|
|
|
135
|
-
type SnapPoints = BottomSheetProps['snapPoints'];
|
|
136
|
-
|
|
137
|
-
const normalizeSnapPoints = (input: SnapPoints): SnapPoints => {
|
|
138
|
-
const snapPoints = input ? ('value' in input ? input.value : input) : [];
|
|
139
|
-
|
|
140
|
-
return snapPoints.map((snapPoint) => {
|
|
141
|
-
if (typeof snapPoint === 'number') {
|
|
142
|
-
return Math.max(0, snapPoint);
|
|
143
|
-
} else {
|
|
144
|
-
const numericValue = Number(snapPoint.replace('%', ''));
|
|
145
|
-
const isPercentage = snapPoint.includes('%');
|
|
146
|
-
|
|
147
|
-
if (isNaN(numericValue)) {
|
|
148
|
-
return 0;
|
|
149
|
-
} else if (isPercentage) {
|
|
150
|
-
return `${Math.max(0, numericValue)}%`;
|
|
151
|
-
} else {
|
|
152
|
-
return Math.max(0, numericValue);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
|
|
158
125
|
export const ImageGallery = <
|
|
159
126
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
160
127
|
>(
|
|
@@ -179,35 +146,20 @@ export const ImageGallery = <
|
|
|
179
146
|
},
|
|
180
147
|
} = useTheme();
|
|
181
148
|
const [gridPhotos, setGridPhotos] = useState<Photo<StreamChatGenerics>[]>([]);
|
|
182
|
-
const { overlay
|
|
149
|
+
const { overlay } = useOverlayContext();
|
|
183
150
|
const { messages, selectedMessage, setSelectedMessage } =
|
|
184
151
|
useImageGalleryContext<StreamChatGenerics>();
|
|
185
152
|
|
|
186
153
|
const { vh, vw } = useViewport();
|
|
187
154
|
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
const halfScreenWidth =
|
|
155
|
+
const fullWindowHeight = vh(100);
|
|
156
|
+
const fullWindowWidth = vw(100);
|
|
157
|
+
const halfScreenWidth = fullWindowWidth / 2;
|
|
191
158
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
*/
|
|
195
|
-
const statusBarHeight = StatusBar.currentHeight ?? 0;
|
|
196
|
-
const bottomBarHeight = fullScreenHeight - measuredScreenHeight - statusBarHeight;
|
|
197
|
-
const androidScreenHeightAdjustment = translucentStatusBar
|
|
198
|
-
? bottomBarHeight === statusBarHeight || bottomBarHeight < 0
|
|
199
|
-
? 0
|
|
200
|
-
: statusBarHeight
|
|
201
|
-
: bottomBarHeight === statusBarHeight || bottomBarHeight < 0
|
|
202
|
-
? -statusBarHeight
|
|
203
|
-
: 0;
|
|
204
|
-
const screenHeight = isAndroid
|
|
205
|
-
? Dimensions.get('window').height + androidScreenHeightAdjustment
|
|
206
|
-
: vh(100);
|
|
207
|
-
const halfScreenHeight = screenHeight / 2;
|
|
208
|
-
const quarterScreenHeight = screenHeight / 4;
|
|
159
|
+
const halfScreenHeight = fullWindowHeight / 2;
|
|
160
|
+
const quarterScreenHeight = fullWindowHeight / 4;
|
|
209
161
|
const snapPoints = React.useMemo(
|
|
210
|
-
() => [(
|
|
162
|
+
() => [(fullWindowHeight * 3) / 4, fullWindowHeight - imageGalleryGridHandleHeight],
|
|
211
163
|
[],
|
|
212
164
|
);
|
|
213
165
|
|
|
@@ -226,7 +178,7 @@ export const ImageGallery = <
|
|
|
226
178
|
* Fade animation for screen, it is always rendered with pointerEvents
|
|
227
179
|
* set to none for fast opening
|
|
228
180
|
*/
|
|
229
|
-
const screenTranslateY = useSharedValue(
|
|
181
|
+
const screenTranslateY = useSharedValue(fullWindowHeight);
|
|
230
182
|
const showScreen = () => {
|
|
231
183
|
'worklet';
|
|
232
184
|
screenTranslateY.value = withTiming(0, {
|
|
@@ -246,7 +198,7 @@ export const ImageGallery = <
|
|
|
246
198
|
/**
|
|
247
199
|
* Image height from URL or default to full screen height
|
|
248
200
|
*/
|
|
249
|
-
const [currentImageHeight, setCurrentImageHeight] = useState<number>(
|
|
201
|
+
const [currentImageHeight, setCurrentImageHeight] = useState<number>(fullWindowHeight);
|
|
250
202
|
|
|
251
203
|
/**
|
|
252
204
|
* JS and UI index values, the JS follows the UI but is needed
|
|
@@ -321,9 +273,9 @@ export const ImageGallery = <
|
|
|
321
273
|
a.type === 'giphy'
|
|
322
274
|
? giphyURL
|
|
323
275
|
: getResizedImageUrl({
|
|
324
|
-
height:
|
|
276
|
+
height: fullWindowHeight,
|
|
325
277
|
url: imageUrl,
|
|
326
|
-
width:
|
|
278
|
+
width: fullWindowWidth,
|
|
327
279
|
}),
|
|
328
280
|
user: cur.user,
|
|
329
281
|
user_id: cur.user_id,
|
|
@@ -360,7 +312,7 @@ export const ImageGallery = <
|
|
|
360
312
|
|
|
361
313
|
if (newIndex > -1) {
|
|
362
314
|
index.value = newIndex;
|
|
363
|
-
translationX.value = -(
|
|
315
|
+
translationX.value = -(fullWindowWidth + MARGIN) * newIndex;
|
|
364
316
|
runOnJS(setSelectedIndex)(newIndex);
|
|
365
317
|
}
|
|
366
318
|
};
|
|
@@ -383,19 +335,19 @@ export const ImageGallery = <
|
|
|
383
335
|
const uriForCurrentImage = imageGalleryAttachments[selectedIndex]?.uri;
|
|
384
336
|
|
|
385
337
|
useEffect(() => {
|
|
386
|
-
setCurrentImageHeight(
|
|
338
|
+
setCurrentImageHeight(fullWindowHeight);
|
|
387
339
|
const photo = imageGalleryAttachments[index.value];
|
|
388
340
|
const height = photo?.original_height;
|
|
389
341
|
const width = photo?.original_width;
|
|
390
342
|
|
|
391
343
|
if (height && width) {
|
|
392
|
-
const imageHeight = Math.floor(height * (
|
|
393
|
-
setCurrentImageHeight(imageHeight >
|
|
344
|
+
const imageHeight = Math.floor(height * (fullWindowWidth / width));
|
|
345
|
+
setCurrentImageHeight(imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight);
|
|
394
346
|
} else if (photo?.uri) {
|
|
395
347
|
if (photo.type === 'image') {
|
|
396
348
|
Image.getSize(photo.uri, (width, height) => {
|
|
397
|
-
const imageHeight = Math.floor(height * (
|
|
398
|
-
setCurrentImageHeight(imageHeight >
|
|
349
|
+
const imageHeight = Math.floor(height * (fullWindowWidth / width));
|
|
350
|
+
setCurrentImageHeight(imageHeight > fullWindowHeight ? fullWindowHeight : imageHeight);
|
|
399
351
|
});
|
|
400
352
|
}
|
|
401
353
|
}
|
|
@@ -410,8 +362,8 @@ export const ImageGallery = <
|
|
|
410
362
|
overlayOpacity,
|
|
411
363
|
photoLength,
|
|
412
364
|
scale,
|
|
413
|
-
screenHeight,
|
|
414
|
-
screenWidth,
|
|
365
|
+
screenHeight: fullWindowHeight,
|
|
366
|
+
screenWidth: fullWindowWidth,
|
|
415
367
|
selectedIndex,
|
|
416
368
|
setSelectedIndex,
|
|
417
369
|
translateX,
|
|
@@ -425,9 +377,9 @@ export const ImageGallery = <
|
|
|
425
377
|
*/
|
|
426
378
|
const headerFooterOpacity = useDerivedValue(
|
|
427
379
|
() =>
|
|
428
|
-
currentImageHeight * scale.value <
|
|
380
|
+
currentImageHeight * scale.value < fullWindowHeight && translateY.value > 0
|
|
429
381
|
? 1 - translateY.value / quarterScreenHeight
|
|
430
|
-
: currentImageHeight * scale.value >
|
|
382
|
+
: currentImageHeight * scale.value > fullWindowHeight &&
|
|
431
383
|
translateY.value > (currentImageHeight / 2) * scale.value - halfScreenHeight
|
|
432
384
|
? 1 -
|
|
433
385
|
(translateY.value - ((currentImageHeight / 2) * scale.value - halfScreenHeight)) /
|
|
@@ -614,15 +566,15 @@ export const ImageGallery = <
|
|
|
614
566
|
previous={selectedIndex > i}
|
|
615
567
|
repeat={true}
|
|
616
568
|
scale={scale}
|
|
617
|
-
screenHeight={
|
|
569
|
+
screenHeight={fullWindowHeight}
|
|
618
570
|
selected={selectedIndex === i}
|
|
619
571
|
shouldRender={Math.abs(selectedIndex - i) < 4}
|
|
620
572
|
source={{ uri: photo.uri }}
|
|
621
573
|
style={[
|
|
622
574
|
{
|
|
623
|
-
height:
|
|
575
|
+
height: fullWindowHeight * 8,
|
|
624
576
|
marginRight: MARGIN,
|
|
625
|
-
width:
|
|
577
|
+
width: fullWindowWidth * 8,
|
|
626
578
|
},
|
|
627
579
|
slide,
|
|
628
580
|
]}
|
|
@@ -639,14 +591,14 @@ export const ImageGallery = <
|
|
|
639
591
|
photo={photo}
|
|
640
592
|
previous={selectedIndex > i}
|
|
641
593
|
scale={scale}
|
|
642
|
-
screenHeight={
|
|
594
|
+
screenHeight={fullWindowHeight}
|
|
643
595
|
selected={selectedIndex === i}
|
|
644
596
|
shouldRender={Math.abs(selectedIndex - i) < 4}
|
|
645
597
|
style={[
|
|
646
598
|
{
|
|
647
|
-
height:
|
|
599
|
+
height: fullWindowHeight * 8,
|
|
648
600
|
marginRight: MARGIN,
|
|
649
|
-
width:
|
|
601
|
+
width: fullWindowWidth * 8,
|
|
650
602
|
},
|
|
651
603
|
slide,
|
|
652
604
|
]}
|
|
@@ -704,11 +656,11 @@ export const ImageGallery = <
|
|
|
704
656
|
{...imageGalleryCustomComponents?.gridHandle}
|
|
705
657
|
/>
|
|
706
658
|
)}
|
|
707
|
-
handleHeight={imageGalleryGridHandleHeight
|
|
659
|
+
handleHeight={imageGalleryGridHandleHeight}
|
|
708
660
|
index={0}
|
|
709
661
|
onChange={(index: number) => setCurrentBottomSheetIndex(index)}
|
|
710
662
|
ref={bottomSheetModalRef}
|
|
711
|
-
snapPoints={
|
|
663
|
+
snapPoints={imageGalleryGridSnapPoints || snapPoints}
|
|
712
664
|
>
|
|
713
665
|
<ImageGrid
|
|
714
666
|
closeGridView={closeGridView}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Platform,
|
|
4
|
-
Pressable,
|
|
5
|
-
SafeAreaView,
|
|
6
|
-
StatusBar,
|
|
7
|
-
StyleSheet,
|
|
8
|
-
Text,
|
|
9
|
-
View,
|
|
10
|
-
ViewStyle,
|
|
11
|
-
} from 'react-native';
|
|
2
|
+
import { Pressable, SafeAreaView, StyleSheet, Text, View, ViewStyle } from 'react-native';
|
|
12
3
|
import Animated, { Extrapolate, interpolate, useAnimatedStyle } from 'react-native-reanimated';
|
|
13
4
|
|
|
14
5
|
import { useOverlayContext } from '../../../contexts/overlayContext/OverlayContext';
|
|
@@ -108,7 +99,7 @@ export const ImageGalleryHeader = <
|
|
|
108
99
|
},
|
|
109
100
|
} = useTheme();
|
|
110
101
|
const { t, tDateTimeParser } = useTranslationContext();
|
|
111
|
-
const { setOverlay
|
|
102
|
+
const { setOverlay } = useOverlayContext();
|
|
112
103
|
|
|
113
104
|
const parsedDate = photo ? tDateTimeParser(photo?.created_at) : null;
|
|
114
105
|
|
|
@@ -146,11 +137,6 @@ export const ImageGalleryHeader = <
|
|
|
146
137
|
],
|
|
147
138
|
}));
|
|
148
139
|
|
|
149
|
-
const androidTranslucentHeaderStyle = {
|
|
150
|
-
paddingTop:
|
|
151
|
-
Platform.OS === 'android' && translucentStatusBar ? StatusBar.currentHeight : undefined,
|
|
152
|
-
};
|
|
153
|
-
|
|
154
140
|
const hideOverlay = () => {
|
|
155
141
|
setOverlay('none');
|
|
156
142
|
};
|
|
@@ -160,9 +146,7 @@ export const ImageGalleryHeader = <
|
|
|
160
146
|
onLayout={(event) => setHeight(event.nativeEvent.layout.height)}
|
|
161
147
|
pointerEvents={'box-none'}
|
|
162
148
|
>
|
|
163
|
-
<ReanimatedSafeAreaView
|
|
164
|
-
style={[{ backgroundColor: white }, androidTranslucentHeaderStyle, container, headerStyle]}
|
|
165
|
-
>
|
|
149
|
+
<ReanimatedSafeAreaView style={[{ backgroundColor: white }, container, headerStyle]}>
|
|
166
150
|
<View style={[styles.innerContainer, innerContainer]}>
|
|
167
151
|
{leftElement ? (
|
|
168
152
|
leftElement({ hideOverlay, photo })
|
|
@@ -12,7 +12,10 @@ import type { UserResponse } from 'stream-chat';
|
|
|
12
12
|
import { useCountdown } from './hooks/useCountdown';
|
|
13
13
|
|
|
14
14
|
import { ChatContextValue, useChatContext } from '../../contexts';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
AttachmentPickerContextValue,
|
|
17
|
+
useAttachmentPickerContext,
|
|
18
|
+
} from '../../contexts/attachmentPickerContext/AttachmentPickerContext';
|
|
16
19
|
import {
|
|
17
20
|
ChannelContextValue,
|
|
18
21
|
useChannelContext,
|
|
@@ -38,7 +41,6 @@ import {
|
|
|
38
41
|
} from '../../contexts/translationContext/TranslationContext';
|
|
39
42
|
|
|
40
43
|
import type { Asset, DefaultStreamChatGenerics } from '../../types/types';
|
|
41
|
-
import { AttachmentSelectionBar } from '../AttachmentPicker/components/AttachmentSelectionBar';
|
|
42
44
|
import { AutoCompleteInput } from '../AutoCompleteInput/AutoCompleteInput';
|
|
43
45
|
|
|
44
46
|
const styles = StyleSheet.create({
|
|
@@ -80,7 +82,8 @@ const styles = StyleSheet.create({
|
|
|
80
82
|
|
|
81
83
|
type MessageInputPropsWithContext<
|
|
82
84
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
83
|
-
> = Pick<
|
|
85
|
+
> = Pick<AttachmentPickerContextValue, 'AttachmentPickerSelectionBar'> &
|
|
86
|
+
Pick<ChatContextValue<StreamChatGenerics>, 'isOnline'> &
|
|
84
87
|
Pick<
|
|
85
88
|
ChannelContextValue<StreamChatGenerics>,
|
|
86
89
|
'disabled' | 'members' | 'threadList' | 'watchers'
|
|
@@ -146,6 +149,7 @@ const MessageInputWithContext = <
|
|
|
146
149
|
additionalTextInputProps,
|
|
147
150
|
asyncIds,
|
|
148
151
|
asyncUploads,
|
|
152
|
+
AttachmentPickerSelectionBar,
|
|
149
153
|
AutoCompleteSuggestionList,
|
|
150
154
|
closeAttachmentPicker,
|
|
151
155
|
cooldownEndsAt,
|
|
@@ -637,14 +641,12 @@ const MessageInputWithContext = <
|
|
|
637
641
|
{
|
|
638
642
|
backgroundColor: white_smoke,
|
|
639
643
|
height:
|
|
640
|
-
|
|
641
|
-
? attachmentPickerBottomSheetHeight + (attachmentSelectionBarHeight ?? 52)
|
|
642
|
-
: 360) - bottomInset,
|
|
644
|
+
attachmentPickerBottomSheetHeight + attachmentSelectionBarHeight - bottomInset,
|
|
643
645
|
},
|
|
644
646
|
attachmentSelectionBar,
|
|
645
647
|
]}
|
|
646
648
|
>
|
|
647
|
-
<
|
|
649
|
+
<AttachmentPickerSelectionBar />
|
|
648
650
|
</View>
|
|
649
651
|
)}
|
|
650
652
|
</>
|
|
@@ -789,6 +791,7 @@ export const MessageInput = <
|
|
|
789
791
|
>(
|
|
790
792
|
props: MessageInputProps<StreamChatGenerics>,
|
|
791
793
|
) => {
|
|
794
|
+
const { AttachmentPickerSelectionBar } = useAttachmentPickerContext();
|
|
792
795
|
const { isOnline } = useChatContext();
|
|
793
796
|
const ownCapabilities = useOwnCapabilitiesContext();
|
|
794
797
|
|
|
@@ -859,6 +862,7 @@ export const MessageInput = <
|
|
|
859
862
|
additionalTextInputProps,
|
|
860
863
|
asyncIds,
|
|
861
864
|
asyncUploads,
|
|
865
|
+
AttachmentPickerSelectionBar,
|
|
862
866
|
AutoCompleteSuggestionHeader,
|
|
863
867
|
AutoCompleteSuggestionItem,
|
|
864
868
|
AutoCompleteSuggestionList,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { generateChannelResponse } from '../../../mock-builders/generator/channel';
|
|
17
17
|
import { generateUser } from '../../../mock-builders/generator/user';
|
|
18
18
|
import { getTestClientWithUser } from '../../../mock-builders/mock';
|
|
19
|
+
import { AttachmentPickerSelectionBar } from '../../AttachmentPicker/components/AttachmentPickerSelectionBar';
|
|
19
20
|
import { CameraSelectorIcon } from '../../AttachmentPicker/components/CameraSelectorIcon';
|
|
20
21
|
import { FileSelectorIcon } from '../../AttachmentPicker/components/FileSelectorIcon';
|
|
21
22
|
import { ImageSelectorIcon } from '../../AttachmentPicker/components/ImageSelectorIcon';
|
|
@@ -27,6 +28,7 @@ describe('MessageInput', () => {
|
|
|
27
28
|
jest.spyOn(Alert, 'alert');
|
|
28
29
|
jest.spyOn(AttachmentPickerUtils, 'useAttachmentPickerContext').mockImplementation(
|
|
29
30
|
jest.fn(() => ({
|
|
31
|
+
AttachmentPickerSelectionBar,
|
|
30
32
|
CameraSelectorIcon,
|
|
31
33
|
closePicker: jest.fn(),
|
|
32
34
|
FileSelectorIcon,
|
|
@@ -15,7 +15,7 @@ export const useCountdown = (end: Date) => {
|
|
|
15
15
|
* the `end` is in the future.
|
|
16
16
|
**/
|
|
17
17
|
useEffect(() => {
|
|
18
|
-
let intervalId:
|
|
18
|
+
let intervalId: ReturnType<typeof setInterval>;
|
|
19
19
|
|
|
20
20
|
const startCountdown = (seconds: number) => {
|
|
21
21
|
setSeconds(seconds);
|
|
@@ -352,17 +352,17 @@ const MessageListWithContext = <
|
|
|
352
352
|
/**
|
|
353
353
|
* The timeout id used to debounce our scrollToIndex calls on messageList updates
|
|
354
354
|
*/
|
|
355
|
-
const scrollToDebounceTimeoutRef = useRef<
|
|
355
|
+
const scrollToDebounceTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
356
356
|
|
|
357
357
|
/**
|
|
358
358
|
* The timeout id used to lazier load the initial scroll set flag
|
|
359
359
|
*/
|
|
360
|
-
const initialScrollSettingTimeoutRef = useRef<
|
|
360
|
+
const initialScrollSettingTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
361
361
|
|
|
362
362
|
/**
|
|
363
363
|
* The timeout id used to temporarily load the initial scroll set flag
|
|
364
364
|
*/
|
|
365
|
-
const onScrollEventTimeoutRef = useRef<
|
|
365
|
+
const onScrollEventTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
366
366
|
|
|
367
367
|
/**
|
|
368
368
|
* Last messageID that was scrolled to after loading a new message list,
|
|
@@ -861,7 +861,7 @@ const MessageListWithContext = <
|
|
|
861
861
|
};
|
|
862
862
|
|
|
863
863
|
const scrollToIndexFailedRetryCountRef = useRef<number>(0);
|
|
864
|
-
const failScrollTimeoutId = useRef<
|
|
864
|
+
const failScrollTimeoutId = useRef<ReturnType<typeof setTimeout>>();
|
|
865
865
|
const onScrollToIndexFailedRef = useRef<
|
|
866
866
|
FlatListProps<MessageType<StreamChatGenerics>>['onScrollToIndexFailed']
|
|
867
867
|
>((info) => {
|
package/src/components/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export * from './AttachmentPicker/AttachmentPicker';
|
|
|
14
14
|
export * from './AttachmentPicker/components/AttachmentPickerBottomSheetHandle';
|
|
15
15
|
export * from './AttachmentPicker/components/AttachmentPickerError';
|
|
16
16
|
export * from './AttachmentPicker/components/AttachmentPickerErrorImage';
|
|
17
|
-
export * from './AttachmentPicker/components/
|
|
17
|
+
export * from './AttachmentPicker/components/AttachmentPickerSelectionBar';
|
|
18
18
|
export * from './AttachmentPicker/components/CameraSelectorIcon';
|
|
19
19
|
export * from './AttachmentPicker/components/FileSelectorIcon';
|
|
20
20
|
export * from './AttachmentPicker/components/ImageOverlaySelectedComponent';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React, { PropsWithChildren, useContext, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
|
+
import { BottomSheetHandleProps } from '@gorhom/bottom-sheet';
|
|
4
|
+
|
|
3
5
|
import type { Asset, DefaultStreamChatGenerics, File } from '../../types/types';
|
|
4
6
|
import { DEFAULT_BASE_CONTEXT_VALUE } from '../utils/defaultBaseContextValue';
|
|
5
7
|
|
|
@@ -12,6 +14,36 @@ export type AttachmentPickerIconProps = {
|
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export type AttachmentPickerContextValue = {
|
|
17
|
+
/**
|
|
18
|
+
* Custom UI component to render [draggable handle](https://github.com/GetStream/stream-chat-react-native/blob/main/screenshots/docs/1.png) of attachment picker.
|
|
19
|
+
*
|
|
20
|
+
* **Default** [AttachmentPickerBottomSheetHandle](https://github.com/GetStream/stream-chat-react-native/blob/main/package/src/components/AttachmentPicker/components/AttachmentPickerBottomSheetHandle.tsx)
|
|
21
|
+
*/
|
|
22
|
+
AttachmentPickerBottomSheetHandle: React.FC<BottomSheetHandleProps>;
|
|
23
|
+
/**
|
|
24
|
+
* Height of the image picker bottom sheet handle.
|
|
25
|
+
* @type number
|
|
26
|
+
* @default 20
|
|
27
|
+
*/
|
|
28
|
+
attachmentPickerBottomSheetHandleHeight: number;
|
|
29
|
+
/**
|
|
30
|
+
* Height of the image picker bottom sheet when opened.
|
|
31
|
+
* @type number
|
|
32
|
+
* @default 40% of window height
|
|
33
|
+
*/
|
|
34
|
+
attachmentPickerBottomSheetHeight: number;
|
|
35
|
+
/**
|
|
36
|
+
* Custom UI component for AttachmentPickerSelectionBar
|
|
37
|
+
*
|
|
38
|
+
* **Default: ** [AttachmentPickerSelectionBar](https://github.com/GetStream/stream-chat-react-native/blob/develop/package/src/components/AttachmentPicker/components/AttachmentPickerSelectionBar.tsx)
|
|
39
|
+
*/
|
|
40
|
+
AttachmentPickerSelectionBar: React.ComponentType;
|
|
41
|
+
/**
|
|
42
|
+
* Height of the attachment selection bar displayed on the attachment picker.
|
|
43
|
+
* @type number
|
|
44
|
+
* @default 52
|
|
45
|
+
*/
|
|
46
|
+
attachmentSelectionBarHeight: number;
|
|
15
47
|
/**
|
|
16
48
|
* `bottomInset` determine the height of the `AttachmentPicker` and the underlying shift to the `MessageList` when it is opened.
|
|
17
49
|
* This can also be set via the `setBottomInset` function provided by the `useAttachmentPickerContext` hook.
|
|
@@ -53,8 +85,6 @@ export type AttachmentPickerContextValue = {
|
|
|
53
85
|
setSelectedPicker: React.Dispatch<React.SetStateAction<'images' | undefined>>;
|
|
54
86
|
setTopInset: React.Dispatch<React.SetStateAction<number>>;
|
|
55
87
|
topInset: number;
|
|
56
|
-
attachmentPickerBottomSheetHeight?: number;
|
|
57
|
-
attachmentSelectionBarHeight?: number;
|
|
58
88
|
selectedPicker?: 'images';
|
|
59
89
|
};
|
|
60
90
|
|
|
@@ -68,13 +98,7 @@ export const AttachmentPickerProvider = ({
|
|
|
68
98
|
}: PropsWithChildren<{
|
|
69
99
|
value?: Pick<
|
|
70
100
|
AttachmentPickerContextValue,
|
|
71
|
-
| '
|
|
72
|
-
| 'attachmentPickerBottomSheetHeight'
|
|
73
|
-
| 'CameraSelectorIcon'
|
|
74
|
-
| 'closePicker'
|
|
75
|
-
| 'FileSelectorIcon'
|
|
76
|
-
| 'ImageSelectorIcon'
|
|
77
|
-
| 'openPicker'
|
|
101
|
+
'CameraSelectorIcon' | 'closePicker' | 'FileSelectorIcon' | 'ImageSelectorIcon' | 'openPicker'
|
|
78
102
|
> &
|
|
79
103
|
Partial<Pick<AttachmentPickerContextValue, 'bottomInset' | 'topInset'>>;
|
|
80
104
|
}>) => {
|
|
@@ -86,7 +110,7 @@ export const AttachmentPickerProvider = ({
|
|
|
86
110
|
const [selectedImages, setSelectedImages] = useState<Asset[]>([]);
|
|
87
111
|
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
|
88
112
|
const [selectedPicker, setSelectedPicker] = useState<'images'>();
|
|
89
|
-
const [topInset, setTopInset] = useState<number>(
|
|
113
|
+
const [topInset, setTopInset] = useState<number>(topInsetValue ?? 0);
|
|
90
114
|
|
|
91
115
|
useEffect(() => {
|
|
92
116
|
setBottomInset(bottomInsetValue ?? 0);
|
|
@@ -24,7 +24,6 @@ export type OverlayContextValue = {
|
|
|
24
24
|
overlay: Overlay;
|
|
25
25
|
setOverlay: React.Dispatch<React.SetStateAction<Overlay>>;
|
|
26
26
|
style?: DeepPartial<Theme>;
|
|
27
|
-
translucentStatusBar?: boolean;
|
|
28
27
|
};
|
|
29
28
|
|
|
30
29
|
export const OverlayContext = React.createContext(
|
|
@@ -37,7 +36,10 @@ export type OverlayProviderProps<
|
|
|
37
36
|
Partial<
|
|
38
37
|
Pick<
|
|
39
38
|
AttachmentPickerContextValue,
|
|
39
|
+
| 'AttachmentPickerBottomSheetHandle'
|
|
40
|
+
| 'attachmentPickerBottomSheetHandleHeight'
|
|
40
41
|
| 'attachmentPickerBottomSheetHeight'
|
|
42
|
+
| 'AttachmentPickerSelectionBar'
|
|
41
43
|
| 'attachmentSelectionBarHeight'
|
|
42
44
|
| 'bottomInset'
|
|
43
45
|
| 'CameraSelectorIcon'
|
|
@@ -56,8 +58,8 @@ export type OverlayProviderProps<
|
|
|
56
58
|
| 'OverlayReactions'
|
|
57
59
|
| 'OverlayReactionsAvatar'
|
|
58
60
|
>
|
|
59
|
-
> &
|
|
60
|
-
|
|
61
|
+
> & {
|
|
62
|
+
imageGalleryGridHandleHeight: number;
|
|
61
63
|
autoPlayVideo?: boolean;
|
|
62
64
|
/**
|
|
63
65
|
* The giphy version to render - check the keys of the [Image Object](https://developers.giphy.com/docs/api/schema#image-object) for possible values. Uses 'fixed_height' by default
|
|
@@ -67,7 +69,6 @@ export type OverlayProviderProps<
|
|
|
67
69
|
giphyVersion?: keyof NonNullable<Attachment['giphy']>;
|
|
68
70
|
/** https://github.com/GetStream/stream-chat-react-native/wiki/Internationalization-(i18n) */
|
|
69
71
|
i18nInstance?: Streami18n;
|
|
70
|
-
imageGalleryGridHandleHeight?: number;
|
|
71
72
|
imageGalleryGridSnapPoints?: [string | number, string | number];
|
|
72
73
|
isMyMessage?: boolean;
|
|
73
74
|
isThreadMessage?: boolean;
|
|
@@ -19,6 +19,7 @@ import { AttachmentPickerBottomSheetHandle as DefaultAttachmentPickerBottomSheet
|
|
|
19
19
|
import { AttachmentPickerError as DefaultAttachmentPickerError } from '../../components/AttachmentPicker/components/AttachmentPickerError';
|
|
20
20
|
import { AttachmentPickerErrorImage as DefaultAttachmentPickerErrorImage } from '../../components/AttachmentPicker/components/AttachmentPickerErrorImage';
|
|
21
21
|
import { AttachmentPickerIOSSelectMorePhotos as DefaultAttachmentPickerIOSSelectMorePhotos } from '../../components/AttachmentPicker/components/AttachmentPickerIOSSelectMorePhotos';
|
|
22
|
+
import { AttachmentPickerSelectionBar as DefaultAttachmentPickerSelectionBar } from '../../components/AttachmentPicker/components/AttachmentPickerSelectionBar';
|
|
22
23
|
import { CameraSelectorIcon as DefaultCameraSelectorIcon } from '../../components/AttachmentPicker/components/CameraSelectorIcon';
|
|
23
24
|
import { FileSelectorIcon as DefaultFileSelectorIcon } from '../../components/AttachmentPicker/components/FileSelectorIcon';
|
|
24
25
|
import { ImageOverlaySelectedComponent as DefaultImageOverlaySelectedComponent } from '../../components/AttachmentPicker/components/ImageOverlaySelectedComponent';
|
|
@@ -28,6 +29,7 @@ import { MessageOverlay } from '../../components/MessageOverlay/MessageOverlay';
|
|
|
28
29
|
import { OverlayBackdrop } from '../../components/MessageOverlay/OverlayBackdrop';
|
|
29
30
|
import { useStreami18n } from '../../hooks/useStreami18n';
|
|
30
31
|
|
|
32
|
+
import { useViewport } from '../../hooks/useViewport';
|
|
31
33
|
import type { DefaultStreamChatGenerics } from '../../types/types';
|
|
32
34
|
import { AttachmentPickerProvider } from '../attachmentPickerContext/AttachmentPickerContext';
|
|
33
35
|
import { ImageGalleryProvider } from '../imageGalleryContext/ImageGalleryContext';
|
|
@@ -63,17 +65,19 @@ export const OverlayProvider = <
|
|
|
63
65
|
>(
|
|
64
66
|
props: PropsWithChildren<OverlayProviderProps<StreamChatGenerics>>,
|
|
65
67
|
) => {
|
|
66
|
-
const
|
|
68
|
+
const { vh } = useViewport();
|
|
69
|
+
const bottomSheetCloseTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
|
67
70
|
const {
|
|
68
71
|
AttachmentPickerBottomSheetHandle = DefaultAttachmentPickerBottomSheetHandle,
|
|
69
|
-
attachmentPickerBottomSheetHandleHeight,
|
|
70
|
-
attachmentPickerBottomSheetHeight,
|
|
72
|
+
attachmentPickerBottomSheetHandleHeight = 20,
|
|
73
|
+
attachmentPickerBottomSheetHeight = vh(45),
|
|
71
74
|
AttachmentPickerError = DefaultAttachmentPickerError,
|
|
72
75
|
attachmentPickerErrorButtonText,
|
|
73
76
|
AttachmentPickerErrorImage = DefaultAttachmentPickerErrorImage,
|
|
74
77
|
attachmentPickerErrorText,
|
|
75
78
|
AttachmentPickerIOSSelectMorePhotos = DefaultAttachmentPickerIOSSelectMorePhotos,
|
|
76
|
-
|
|
79
|
+
AttachmentPickerSelectionBar = DefaultAttachmentPickerSelectionBar,
|
|
80
|
+
attachmentSelectionBarHeight = 52,
|
|
77
81
|
autoPlayVideo,
|
|
78
82
|
bottomInset,
|
|
79
83
|
CameraSelectorIcon = DefaultCameraSelectorIcon,
|
|
@@ -98,7 +102,7 @@ export const OverlayProvider = <
|
|
|
98
102
|
giphyVersion,
|
|
99
103
|
i18nInstance,
|
|
100
104
|
imageGalleryCustomComponents,
|
|
101
|
-
imageGalleryGridHandleHeight,
|
|
105
|
+
imageGalleryGridHandleHeight = 40,
|
|
102
106
|
imageGalleryGridSnapPoints,
|
|
103
107
|
ImageOverlaySelectedComponent = DefaultImageOverlaySelectedComponent,
|
|
104
108
|
ImageSelectorIcon = DefaultImageSelectorIcon,
|
|
@@ -122,7 +126,6 @@ export const OverlayProvider = <
|
|
|
122
126
|
OverlayReactions,
|
|
123
127
|
OverlayReactionsAvatar,
|
|
124
128
|
topInset,
|
|
125
|
-
translucentStatusBar,
|
|
126
129
|
value,
|
|
127
130
|
} = props;
|
|
128
131
|
|
|
@@ -139,7 +142,6 @@ export const OverlayProvider = <
|
|
|
139
142
|
ImageOverlaySelectedComponent,
|
|
140
143
|
numberOfAttachmentImagesToLoadPerCall,
|
|
141
144
|
numberOfAttachmentPickerImageColumns,
|
|
142
|
-
translucentStatusBar,
|
|
143
145
|
};
|
|
144
146
|
|
|
145
147
|
const bottomSheetRef = useRef<BottomSheet>(null);
|
|
@@ -189,7 +191,9 @@ export const OverlayProvider = <
|
|
|
189
191
|
}, [overlay]);
|
|
190
192
|
|
|
191
193
|
const attachmentPickerContext = {
|
|
194
|
+
AttachmentPickerBottomSheetHandle,
|
|
192
195
|
attachmentPickerBottomSheetHeight,
|
|
196
|
+
AttachmentPickerSelectionBar,
|
|
193
197
|
attachmentSelectionBarHeight,
|
|
194
198
|
bottomInset,
|
|
195
199
|
CameraSelectorIcon,
|
|
@@ -211,7 +215,6 @@ export const OverlayProvider = <
|
|
|
211
215
|
overlay,
|
|
212
216
|
setOverlay,
|
|
213
217
|
style: value?.style,
|
|
214
|
-
translucentStatusBar,
|
|
215
218
|
};
|
|
216
219
|
|
|
217
220
|
return (
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { Dimensions } from 'react-native';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A custom hook that provides functions to calculate dimensions based on
|
|
6
|
+
* a percentage of the screen height (vh) and viewport width (vw). It
|
|
7
|
+
* dynamically updates dimensions on changes in device orientation.
|
|
8
|
+
*
|
|
9
|
+
* @returns {Object} An object containing functions vh and vw.
|
|
10
|
+
*/
|
|
11
|
+
export const useScreenDimensions = (rounded?: boolean) => {
|
|
12
|
+
const [screenDimensions, setScreenDimensions] = useState(Dimensions.get('screen'));
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const subscriptions = Dimensions.addEventListener('change', ({ screen }) => {
|
|
16
|
+
setScreenDimensions((prev) => {
|
|
17
|
+
const { height, width } = screen;
|
|
18
|
+
if (prev.height !== height || prev.width !== width) {
|
|
19
|
+
return screen;
|
|
20
|
+
}
|
|
21
|
+
return prev;
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return () => subscriptions?.remove();
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
const vw = (percentageWidth: number) => {
|
|
29
|
+
const value = screenDimensions.width * (percentageWidth / 100);
|
|
30
|
+
return rounded ? Math.round(value) : value;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const vh = (percentageHeight: number) => {
|
|
34
|
+
const value = screenDimensions.height * (percentageHeight / 100);
|
|
35
|
+
return rounded ? Math.round(value) : value;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const screenDimensionFunctions = useMemo(() => ({ vh, vw }), [vh, vw]);
|
|
39
|
+
|
|
40
|
+
return screenDimensionFunctions;
|
|
41
|
+
};
|