stream-chat-react-native-core 4.6.1 → 4.7.0-beta.1
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/Attachment/Attachment.js +22 -13
- package/lib/commonjs/components/Attachment/Attachment.js.map +1 -1
- package/lib/commonjs/components/Attachment/Gallery.js +72 -37
- package/lib/commonjs/components/Attachment/Gallery.js.map +1 -1
- package/lib/commonjs/components/Attachment/VideoThumbnail.js +83 -0
- package/lib/commonjs/components/Attachment/VideoThumbnail.js.map +1 -0
- package/lib/commonjs/components/Attachment/hooks/useGoToURL.js +1 -1
- package/lib/commonjs/components/Attachment/hooks/useGoToURL.js.map +1 -1
- package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
- package/lib/commonjs/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
- package/lib/commonjs/components/Attachment/utils/getAspectRatio.js +5 -5
- package/lib/commonjs/components/Attachment/utils/getAspectRatio.js.map +1 -1
- package/lib/commonjs/components/Channel/Channel.js +19 -14
- package/lib/commonjs/components/Channel/Channel.js.map +1 -1
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js +4 -2
- package/lib/commonjs/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +43 -28
- package/lib/commonjs/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/ImageGallery.js +167 -345
- package/lib/commonjs/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js +4 -4
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js +225 -0
- package/lib/commonjs/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js +102 -40
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js +145 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/components/ImageGrid.js +31 -34
- package/lib/commonjs/components/ImageGallery/components/ImageGrid.js.map +1 -1
- package/lib/commonjs/components/ImageGallery/components/ProgressControl.js +153 -0
- package/lib/commonjs/components/ImageGallery/components/ProgressControl.js.map +1 -0
- package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js +373 -0
- package/lib/commonjs/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -0
- package/lib/commonjs/components/Message/Message.js +23 -13
- package/lib/commonjs/components/Message/Message.js.map +1 -1
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +4 -2
- package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/commonjs/components/MessageOverlay/MessageOverlay.js +25 -23
- package/lib/commonjs/components/MessageOverlay/MessageOverlay.js.map +1 -1
- package/lib/commonjs/components/Reply/Reply.js +32 -12
- package/lib/commonjs/components/Reply/Reply.js.map +1 -1
- package/lib/commonjs/components/Spinner/Spinner.js +12 -4
- package/lib/commonjs/components/Spinner/Spinner.js.map +1 -1
- package/lib/commonjs/components/index.js +26 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/contexts/messageContext/MessageContext.js +2 -2
- package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/commonjs/contexts/messageOverlayContext/MessageOverlayContext.js +2 -2
- package/lib/commonjs/contexts/messageOverlayContext/MessageOverlayContext.js.map +1 -1
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/commonjs/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js +10 -1
- package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/commonjs/icons/Pause.js +61 -0
- package/lib/commonjs/icons/Pause.js.map +1 -0
- package/lib/commonjs/icons/Play.js +42 -0
- package/lib/commonjs/icons/Play.js.map +1 -0
- package/lib/commonjs/icons/index.js +26 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/mock-builders/api/queryMembers.js +98 -1
- package/lib/commonjs/mock-builders/api/queryMembers.js.map +1 -1
- package/lib/commonjs/native.js +7 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/utils/getUrlOfImageAttachment.js +1 -1
- package/lib/commonjs/utils/getUrlOfImageAttachment.js.map +1 -1
- package/lib/commonjs/version.json +1 -1
- package/lib/module/components/Attachment/Attachment.js +22 -13
- package/lib/module/components/Attachment/Attachment.js.map +1 -1
- package/lib/module/components/Attachment/Gallery.js +72 -37
- package/lib/module/components/Attachment/Gallery.js.map +1 -1
- package/lib/module/components/Attachment/VideoThumbnail.js +83 -0
- package/lib/module/components/Attachment/VideoThumbnail.js.map +1 -0
- package/lib/module/components/Attachment/hooks/useGoToURL.js +1 -1
- package/lib/module/components/Attachment/hooks/useGoToURL.js.map +1 -1
- package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js +1 -0
- package/lib/module/components/Attachment/utils/buildGallery/buildThumbnail.js.map +1 -1
- package/lib/module/components/Attachment/utils/getAspectRatio.js +5 -5
- package/lib/module/components/Attachment/utils/getAspectRatio.js.map +1 -1
- package/lib/module/components/Channel/Channel.js +19 -14
- package/lib/module/components/Channel/Channel.js.map +1 -1
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js +4 -2
- package/lib/module/components/Channel/hooks/useCreateMessagesContext.js.map +1 -1
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js +43 -28
- package/lib/module/components/ChannelPreview/hooks/useChannelPreviewDisplayName.js.map +1 -1
- package/lib/module/components/ImageGallery/ImageGallery.js +167 -345
- package/lib/module/components/ImageGallery/ImageGallery.js.map +1 -1
- package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js +4 -4
- package/lib/module/components/ImageGallery/components/AnimatedGalleryImage.js.map +1 -1
- package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js +225 -0
- package/lib/module/components/ImageGallery/components/AnimatedGalleryVideo.js.map +1 -0
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js +102 -40
- package/lib/module/components/ImageGallery/components/ImageGalleryFooter.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js +145 -0
- package/lib/module/components/ImageGallery/components/ImageGalleryVideoControl.js.map +1 -0
- package/lib/module/components/ImageGallery/components/ImageGrid.js +31 -34
- package/lib/module/components/ImageGallery/components/ImageGrid.js.map +1 -1
- package/lib/module/components/ImageGallery/components/ProgressControl.js +153 -0
- package/lib/module/components/ImageGallery/components/ProgressControl.js.map +1 -0
- package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js +373 -0
- package/lib/module/components/ImageGallery/hooks/useImageGalleryGestures.js.map +1 -0
- package/lib/module/components/Message/Message.js +23 -13
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/Message/hooks/useCreateMessageContext.js +4 -2
- package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
- package/lib/module/components/MessageOverlay/MessageOverlay.js +25 -23
- package/lib/module/components/MessageOverlay/MessageOverlay.js.map +1 -1
- package/lib/module/components/Reply/Reply.js +32 -12
- package/lib/module/components/Reply/Reply.js.map +1 -1
- package/lib/module/components/Spinner/Spinner.js +12 -4
- package/lib/module/components/Spinner/Spinner.js.map +1 -1
- package/lib/module/components/index.js +26 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/contexts/messageContext/MessageContext.js +2 -2
- package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
- package/lib/module/contexts/messageOverlayContext/MessageOverlayContext.js +2 -2
- package/lib/module/contexts/messageOverlayContext/MessageOverlayContext.js.map +1 -1
- package/lib/module/contexts/messagesContext/MessagesContext.js +2 -2
- package/lib/module/contexts/messagesContext/MessagesContext.js.map +1 -1
- package/lib/module/contexts/themeContext/utils/theme.js +10 -1
- package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
- package/lib/module/icons/Pause.js +61 -0
- package/lib/module/icons/Pause.js.map +1 -0
- package/lib/module/icons/Play.js +42 -0
- package/lib/module/icons/Play.js.map +1 -0
- package/lib/module/icons/index.js +26 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/mock-builders/api/queryMembers.js +98 -1
- package/lib/module/mock-builders/api/queryMembers.js.map +1 -1
- package/lib/module/native.js +7 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/utils/getUrlOfImageAttachment.js +1 -1
- package/lib/module/utils/getUrlOfImageAttachment.js.map +1 -1
- package/lib/module/version.json +1 -1
- package/lib/typescript/components/Attachment/Gallery.d.ts +1 -1
- package/lib/typescript/components/Attachment/VideoThumbnail.d.ts +4 -0
- package/lib/typescript/components/Attachment/utils/buildGallery/types.d.ts +1 -0
- package/lib/typescript/components/Attachment/utils/getAspectRatio.d.ts +1 -1
- package/lib/typescript/components/Channel/Channel.d.ts +1 -1
- package/lib/typescript/components/Channel/hooks/useCreateMessagesContext.d.ts +1 -1
- package/lib/typescript/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.d.ts +1 -0
- package/lib/typescript/components/ChannelPreview/hooks/useChannelPreviewDisplayName.d.ts +4 -4
- package/lib/typescript/components/ImageGallery/ImageGallery.d.ts +2 -0
- package/lib/typescript/components/ImageGallery/components/AnimatedGalleryVideo.d.ts +27 -0
- package/lib/typescript/components/ImageGallery/components/ImageGalleryFooter.d.ts +18 -2
- package/lib/typescript/components/ImageGallery/components/ImageGalleryVideoControl.d.ts +3 -0
- package/lib/typescript/components/ImageGallery/components/ProgressControl.d.ts +5 -0
- package/lib/typescript/components/ImageGallery/hooks/useImageGalleryGestures.d.ts +36 -0
- package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts +1 -1
- package/lib/typescript/components/Spinner/Spinner.d.ts +7 -1
- package/lib/typescript/components/index.d.ts +2 -0
- package/lib/typescript/contexts/messageContext/MessageContext.d.ts +3 -1
- package/lib/typescript/contexts/messageOverlayContext/MessageOverlayContext.d.ts +1 -0
- package/lib/typescript/contexts/messagesContext/MessagesContext.d.ts +2 -0
- package/lib/typescript/contexts/themeContext/utils/theme.d.ts +9 -0
- package/lib/typescript/icons/Pause.d.ts +3 -0
- package/lib/typescript/icons/Play.d.ts +3 -0
- package/lib/typescript/icons/index.d.ts +2 -0
- package/lib/typescript/mock-builders/api/queryMembers.d.ts +161 -0
- package/lib/typescript/mock-builders/api/utils.d.ts +7 -0
- package/lib/typescript/mock-builders/generator/user.d.ts +30 -0
- package/lib/typescript/mock-builders/mock.d.ts +3 -0
- package/lib/typescript/native.d.ts +66 -1
- package/package.json +1 -1
- package/src/components/Attachment/Attachment.tsx +11 -7
- package/src/components/Attachment/Gallery.tsx +75 -36
- package/src/components/Attachment/VideoThumbnail.tsx +45 -0
- package/src/components/Attachment/hooks/useGoToURL.ts +1 -1
- package/src/components/Attachment/utils/buildGallery/buildThumbnail.ts +1 -0
- package/src/components/Attachment/utils/buildGallery/types.ts +1 -0
- package/src/components/Attachment/utils/getAspectRatio.ts +7 -5
- package/src/components/Channel/Channel.tsx +4 -0
- package/src/components/Channel/hooks/useCreateMessagesContext.ts +2 -0
- package/src/components/ChannelPreview/hooks/__tests__/useChannelPreviewDisplayName.test.tsx +83 -0
- package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayName.ts +43 -26
- package/src/components/ImageGallery/ImageGallery.tsx +145 -667
- package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx +4 -4
- package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx +224 -0
- package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +114 -19
- package/src/components/ImageGallery/components/ImageGalleryVideoControl.tsx +103 -0
- package/src/components/ImageGallery/components/ImageGrid.tsx +12 -25
- package/src/components/ImageGallery/components/ProgressControl.tsx +107 -0
- package/src/components/ImageGallery/hooks/useImageGalleryGestures.tsx +722 -0
- package/src/components/Message/Message.tsx +10 -3
- package/src/components/Message/hooks/useCreateMessageContext.ts +2 -0
- package/src/components/MessageOverlay/MessageOverlay.tsx +2 -0
- package/src/components/Reply/Reply.tsx +36 -23
- package/src/components/Spinner/Spinner.tsx +11 -4
- package/src/components/index.ts +2 -0
- package/src/contexts/messageContext/MessageContext.tsx +2 -0
- package/src/contexts/messageOverlayContext/MessageOverlayContext.tsx +1 -0
- package/src/contexts/messagesContext/MessagesContext.tsx +2 -0
- package/src/contexts/themeContext/utils/theme.ts +18 -0
- package/src/icons/Pause.tsx +14 -0
- package/src/icons/Play.tsx +17 -0
- package/src/icons/index.ts +2 -0
- package/src/mock-builders/api/queryMembers.js +98 -0
- package/src/native.ts +59 -1
- package/src/utils/getUrlOfImageAttachment.ts +1 -1
- package/src/version.json +1 -1
|
@@ -7,7 +7,7 @@ import { vw } from '../../../utils/utils';
|
|
|
7
7
|
|
|
8
8
|
const screenWidth = vw(100);
|
|
9
9
|
const halfScreenWidth = vw(50);
|
|
10
|
-
const
|
|
10
|
+
const oneEighth = 1 / 8;
|
|
11
11
|
|
|
12
12
|
type Props = {
|
|
13
13
|
index: number;
|
|
@@ -65,7 +65,7 @@ export const AnimatedGalleryImage: React.FC<Props> = React.memo(
|
|
|
65
65
|
translateY: selected ? translateY.value + yScaleOffset : yScaleOffset,
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
|
-
scale: selected ? scale.value / 8 :
|
|
68
|
+
scale: selected ? scale.value / 8 : oneEighth,
|
|
69
69
|
},
|
|
70
70
|
{ scaleX: -1 },
|
|
71
71
|
],
|
|
@@ -78,7 +78,7 @@ export const AnimatedGalleryImage: React.FC<Props> = React.memo(
|
|
|
78
78
|
* load on memory.
|
|
79
79
|
*/
|
|
80
80
|
if (!shouldRender) {
|
|
81
|
-
return <View style={[style, { transform: [{ scale:
|
|
81
|
+
return <View style={[style, { transform: [{ scale: oneEighth }] }]} />;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
return (
|
|
@@ -95,7 +95,7 @@ export const AnimatedGalleryImage: React.FC<Props> = React.memo(
|
|
|
95
95
|
{
|
|
96
96
|
translateX: -translateX.value + 7 * screenWidth * (0.5 + index),
|
|
97
97
|
},
|
|
98
|
-
{ scale:
|
|
98
|
+
{ scale: oneEighth },
|
|
99
99
|
],
|
|
100
100
|
},
|
|
101
101
|
]}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { StyleSheet, View, ViewStyle } from 'react-native';
|
|
3
|
+
import type { StyleProp } from 'react-native';
|
|
4
|
+
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
PlaybackStatus,
|
|
8
|
+
Video,
|
|
9
|
+
VideoPayloadData,
|
|
10
|
+
VideoProgressData,
|
|
11
|
+
VideoType,
|
|
12
|
+
} from '../../../native';
|
|
13
|
+
|
|
14
|
+
import { vw } from '../../../utils/utils';
|
|
15
|
+
import { Spinner } from '../../Spinner/Spinner';
|
|
16
|
+
|
|
17
|
+
const screenWidth = vw(100);
|
|
18
|
+
const halfScreenWidth = vw(50);
|
|
19
|
+
const oneEighth = 1 / 8;
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
handleEnd: () => void;
|
|
23
|
+
handleLoad: (payload: VideoPayloadData) => void;
|
|
24
|
+
handleProgress: (data: VideoProgressData) => void;
|
|
25
|
+
index: number;
|
|
26
|
+
offsetScale: Animated.SharedValue<number>;
|
|
27
|
+
paused: boolean;
|
|
28
|
+
previous: boolean;
|
|
29
|
+
scale: Animated.SharedValue<number>;
|
|
30
|
+
screenHeight: number;
|
|
31
|
+
selected: boolean;
|
|
32
|
+
shouldRender: boolean;
|
|
33
|
+
source: { uri: string };
|
|
34
|
+
translateX: Animated.SharedValue<number>;
|
|
35
|
+
translateY: Animated.SharedValue<number>;
|
|
36
|
+
videoRef: React.RefObject<VideoType>;
|
|
37
|
+
style?: StyleProp<ViewStyle>;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const styles = StyleSheet.create({
|
|
41
|
+
activityIndicator: {
|
|
42
|
+
alignSelf: 'center',
|
|
43
|
+
},
|
|
44
|
+
videoPlayer: {
|
|
45
|
+
height: '100%',
|
|
46
|
+
width: '100%',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export const AnimatedGalleryVideo: React.FC<Props> = React.memo(
|
|
51
|
+
(props) => {
|
|
52
|
+
const [opacity, setOpacity] = useState<number>(1);
|
|
53
|
+
const {
|
|
54
|
+
handleEnd,
|
|
55
|
+
handleLoad,
|
|
56
|
+
handleProgress,
|
|
57
|
+
index,
|
|
58
|
+
offsetScale,
|
|
59
|
+
paused,
|
|
60
|
+
previous,
|
|
61
|
+
scale,
|
|
62
|
+
screenHeight,
|
|
63
|
+
selected,
|
|
64
|
+
shouldRender,
|
|
65
|
+
source,
|
|
66
|
+
style,
|
|
67
|
+
translateX,
|
|
68
|
+
translateY,
|
|
69
|
+
videoRef,
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
const onLoadStart = () => {
|
|
73
|
+
setOpacity(1);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const onLoad = (payload: VideoPayloadData) => {
|
|
77
|
+
setOpacity(0);
|
|
78
|
+
handleLoad(payload);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const onEnd = () => {
|
|
82
|
+
handleEnd();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const onProgress = (data: VideoProgressData) => {
|
|
86
|
+
handleProgress(data);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const onBuffer = ({ isBuffering }: { isBuffering: boolean }) => {
|
|
90
|
+
if (isBuffering) setOpacity(1);
|
|
91
|
+
else setOpacity(0);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const onPlayBackStatusUpdate = (playbackStatus: PlaybackStatus) => {
|
|
95
|
+
if (!playbackStatus.isLoaded) {
|
|
96
|
+
// Update your UI for the unloaded state
|
|
97
|
+
setOpacity(1);
|
|
98
|
+
if (playbackStatus.error) {
|
|
99
|
+
console.error(`Encountered a fatal error during playback: ${playbackStatus.error}`);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
// Update your UI for the loaded state
|
|
103
|
+
setOpacity(0);
|
|
104
|
+
handleLoad({ duration: playbackStatus.durationMillis / 1000 });
|
|
105
|
+
if (playbackStatus.isPlaying) {
|
|
106
|
+
// Update your UI for the playing state
|
|
107
|
+
handleProgress({
|
|
108
|
+
currentTime: playbackStatus.positionMillis / 1000,
|
|
109
|
+
seekableDuration: playbackStatus.durationMillis / 1000,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (playbackStatus.isBuffering) {
|
|
114
|
+
// Update your UI for the buffering state
|
|
115
|
+
setOpacity(1);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (playbackStatus.didJustFinish && !playbackStatus.isLooping) {
|
|
119
|
+
// The player has just finished playing and will stop. Maybe you want to play something else?
|
|
120
|
+
handleEnd();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const animatedViewStyles = useAnimatedStyle<ViewStyle>(() => {
|
|
126
|
+
const xScaleOffset = -7 * screenWidth * (0.5 + index);
|
|
127
|
+
const yScaleOffset = -screenHeight * 3.5;
|
|
128
|
+
return {
|
|
129
|
+
transform: [
|
|
130
|
+
{
|
|
131
|
+
translateX: selected
|
|
132
|
+
? translateX.value + xScaleOffset
|
|
133
|
+
: scale.value < 1 || scale.value !== offsetScale.value
|
|
134
|
+
? xScaleOffset
|
|
135
|
+
: previous
|
|
136
|
+
? translateX.value - halfScreenWidth * (scale.value - 1) + xScaleOffset
|
|
137
|
+
: translateX.value + halfScreenWidth * (scale.value - 1) + xScaleOffset,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
translateY: selected ? translateY.value + yScaleOffset : yScaleOffset,
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
scale: selected ? scale.value / 8 : oneEighth,
|
|
144
|
+
},
|
|
145
|
+
{ scaleX: -1 },
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
}, [previous, selected]);
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* An empty view is rendered for images not close to the currently
|
|
152
|
+
* selected in order to maintain spacing while reducing the image
|
|
153
|
+
* load on memory.
|
|
154
|
+
*/
|
|
155
|
+
if (!shouldRender) {
|
|
156
|
+
return <View style={[style, { transform: [{ scale: oneEighth }] }]} />;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<Animated.View
|
|
161
|
+
style={[
|
|
162
|
+
style,
|
|
163
|
+
animatedViewStyles,
|
|
164
|
+
{
|
|
165
|
+
transform: [
|
|
166
|
+
{ scaleX: -1 },
|
|
167
|
+
{ translateY: -screenHeight * 3.5 },
|
|
168
|
+
{
|
|
169
|
+
translateX: -translateX.value + 7 * screenWidth * (0.5 + index),
|
|
170
|
+
},
|
|
171
|
+
{ scale: oneEighth },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
]}
|
|
175
|
+
>
|
|
176
|
+
<Video
|
|
177
|
+
onBuffer={onBuffer}
|
|
178
|
+
onEnd={onEnd}
|
|
179
|
+
onLoad={onLoad}
|
|
180
|
+
onLoadStart={onLoadStart}
|
|
181
|
+
onPlaybackStatusUpdate={onPlayBackStatusUpdate}
|
|
182
|
+
onProgress={onProgress}
|
|
183
|
+
paused={paused}
|
|
184
|
+
resizeMode='cover'
|
|
185
|
+
style={style}
|
|
186
|
+
uri={source.uri}
|
|
187
|
+
videoRef={videoRef}
|
|
188
|
+
/>
|
|
189
|
+
<Animated.View
|
|
190
|
+
style={[
|
|
191
|
+
styles.activityIndicator,
|
|
192
|
+
{
|
|
193
|
+
opacity,
|
|
194
|
+
transform: [
|
|
195
|
+
{ scaleX: -1 },
|
|
196
|
+
{ translateY: -screenHeight * 4 },
|
|
197
|
+
{ scale: 1 / oneEighth },
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
]}
|
|
201
|
+
>
|
|
202
|
+
<Spinner height={40} width={40} />
|
|
203
|
+
</Animated.View>
|
|
204
|
+
</Animated.View>
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
(prevProps, nextProps) => {
|
|
209
|
+
if (
|
|
210
|
+
prevProps.paused === nextProps.paused &&
|
|
211
|
+
prevProps.shouldRender === nextProps.shouldRender &&
|
|
212
|
+
prevProps.source.uri === nextProps.source.uri &&
|
|
213
|
+
prevProps.screenHeight === nextProps.screenHeight &&
|
|
214
|
+
prevProps.selected === nextProps.selected &&
|
|
215
|
+
prevProps.previous === nextProps.previous &&
|
|
216
|
+
prevProps.index === nextProps.index
|
|
217
|
+
) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
},
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
AnimatedGalleryVideo.displayName = 'AnimatedGalleryVideo';
|
|
@@ -2,6 +2,8 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { SafeAreaView, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native';
|
|
3
3
|
import Animated, { Extrapolate, interpolate, useAnimatedStyle } from 'react-native-reanimated';
|
|
4
4
|
|
|
5
|
+
import { ImageGalleryVideoControl } from './ImageGalleryVideoControl';
|
|
6
|
+
|
|
5
7
|
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
|
|
6
8
|
import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext';
|
|
7
9
|
import { Grid as GridIconDefault, Share as ShareIconDefault } from '../../../icons';
|
|
@@ -60,6 +62,22 @@ export type ImageGalleryFooterCustomComponent<
|
|
|
60
62
|
photo?: Photo<StreamChatGenerics>;
|
|
61
63
|
}) => React.ReactElement | null;
|
|
62
64
|
|
|
65
|
+
export type ImageGalleryFooterVideoControlProps = {
|
|
66
|
+
duration: number;
|
|
67
|
+
onPlayPause: () => void;
|
|
68
|
+
onProgressDrag: (progress: number) => void;
|
|
69
|
+
paused: boolean;
|
|
70
|
+
progress: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type ImageGalleryFooterVideoControlComponent = ({
|
|
74
|
+
duration,
|
|
75
|
+
onPlayPause,
|
|
76
|
+
onProgressDrag,
|
|
77
|
+
paused,
|
|
78
|
+
progress,
|
|
79
|
+
}: ImageGalleryFooterVideoControlProps) => React.ReactElement | null;
|
|
80
|
+
|
|
63
81
|
export type ImageGalleryFooterCustomComponentProps<
|
|
64
82
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
65
83
|
> = {
|
|
@@ -68,41 +86,55 @@ export type ImageGalleryFooterCustomComponentProps<
|
|
|
68
86
|
leftElement?: ImageGalleryFooterCustomComponent<StreamChatGenerics>;
|
|
69
87
|
rightElement?: ImageGalleryFooterCustomComponent<StreamChatGenerics>;
|
|
70
88
|
ShareIcon?: React.ReactElement;
|
|
89
|
+
videoControlElement?: ImageGalleryFooterVideoControlComponent;
|
|
71
90
|
};
|
|
72
91
|
|
|
73
|
-
type
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
type ImageGalleryFooterPropsWithContext<
|
|
93
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
94
|
+
> = ImageGalleryFooterCustomComponentProps<StreamChatGenerics> & {
|
|
95
|
+
duration: number;
|
|
96
|
+
onPlayPause: () => void;
|
|
97
|
+
onProgressDrag: (progress: number) => void;
|
|
98
|
+
opacity: Animated.SharedValue<number>;
|
|
99
|
+
openGridView: () => void;
|
|
100
|
+
paused: boolean;
|
|
101
|
+
photo: Photo<StreamChatGenerics>;
|
|
102
|
+
photoLength: number;
|
|
103
|
+
progress: number;
|
|
104
|
+
selectedIndex: number;
|
|
105
|
+
visible: Animated.SharedValue<number>;
|
|
106
|
+
};
|
|
82
107
|
|
|
83
|
-
export const
|
|
108
|
+
export const ImageGalleryFooterWithContext = <
|
|
84
109
|
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
85
110
|
>(
|
|
86
|
-
props:
|
|
111
|
+
props: ImageGalleryFooterPropsWithContext<StreamChatGenerics>,
|
|
87
112
|
) => {
|
|
88
113
|
const {
|
|
89
114
|
centerElement,
|
|
115
|
+
duration,
|
|
90
116
|
GridIcon,
|
|
91
117
|
leftElement,
|
|
118
|
+
onPlayPause,
|
|
119
|
+
onProgressDrag,
|
|
92
120
|
opacity,
|
|
93
121
|
openGridView,
|
|
122
|
+
paused,
|
|
94
123
|
photo,
|
|
95
124
|
photoLength,
|
|
125
|
+
progress,
|
|
96
126
|
rightElement,
|
|
97
127
|
selectedIndex,
|
|
98
128
|
ShareIcon,
|
|
129
|
+
videoControlElement,
|
|
99
130
|
visible,
|
|
100
131
|
} = props;
|
|
132
|
+
|
|
101
133
|
const [height, setHeight] = useState(200);
|
|
102
134
|
const [shareMenuOpen, setShareMenuOpen] = useState(false);
|
|
103
135
|
const {
|
|
104
136
|
theme: {
|
|
105
|
-
colors: { black
|
|
137
|
+
colors: { black },
|
|
106
138
|
imageGallery: {
|
|
107
139
|
footer: {
|
|
108
140
|
centerContainer,
|
|
@@ -126,18 +158,21 @@ export const ImageGalleryFooter = <
|
|
|
126
158
|
},
|
|
127
159
|
],
|
|
128
160
|
}),
|
|
129
|
-
[],
|
|
161
|
+
[height],
|
|
130
162
|
);
|
|
131
163
|
|
|
132
164
|
const share = async () => {
|
|
133
165
|
setShareMenuOpen(true);
|
|
134
166
|
try {
|
|
135
|
-
const
|
|
136
|
-
|
|
167
|
+
const extension = photo.mime_type?.split('/')[1] || 'jpg';
|
|
168
|
+
const localFile = await saveFile({
|
|
169
|
+
fileName: `${photo.user?.id || 'ChatPhoto'}-${
|
|
170
|
+
photo.messageId
|
|
171
|
+
}-${selectedIndex}.${extension}`,
|
|
137
172
|
fromUrl: photo.uri,
|
|
138
173
|
});
|
|
139
|
-
await shareImage({ type:
|
|
140
|
-
await deleteFile({ uri:
|
|
174
|
+
await shareImage({ type: photo.mime_type, url: localFile });
|
|
175
|
+
await deleteFile({ uri: localFile });
|
|
141
176
|
} catch (error) {
|
|
142
177
|
console.log(error);
|
|
143
178
|
}
|
|
@@ -150,8 +185,21 @@ export const ImageGalleryFooter = <
|
|
|
150
185
|
pointerEvents={'box-none'}
|
|
151
186
|
style={styles.wrapper}
|
|
152
187
|
>
|
|
153
|
-
<ReanimatedSafeAreaView style={[
|
|
154
|
-
|
|
188
|
+
<ReanimatedSafeAreaView style={[container, footerStyle]}>
|
|
189
|
+
{photo.type === 'video' ? (
|
|
190
|
+
videoControlElement ? (
|
|
191
|
+
videoControlElement({ duration, onPlayPause, onProgressDrag, paused, progress })
|
|
192
|
+
) : (
|
|
193
|
+
<ImageGalleryVideoControl
|
|
194
|
+
duration={duration}
|
|
195
|
+
onPlayPause={onPlayPause}
|
|
196
|
+
onProgressDrag={onProgressDrag}
|
|
197
|
+
paused={paused}
|
|
198
|
+
progress={progress}
|
|
199
|
+
/>
|
|
200
|
+
)
|
|
201
|
+
) : null}
|
|
202
|
+
<View style={[styles.innerContainer, innerContainer, { backgroundColor: 'white' }]}>
|
|
155
203
|
{leftElement ? (
|
|
156
204
|
leftElement({ openGridView, photo, share, shareMenuOpen })
|
|
157
205
|
) : (
|
|
@@ -188,4 +236,51 @@ export const ImageGalleryFooter = <
|
|
|
188
236
|
);
|
|
189
237
|
};
|
|
190
238
|
|
|
239
|
+
const areEqual = <StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics>(
|
|
240
|
+
prevProps: ImageGalleryFooterPropsWithContext<StreamChatGenerics>,
|
|
241
|
+
nextProps: ImageGalleryFooterPropsWithContext<StreamChatGenerics>,
|
|
242
|
+
) => {
|
|
243
|
+
const {
|
|
244
|
+
duration: prevDuration,
|
|
245
|
+
paused: prevPaused,
|
|
246
|
+
progress: prevProgress,
|
|
247
|
+
selectedIndex: prevSelectedIndex,
|
|
248
|
+
} = prevProps;
|
|
249
|
+
const {
|
|
250
|
+
duration: nextDuration,
|
|
251
|
+
paused: nextPaused,
|
|
252
|
+
progress: nextProgress,
|
|
253
|
+
selectedIndex: nextSelectedIndex,
|
|
254
|
+
} = nextProps;
|
|
255
|
+
|
|
256
|
+
const isDurationEqual = prevDuration === nextDuration;
|
|
257
|
+
if (!isDurationEqual) return false;
|
|
258
|
+
|
|
259
|
+
const isPausedEqual = prevPaused === nextPaused;
|
|
260
|
+
if (!isPausedEqual) return false;
|
|
261
|
+
|
|
262
|
+
const isProgressEqual = prevProgress === nextProgress;
|
|
263
|
+
if (!isProgressEqual) return false;
|
|
264
|
+
|
|
265
|
+
const isSelectedIndexEqual = prevSelectedIndex === nextSelectedIndex;
|
|
266
|
+
if (!isSelectedIndexEqual) return false;
|
|
267
|
+
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const MemoizedImageGalleryFooter = React.memo(
|
|
272
|
+
ImageGalleryFooterWithContext,
|
|
273
|
+
areEqual,
|
|
274
|
+
) as typeof ImageGalleryFooterWithContext;
|
|
275
|
+
|
|
276
|
+
export type ImageGalleryFooterProps<
|
|
277
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
278
|
+
> = ImageGalleryFooterPropsWithContext<StreamChatGenerics>;
|
|
279
|
+
|
|
280
|
+
export const ImageGalleryFooter = <
|
|
281
|
+
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
|
|
282
|
+
>(
|
|
283
|
+
props: ImageGalleryFooterProps<StreamChatGenerics>,
|
|
284
|
+
) => <MemoizedImageGalleryFooter {...props} />;
|
|
285
|
+
|
|
191
286
|
ImageGalleryFooter.displayName = 'ImageGalleryFooter{imageGallery{footer}}';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
|
|
6
|
+
import type { ImageGalleryFooterVideoControlProps } from './ImageGalleryFooter';
|
|
7
|
+
import { ProgressControl } from './ProgressControl';
|
|
8
|
+
|
|
9
|
+
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
|
|
10
|
+
|
|
11
|
+
import { Pause, Play } from '../../../icons';
|
|
12
|
+
|
|
13
|
+
const styles = StyleSheet.create({
|
|
14
|
+
durationTextStyle: {
|
|
15
|
+
color: '#fff',
|
|
16
|
+
fontWeight: 'bold',
|
|
17
|
+
},
|
|
18
|
+
roundedView: {
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
backgroundColor: '#fff',
|
|
21
|
+
borderRadius: 50,
|
|
22
|
+
display: 'flex',
|
|
23
|
+
elevation: 2,
|
|
24
|
+
height: 36,
|
|
25
|
+
justifyContent: 'center',
|
|
26
|
+
width: 36,
|
|
27
|
+
},
|
|
28
|
+
videoContainer: {
|
|
29
|
+
alignItems: 'center',
|
|
30
|
+
backgroundColor: 'rgba(52, 52, 52, 0.1)',
|
|
31
|
+
display: 'flex',
|
|
32
|
+
flexDirection: 'row',
|
|
33
|
+
justifyContent: 'space-between',
|
|
34
|
+
padding: 10,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const ImageGalleryVideoControl: React.FC<ImageGalleryFooterVideoControlProps> = React.memo(
|
|
39
|
+
(props) => {
|
|
40
|
+
const { duration, onPlayPause, onProgressDrag, paused, progress } = props;
|
|
41
|
+
|
|
42
|
+
const videoDuration = duration
|
|
43
|
+
? duration / 3600 >= 1
|
|
44
|
+
? dayjs.duration(duration, 'second').format('HH:mm:ss')
|
|
45
|
+
: dayjs.duration(duration, 'second').format('mm:ss')
|
|
46
|
+
: null;
|
|
47
|
+
|
|
48
|
+
const progressValueInSeconds = progress * duration;
|
|
49
|
+
|
|
50
|
+
const progressDuration = progressValueInSeconds
|
|
51
|
+
? progressValueInSeconds / 3600 >= 1
|
|
52
|
+
? dayjs.duration(progressValueInSeconds, 'second').format('HH:mm:ss')
|
|
53
|
+
: dayjs.duration(progressValueInSeconds, 'second').format('mm:ss')
|
|
54
|
+
: null;
|
|
55
|
+
|
|
56
|
+
const {
|
|
57
|
+
theme: {
|
|
58
|
+
imageGallery: {
|
|
59
|
+
videoControl: { durationTextStyle, roundedView, videoContainer },
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
} = useTheme();
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<View style={[styles.videoContainer, videoContainer]}>
|
|
66
|
+
<TouchableOpacity onPress={onPlayPause}>
|
|
67
|
+
<View style={[styles.roundedView, roundedView]}>
|
|
68
|
+
{paused ? (
|
|
69
|
+
<Play height={24} pathFill={'#000'} width={24} />
|
|
70
|
+
) : (
|
|
71
|
+
<Pause height={24} width={24} />
|
|
72
|
+
)}
|
|
73
|
+
</View>
|
|
74
|
+
</TouchableOpacity>
|
|
75
|
+
<Text style={[styles.durationTextStyle, durationTextStyle]}>
|
|
76
|
+
{progressDuration ? progressDuration : '00:00'}
|
|
77
|
+
</Text>
|
|
78
|
+
<ProgressControl
|
|
79
|
+
duration={duration}
|
|
80
|
+
onPlayPause={onPlayPause}
|
|
81
|
+
onProgressDrag={onProgressDrag}
|
|
82
|
+
progress={progress}
|
|
83
|
+
/>
|
|
84
|
+
<Text style={[styles.durationTextStyle, durationTextStyle]}>
|
|
85
|
+
{videoDuration ? videoDuration : '00:00'}
|
|
86
|
+
</Text>
|
|
87
|
+
</View>
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
(prevProps, nextProps) => {
|
|
91
|
+
if (
|
|
92
|
+
prevProps.duration === nextProps.duration &&
|
|
93
|
+
prevProps.paused === nextProps.paused &&
|
|
94
|
+
prevProps.progress === nextProps.progress
|
|
95
|
+
) {
|
|
96
|
+
return true;
|
|
97
|
+
} else {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
ImageGalleryVideoControl.displayName = 'ImageGalleryVideoControl{imageGallery{videoControl}}';
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Image, StyleSheet, View } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import { BottomSheetFlatList, TouchableOpacity } from '@gorhom/bottom-sheet';
|
|
5
5
|
|
|
6
|
+
import { VideoThumbnail } from '../../../components/Attachment/VideoThumbnail';
|
|
6
7
|
import { useTheme } from '../../../contexts/themeContext/ThemeContext';
|
|
7
8
|
import type { DefaultStreamChatGenerics } from '../../../types/types';
|
|
8
9
|
import { vw } from '../../../utils/utils';
|
|
9
|
-
import { Avatar } from '../../Avatar/Avatar';
|
|
10
10
|
|
|
11
11
|
import type { Photo } from '../ImageGallery';
|
|
12
12
|
|
|
@@ -66,15 +66,14 @@ const GridImage = <
|
|
|
66
66
|
}) => {
|
|
67
67
|
const {
|
|
68
68
|
theme: {
|
|
69
|
-
colors: { white },
|
|
70
69
|
imageGallery: {
|
|
71
|
-
grid: {
|
|
70
|
+
grid: { gridImage },
|
|
72
71
|
},
|
|
73
72
|
},
|
|
74
73
|
} = useTheme();
|
|
75
|
-
const {
|
|
74
|
+
const { imageComponent, ...restItem } = item;
|
|
76
75
|
|
|
77
|
-
const { numberOfImageGalleryGridColumns, selectAndClose,
|
|
76
|
+
const { numberOfImageGalleryGridColumns, selectAndClose, type, uri } = restItem;
|
|
78
77
|
|
|
79
78
|
const size = vw(100) / (numberOfImageGalleryGridColumns || 3) - 2;
|
|
80
79
|
|
|
@@ -84,25 +83,13 @@ const GridImage = <
|
|
|
84
83
|
|
|
85
84
|
return (
|
|
86
85
|
<TouchableOpacity onPress={selectAndClose}>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
<Avatar
|
|
95
|
-
containerStyle={[
|
|
96
|
-
styles.avatarImageWrapper,
|
|
97
|
-
{ backgroundColor: white },
|
|
98
|
-
gridAvatarWrapper,
|
|
99
|
-
]}
|
|
100
|
-
image={user.image}
|
|
101
|
-
imageStyle={gridAvatar}
|
|
102
|
-
size={22}
|
|
103
|
-
/>
|
|
104
|
-
)}
|
|
105
|
-
</ImageBackground>
|
|
86
|
+
{type === 'video' ? (
|
|
87
|
+
<View style={[styles.image, { height: size, width: size }, gridImage]}>
|
|
88
|
+
<VideoThumbnail />
|
|
89
|
+
</View>
|
|
90
|
+
) : (
|
|
91
|
+
<Image source={{ uri }} style={[styles.image, { height: size, width: size }]} />
|
|
92
|
+
)}
|
|
106
93
|
</TouchableOpacity>
|
|
107
94
|
);
|
|
108
95
|
};
|