Skip to content

Commit 52ef753

Browse files
committed
Merge branch 'develop' into V7
# Conflicts: # .github/workflows/sample-distribution.yml # package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayPresence.ts # package/src/components/ChannelPreview/hooks/useIsChannelMuted.ts # package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts # package/src/hooks/useTranslatedMessage.ts
2 parents 228d559 + 70e6c70 commit 52ef753

File tree

8 files changed

+101
-130
lines changed

8 files changed

+101
-130
lines changed

.github/workflows/sample-distribution.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ on:
1414
jobs:
1515
build_and_deploy_ios_testflight_qa:
1616
name: Build SampleApp iOS and Deploy-${{ github.ref == 'refs/heads/V7' }}
17-
runs-on: [macos-14]
17+
runs-on: [macos-15]
1818
steps:
1919
- name: Connect Bot
2020
uses: webfactory/[email protected]

package/src/components/Avatar/Avatar.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useCallback, useMemo } from 'react';
22
import {
33
Image,
44
ImageProps,
@@ -83,6 +83,34 @@ export const Avatar = (props: AvatarProps) => {
8383

8484
const { isLoadingImageError, setLoadingImageError } = useLoadingImage();
8585

86+
const onError = useCallback(() => {
87+
setLoadingImageError(true);
88+
}, [setLoadingImageError]);
89+
90+
const uri = useMemo(() => {
91+
let imageUrl;
92+
if (
93+
!imageProp ||
94+
imageProp.includes(randomImageBaseUrl) ||
95+
imageProp.includes(randomSvgBaseUrl)
96+
) {
97+
if (imageProp?.includes(streamCDN)) {
98+
imageUrl = imageProp;
99+
} else {
100+
imageUrl = `${randomImageBaseUrl}${name ? `?name=${getInitials(name)}&size=${size}` : ''}`;
101+
}
102+
} else {
103+
imageUrl = getResizedImageUrl({
104+
height: size,
105+
resizableCDNHosts,
106+
url: imageProp,
107+
width: size,
108+
});
109+
}
110+
111+
return imageUrl;
112+
}, [imageProp, name, size, resizableCDNHosts]);
113+
86114
return (
87115
<View>
88116
<View
@@ -108,24 +136,10 @@ export const Avatar = (props: AvatarProps) => {
108136
/>
109137
) : (
110138
<ImageComponent
111-
accessibilityLabel={testID || 'Avatar Image'}
112-
onError={() => setLoadingImageError(true)}
139+
accessibilityLabel={testID ?? 'Avatar Image'}
140+
onError={onError}
113141
source={{
114-
uri:
115-
!imageProp ||
116-
imageProp.includes(randomImageBaseUrl) ||
117-
imageProp.includes(randomSvgBaseUrl)
118-
? imageProp?.includes(streamCDN)
119-
? imageProp
120-
: `${randomImageBaseUrl}${
121-
name ? `?name=${getInitials(name)}&size=${size}` : ''
122-
}`
123-
: getResizedImageUrl({
124-
height: size,
125-
resizableCDNHosts,
126-
url: imageProp,
127-
width: size,
128-
}),
142+
uri,
129143
}}
130144
style={[
131145
image,
@@ -139,7 +153,7 @@ export const Avatar = (props: AvatarProps) => {
139153
: {},
140154
imageStyle,
141155
]}
142-
testID={testID || 'avatar-image'}
156+
testID={testID ?? 'avatar-image'}
143157
/>
144158
)}
145159
</View>

package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayAvatar.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useMemo } from 'react';
22

33
import type { Channel, StreamChat } from 'stream-chat';
44

@@ -50,19 +50,10 @@ export const getChannelPreviewDisplayAvatar = (channel: Channel, client: StreamC
5050
export const useChannelPreviewDisplayAvatar = (channel: Channel) => {
5151
const { client } = useChatContext();
5252

53-
const channelData = channel?.data;
54-
const image = channelData?.image;
55-
const name = channelData?.name;
56-
const id = client?.user?.id;
57-
58-
const [displayAvatar, setDisplayAvatar] = useState(
59-
getChannelPreviewDisplayAvatar(channel, client),
53+
const displayAvatar = useMemo(
54+
() => getChannelPreviewDisplayAvatar(channel, client),
55+
[channel, client],
6056
);
6157

62-
useEffect(() => {
63-
setDisplayAvatar(getChannelPreviewDisplayAvatar(channel, client));
64-
// eslint-disable-next-line react-hooks/exhaustive-deps
65-
}, [id, image, name]);
66-
6758
return displayAvatar;
6859
};

package/src/components/ChannelPreview/hooks/useChannelPreviewDisplayName.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useMemo } from 'react';
22

33
import type { Channel, ChannelMemberResponse } from 'stream-chat';
44

@@ -22,7 +22,9 @@ export const getChannelPreviewDisplayName = ({
2222
members?: Channel['state']['members'];
2323
}): string => {
2424
if (channelName) {
25-
return channelName;
25+
return channelName.length > characterLimit
26+
? `${channelName.slice(0, characterLimit - ELLIPSIS.length)}${ELLIPSIS}`
27+
: channelName;
2628
}
2729

2830
const channelMembers = Object.values(members || {});
@@ -74,33 +76,25 @@ export const useChannelPreviewDisplayName = (channel?: Channel, characterLength?
7476
const { client } = useChatContext();
7577
const { vw } = useViewport();
7678

77-
const DEFAULT_MAX_CHARACTER_LENGTH = (vw(100) - 16) / 6;
79+
const DEFAULT_MAX_CHARACTER_LENGTH = Math.floor((vw(100) - 16) / 6);
7880

7981
const currentUserId = client?.userID;
8082
const members = channel?.state?.members;
81-
const numOfMembers = Object.keys(members || {}).length;
8283
const channelName = channel?.data?.name;
8384
const characterLimit = characterLength || DEFAULT_MAX_CHARACTER_LENGTH;
84-
const [displayName, setDisplayName] = useState(
85-
getChannelPreviewDisplayName({
86-
channelName,
87-
characterLimit,
88-
currentUserId,
89-
members,
90-
}),
91-
);
85+
const numOfMembers = Object.keys(members || {}).length;
9286

93-
useEffect(() => {
94-
setDisplayName(
87+
const displayName = useMemo(
88+
() =>
9589
getChannelPreviewDisplayName({
9690
channelName,
9791
characterLimit,
9892
currentUserId,
9993
members,
10094
}),
101-
);
10295
// eslint-disable-next-line react-hooks/exhaustive-deps
103-
}, [channelName, currentUserId, characterLimit, numOfMembers]);
96+
[channelName, characterLimit, currentUserId, members, numOfMembers],
97+
);
10498

10599
return displayName;
106100
};
Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,23 @@
1-
import { useEffect, useState } from 'react';
2-
3-
import type { Channel, StreamChat } from 'stream-chat';
1+
import type { Channel } from 'stream-chat';
42

53
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
64

7-
const getChannelPreviewDisplayPresence = (channel: Channel, client: StreamChat) => {
8-
const currentUserId = client.userID;
9-
10-
if (currentUserId) {
11-
const members = Object.values(channel.state.members);
12-
const otherMembers = members.filter((member) => member.user?.id !== currentUserId);
13-
14-
if (otherMembers.length === 1) {
15-
return !!otherMembers[0].user?.online;
16-
}
17-
}
18-
return false;
19-
};
20-
215
/**
226
* Hook to set the display avatar presence for channel preview
237
* @param {*} channel
248
*
259
* @returns {boolean} e.g., true
2610
*/
27-
export const useChannelPreviewDisplayPresence = (channel: Channel) => {
11+
export const useChannelPreviewDisplayPresence = (
12+
channel: Channel,
13+
) => {
2814
const { client } = useChatContext();
15+
const members = channel.state.members;
16+
const membersCount = Object.keys(members).length;
2917

30-
const currentUserId = client.userID;
31-
const members = Object.values(channel.state.members).filter(
32-
(member) => !!member.user?.id && !!currentUserId && member.user?.id !== currentUserId,
33-
);
34-
const channelMemberOnline = members.some((member) => member.user?.online);
35-
36-
const [displayPresence, setDisplayPresence] = useState(false);
18+
if (membersCount !== 2) return false;
3719

38-
useEffect(() => {
39-
setDisplayPresence(getChannelPreviewDisplayPresence(channel, client));
40-
}, [channel, channelMemberOnline, client]);
20+
const otherMember = Object.values(members).find((member) => member.user?.id !== client.userID);
4121

42-
return displayPresence;
22+
return otherMember?.user?.online ?? false;
4323
};

package/src/components/ChannelPreview/hooks/useIsChannelMuted.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ import type { Channel } from 'stream-chat';
44

55
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
66

7-
export const useIsChannelMuted = (channel: Channel) => {
7+
8+
const defaultMuteStatus = {
9+
createdAt: null,
10+
expiresAt: null,
11+
muted: false,
12+
};
13+
14+
export const useIsChannelMuted =(
15+
channel: Channel,
16+
) => {
817
const { client } = useChatContext();
918

1019
const [muted, setMuted] = useState(() => channel.muteStatus());
@@ -18,5 +27,5 @@ export const useIsChannelMuted = (channel: Channel) => {
1827
return () => client.off('notification.channel_mutes_updated', handleEvent);
1928
}, [channel, client, muted]);
2029

21-
return muted || { createdAt: null, expiresAt: null, muted: false };
30+
return muted ?? defaultMuteStatus;
2231
};

package/src/components/ChannelPreview/hooks/useLatestMessagePreview.ts

Lines changed: 29 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState } from 'react';
1+
import { useMemo } from 'react';
22

33
import { TFunction } from 'i18next';
44
import type {
@@ -259,61 +259,44 @@ export const useLatestMessagePreview = (
259259
? stringifyMessage(translatedLastMessage)
260260
: '';
261261

262-
const [readEvents, setReadEvents] = useState(true);
263-
const [latestMessagePreview, setLatestMessagePreview] = useState<LatestMessagePreview>({
264-
created_at: '',
265-
messageObject: undefined,
266-
previews: [
267-
{
268-
bold: false,
269-
text: '',
270-
},
271-
],
272-
status: MessageReadStatus.NOT_SENT_BY_CURRENT_USER,
273-
});
262+
const readEvents = useMemo(() => {
263+
if (!channelConfigExists) {
264+
return true;
265+
}
266+
const read_events = !channel.disconnected && !!channel?.id && channel.getConfig()?.read_events;
267+
if (typeof read_events !== 'boolean') {
268+
return true;
269+
}
270+
return read_events;
271+
}, [channelConfigExists, channel]);
274272

275273
const readStatus = getLatestMessageReadStatus(channel, client, translatedLastMessage, readEvents);
276274

277-
useEffect(() => {
278-
if (channelConfigExists) {
279-
const read_events =
280-
!channel.disconnected && !!channel?.id && channel.getConfig()?.read_events;
281-
if (typeof read_events === 'boolean') {
282-
setReadEvents(read_events);
283-
}
284-
}
285-
// eslint-disable-next-line react-hooks/exhaustive-deps
286-
}, [channelConfigExists]);
287-
288275
const pollId = lastMessage?.poll_id ?? '';
289276
const poll = client.polls.fromState(pollId);
290277
const pollState: LatestMessagePreviewSelectorReturnType =
291278
useStateStore(poll?.state, selector) ?? {};
292279
const { createdBy, latestVotesByOption, name } = pollState;
293280

294-
useEffect(
295-
() =>
296-
setLatestMessagePreview(
297-
getLatestMessagePreview({
298-
channel,
299-
client,
300-
lastMessage: translatedLastMessage,
301-
pollState,
302-
readEvents,
303-
t,
304-
}),
305-
),
306-
// eslint-disable-next-line react-hooks/exhaustive-deps
307-
[
308-
channelLastMessageString,
309-
forceUpdate,
281+
const latestMessagePreview = useMemo(() => {
282+
return getLatestMessagePreview({
283+
channel,
284+
client,
285+
lastMessage: translatedLastMessage,
286+
pollState,
310287
readEvents,
311-
readStatus,
312-
latestVotesByOption,
313-
createdBy,
314-
name,
315-
],
316-
);
288+
t,
289+
});
290+
// eslint-disable-next-line react-hooks/exhaustive-deps
291+
}, [
292+
channelLastMessageString,
293+
forceUpdate,
294+
readEvents,
295+
readStatus,
296+
latestVotesByOption,
297+
createdBy,
298+
name,
299+
]);
317300

318301
return latestMessagePreview;
319302
};

package/src/hooks/useTranslatedMessage.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { useTranslationContext } from '../contexts/translationContext/Translatio
44

55
type TranslationKey = `${TranslationLanguages}_text`;
66

7-
export const useTranslatedMessage = (message?: MessageResponse | FormatMessageResponse) => {
8-
const { userLanguage: translationContextUserLanguage } = useTranslationContext();
9-
10-
const userLanguage = translationContextUserLanguage;
7+
export const useTranslatedMessage = (
8+
message?: MessageResponse | FormatMessageResponse,
9+
) => {
10+
const { userLanguage } = useTranslationContext();
1111

1212
const translationKey: TranslationKey = `${userLanguage}_text`;
1313

0 commit comments

Comments
 (0)