-
Notifications
You must be signed in to change notification settings - Fork 374
Expand file tree
/
Copy pathuseChannelPreviewDisplayName.ts
More file actions
109 lines (87 loc) · 3.51 KB
/
useChannelPreviewDisplayName.ts
File metadata and controls
109 lines (87 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { useMemo } from 'react';
import type { Channel, ChannelMemberResponse } from 'stream-chat';
import { useChatContext } from '../../../contexts/chatContext/ChatContext';
import { useViewport } from '../../../hooks/useViewport';
import type { DefaultStreamChatGenerics } from '../../../types/types';
const ELLIPSIS = '...';
const getMemberName = (member: ChannelMemberResponse) =>
member.user?.name || member.user?.id || 'Unknown User';
export const getChannelPreviewDisplayName = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
>({
channelName,
characterLimit,
currentUserId,
members,
}: {
characterLimit: number;
channelName?: string;
currentUserId?: string;
members?: Channel<StreamChatGenerics>['state']['members'];
}): string => {
if (channelName) {
return channelName.length > characterLimit
? `${channelName.slice(0, characterLimit - ELLIPSIS.length)}${ELLIPSIS}`
: channelName;
}
const channelMembers = Object.values(members || {});
const otherMembers = channelMembers.filter((member) => member.user?.id !== currentUserId);
otherMembers.sort((prevUser, nextUser) =>
(prevUser?.user?.name ?? '')
.toLowerCase()
.localeCompare((nextUser?.user?.name ?? '').toLocaleUpperCase()),
);
const createChannelNameSuffix = (remainingNumberOfMembers: number) =>
remainingNumberOfMembers <= 1 ? `${ELLIPSIS}` : `,${ELLIPSIS}+${remainingNumberOfMembers}`;
if (otherMembers.length === 1) {
const name = getMemberName(otherMembers[0]);
return name.length > characterLimit
? `${name.slice(0, characterLimit - ELLIPSIS.length)}${ELLIPSIS}`
: name;
}
const name = otherMembers.reduce((result, currentMember, index, originalArray) => {
if (result.length >= characterLimit) {
return result;
}
const currentMemberName = getMemberName(currentMember);
const resultHasSpaceForCurrentMemberName =
result.length + (currentMemberName.length + ELLIPSIS.length) < characterLimit;
if (resultHasSpaceForCurrentMemberName) {
return result.length > 0 ? `${result}, ${currentMemberName}` : `${currentMemberName}`;
} else {
const remainingNumberOfMembers = originalArray.length - index;
const truncateLimit = characterLimit - (ELLIPSIS.length + result.length);
const tuncatedCurrentMemberName = `, ${currentMemberName.slice(0, truncateLimit)}`;
const channelNameSuffix = createChannelNameSuffix(remainingNumberOfMembers);
return `${result}${tuncatedCurrentMemberName}${channelNameSuffix}`;
}
}, '');
return name;
};
export const useChannelPreviewDisplayName = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
>(
channel?: Channel<StreamChatGenerics>,
characterLength?: number,
) => {
const { client } = useChatContext<StreamChatGenerics>();
const { vw } = useViewport();
const DEFAULT_MAX_CHARACTER_LENGTH = Math.floor((vw(100) - 16) / 6);
const currentUserId = client?.userID;
const members = channel?.state?.members;
const channelName = channel?.data?.name;
const characterLimit = characterLength || DEFAULT_MAX_CHARACTER_LENGTH;
const numOfMembers = Object.keys(members || {}).length;
const displayName = useMemo(
() =>
getChannelPreviewDisplayName({
channelName,
characterLimit,
currentUserId,
members,
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[channelName, characterLimit, currentUserId, members, numOfMembers],
);
return displayName;
};