Skip to content

Commit 3893076

Browse files
committed
Merge branch 'develop' of github.com:GetStream/stream-chat-react-native into V8
2 parents a15126f + 6c32f8b commit 3893076

File tree

4 files changed

+76
-37
lines changed

4 files changed

+76
-37
lines changed

package/src/components/Attachment/FileAttachmentGroup.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ type FilesToDisplayType = Attachment & {
3939

4040
const FileAttachmentGroupWithContext = (props: FileAttachmentGroupPropsWithContext) => {
4141
const { Attachment, AudioAttachment, files, messageId, styles: stylesProp = {} } = props;
42-
const [filesToDisplay, setFilesToDisplay] = useState<FilesToDisplayType[]>([]);
42+
const [filesToDisplay, setFilesToDisplay] = useState<FilesToDisplayType[]>(() =>
43+
files.map((file) => ({ ...file, duration: file.duration || 0, paused: true, progress: 0 })),
44+
);
4345

4446
useEffect(() => {
4547
setFilesToDisplay(

package/src/components/ChannelList/hooks/usePaginatedChannels.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export const usePaginatedChannels = ({
282282
// ready. I do not like providing a way to set the ready state, as it should be managed
283283
// in the LLC entirely. Once we move offline support to the LLC, we can remove this check
284284
// too as it'll be redundant.
285-
pagination?.isLoading || (!channelListInitialized && channels.length === 0),
285+
pagination?.isLoading || (!channelListInitialized && channels.length === 0 && !error),
286286
loadingNextPage: pagination?.isLoadingNext,
287287
loadNextPage: channelManager.loadNext,
288288
refreshing: activeQueryType === 'refresh',

package/src/components/Message/Message.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,12 @@ export type MessagePropsWithContext = Pick<
135135
> &
136136
Pick<KeyboardContextValue, 'dismissKeyboard'> &
137137
Partial<
138-
Omit<MessageContextValue, 'groupStyles' | 'handleReaction' | 'message' | 'isMessageAIGenerated'>
138+
Omit<
139+
MessageContextValue,
140+
'groupStyles' | 'handleReaction' | 'message' | 'isMessageAIGenerated' | 'readBy'
141+
>
139142
> &
140-
Pick<MessageContextValue, 'groupStyles' | 'message' | 'isMessageAIGenerated'> &
143+
Pick<MessageContextValue, 'groupStyles' | 'message' | 'isMessageAIGenerated' | 'readBy'> &
141144
Pick<
142145
MessagesContextValue,
143146
| 'sendReaction'
@@ -262,8 +265,8 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
262265
t,
263266
threadList = false,
264267
updateMessage,
268+
readBy,
265269
} = props;
266-
const { read } = useChannelContext();
267270
const isMessageAIGenerated = messagesContext.isMessageAIGenerated;
268271
const isAIGenerated = useMemo(
269272
() => isMessageAIGenerated(message),
@@ -278,7 +281,6 @@ const MessageWithContext = (props: MessagePropsWithContext) => {
278281
screenPadding,
279282
},
280283
} = useTheme();
281-
const readBy = useMemo(() => getReadState(message, read), [message, read]);
282284

283285
const showMessageOverlay = async (showMessageReactions = false, selectedReaction?: string) => {
284286
await dismissKeyboard();
@@ -759,6 +761,7 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
759761
message: prevMessage,
760762
messagesContext: prevMessagesContext,
761763
showUnreadUnderlay: prevShowUnreadUnderlay,
764+
readBy: prevReadBy,
762765
t: prevT,
763766
} = prevProps;
764767
const {
@@ -771,9 +774,15 @@ const areEqual = (prevProps: MessagePropsWithContext, nextProps: MessagePropsWit
771774
message: nextMessage,
772775
messagesContext: nextMessagesContext,
773776
showUnreadUnderlay: nextShowUnreadUnderlay,
777+
readBy: nextReadBy,
774778
t: nextT,
775779
} = nextProps;
776780

781+
const readByEqual = prevReadBy === nextReadBy;
782+
if (!readByEqual) {
783+
return false;
784+
}
785+
777786
const membersEqual = Object.keys(prevMembers).length === Object.keys(nextMembers).length;
778787
if (!membersEqual) {
779788
return false;
@@ -925,12 +934,14 @@ export type MessageProps = Partial<
925934
* @example ./Message.md
926935
*/
927936
export const Message = (props: MessageProps) => {
928-
const { channel, enforceUniqueReaction, members } = useChannelContext();
937+
const { message } = props;
938+
const { channel, enforceUniqueReaction, members, read } = useChannelContext();
929939
const chatContext = useChatContext();
930940
const { dismissKeyboard } = useKeyboardContext();
931941
const messagesContext = useMessagesContext();
932942
const { openThread } = useThreadContext();
933943
const { t } = useTranslationContext();
944+
const readBy = useMemo(() => getReadState(message, read), [message, read]);
934945

935946
return (
936947
<MemoizedMessage
@@ -943,6 +954,7 @@ export const Message = (props: MessageProps) => {
943954
members,
944955
messagesContext,
945956
openThread,
957+
readBy,
946958
t,
947959
}}
948960
{...props}

package/src/components/Message/MessageSimple/MessageSimple.tsx

Lines changed: 55 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ export type MessageSimplePropsWithContext = Pick<
9090
| 'reactionListPosition'
9191
| 'ReactionListTop'
9292
| 'setQuotedMessageState'
93-
>;
93+
> & {
94+
/**
95+
* Will determine whether the swipeable wrapper is always rendered for each
96+
* message. If set to false, the animated wrapper will be rendered only when
97+
* a swiping gesture is active and not otherwise.
98+
* Since stateful components would lose their state if we remount them while
99+
* an animation is happening, this should always be set to true in those instances.
100+
*/
101+
shouldRenderSwipeableWrapper: boolean;
102+
};
94103

95104
const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
96105
const [messageContentWidth, setMessageContentWidth] = useState(0);
@@ -123,6 +132,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
123132
ReactionListTop,
124133
setQuotedMessageState,
125134
showMessageStatus,
135+
shouldRenderSwipeableWrapper,
126136
} = props;
127137

128138
const {
@@ -202,7 +212,9 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
202212
const translateX = useSharedValue(0);
203213
const touchStart = useSharedValue<{ x: number; y: number } | null>(null);
204214
const isSwiping = useSharedValue<boolean>(false);
205-
const [isBeingSwiped, setIsBeingSwiped] = useState<boolean>(false);
215+
const [shouldRenderAnimatedWrapper, setShouldRenderAnimatedWrapper] = useState<boolean>(
216+
shouldRenderSwipeableWrapper,
217+
);
206218

207219
const onSwipeToReply = useCallback(() => {
208220
clearQuotedMessageState();
@@ -233,7 +245,9 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
233245
if (isHorizontalPanning) {
234246
state.activate();
235247
isSwiping.value = true;
236-
runOnJS(setIsBeingSwiped)(true);
248+
if (!shouldRenderSwipeableWrapper) {
249+
runOnJS(setShouldRenderAnimatedWrapper)(isSwiping.value);
250+
}
237251
} else {
238252
state.fail();
239253
}
@@ -253,6 +267,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
253267
runOnJS(triggerHaptic)('impactMedium');
254268
}
255269
}
270+
isSwiping.value = false;
256271
translateX.value = withSpring(
257272
0,
258273
{
@@ -262,41 +277,44 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
262277
stiffness: 1,
263278
},
264279
() => {
265-
isSwiping.value = false;
266-
runOnJS(setIsBeingSwiped)(false);
280+
if (!shouldRenderSwipeableWrapper) {
281+
runOnJS(setShouldRenderAnimatedWrapper)(isSwiping.value);
282+
}
267283
},
268284
);
269285
}),
270-
[isSwiping, messageSwipeToReplyHitSlop, onSwipeToReply, touchStart, translateX, triggerHaptic],
286+
[
287+
isSwiping,
288+
messageSwipeToReplyHitSlop,
289+
onSwipeToReply,
290+
touchStart,
291+
translateX,
292+
triggerHaptic,
293+
shouldRenderSwipeableWrapper,
294+
],
271295
);
272296

273297
const messageBubbleAnimatedStyle = useAnimatedStyle(
274-
() =>
275-
isSwiping.value
276-
? {
277-
transform: [{ translateX: translateX.value }],
278-
}
279-
: {},
298+
() => ({
299+
transform: [{ translateX: translateX.value }],
300+
}),
280301
[],
281302
);
282303

283304
const swipeContentAnimatedStyle = useAnimatedStyle(
284-
() =>
285-
isSwiping.value
286-
? {
287-
opacity: interpolate(translateX.value, [0, THRESHOLD], [0, 1]),
288-
transform: [
289-
{
290-
translateX: interpolate(
291-
translateX.value,
292-
[0, THRESHOLD],
293-
[-THRESHOLD, 0],
294-
Extrapolation.CLAMP,
295-
),
296-
},
297-
],
298-
}
299-
: {},
305+
() => ({
306+
opacity: interpolate(translateX.value, [0, THRESHOLD], [0, 1]),
307+
transform: [
308+
{
309+
translateX: interpolate(
310+
translateX.value,
311+
[0, THRESHOLD],
312+
[-THRESHOLD, 0],
313+
Extrapolation.CLAMP,
314+
),
315+
},
316+
],
317+
}),
300318
[],
301319
);
302320

@@ -332,7 +350,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
332350
() => (
333351
<GestureDetector gesture={swipeGesture}>
334352
<View hitSlop={messageSwipeToReplyHitSlop} style={[styles.contentWrapper, contentWrapper]}>
335-
{isBeingSwiped ? (
353+
{shouldRenderAnimatedWrapper ? (
336354
<>
337355
<AnimatedWrapper
338356
style={[
@@ -356,7 +374,7 @@ const MessageSimpleWithContext = (props: MessageSimplePropsWithContext) => {
356374
[
357375
MessageSwipeContent,
358376
contentWrapper,
359-
isBeingSwiped,
377+
shouldRenderAnimatedWrapper,
360378
messageBubbleAnimatedStyle,
361379
messageSwipeToReplyHitSlop,
362380
renderMessageBubble,
@@ -592,6 +610,7 @@ export const MessageSimple = (props: MessageSimpleProps) => {
592610
onlyEmojis,
593611
otherAttachments,
594612
showMessageStatus,
613+
isMessageAIGenerated,
595614
} = useMessageContext();
596615
const {
597616
clearQuotedMessageState,
@@ -613,6 +632,11 @@ export const MessageSimple = (props: MessageSimpleProps) => {
613632
ReactionListTop,
614633
setQuotedMessageState,
615634
} = useMessagesContext();
635+
const isAIGenerated = useMemo(
636+
() => isMessageAIGenerated(message),
637+
[message, isMessageAIGenerated],
638+
);
639+
const shouldRenderSwipeableWrapper = (message?.attachments || []).length > 0 || isAIGenerated;
616640

617641
return (
618642
<MemoizedMessageSimple
@@ -645,6 +669,7 @@ export const MessageSimple = (props: MessageSimpleProps) => {
645669
reactionListPosition,
646670
ReactionListTop,
647671
setQuotedMessageState,
672+
shouldRenderSwipeableWrapper,
648673
showMessageStatus,
649674
}}
650675
{...props}

0 commit comments

Comments
 (0)