@sendbird/uikit-utils 2.0.3 → 2.2.0
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/hooks/index.js +14 -1
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/index.js +39 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/sendbird/channel.js +18 -6
- package/lib/commonjs/sendbird/channel.js.map +1 -1
- package/lib/commonjs/sendbird/message.js +12 -2
- package/lib/commonjs/sendbird/message.js.map +1 -1
- package/lib/commonjs/sendbird/user.js +23 -0
- package/lib/commonjs/sendbird/user.js.map +1 -0
- package/lib/commonjs/shared/bufferedRequest.js +38 -12
- package/lib/commonjs/shared/bufferedRequest.js.map +1 -1
- package/lib/commonjs/shared/regex.js +52 -6
- package/lib/commonjs/shared/regex.js.map +1 -1
- package/lib/commonjs/shared/replace.js +14 -0
- package/lib/commonjs/shared/replace.js.map +1 -0
- package/lib/commonjs/types.js +3 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/ui-format/common.js +17 -14
- package/lib/commonjs/ui-format/common.js.map +1 -1
- package/lib/commonjs/ui-format/groupChannel.js +7 -10
- package/lib/commonjs/ui-format/groupChannel.js.map +1 -1
- package/lib/module/hooks/index.js +10 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/index.js +4 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/sendbird/channel.js +14 -4
- package/lib/module/sendbird/channel.js.map +1 -1
- package/lib/module/sendbird/message.js +9 -3
- package/lib/module/sendbird/message.js.map +1 -1
- package/lib/module/sendbird/user.js +12 -0
- package/lib/module/sendbird/user.js.map +1 -0
- package/lib/module/shared/bufferedRequest.js +39 -12
- package/lib/module/shared/bufferedRequest.js.map +1 -1
- package/lib/module/shared/regex.js +43 -3
- package/lib/module/shared/regex.js.map +1 -1
- package/lib/module/shared/replace.js +6 -0
- package/lib/module/shared/replace.js.map +1 -0
- package/lib/module/types.js +1 -4
- package/lib/module/types.js.map +1 -1
- package/lib/module/ui-format/common.js +12 -7
- package/lib/module/ui-format/common.js.map +1 -1
- package/lib/module/ui-format/groupChannel.js +5 -4
- package/lib/module/ui-format/groupChannel.js.map +1 -1
- package/lib/typescript/src/hooks/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts +4 -2
- package/lib/typescript/src/sendbird/channel.d.ts +6 -1
- package/lib/typescript/src/sendbird/message.d.ts +4 -2
- package/lib/typescript/src/sendbird/user.d.ts +7 -0
- package/lib/typescript/src/shared/bufferedRequest.d.ts +6 -4
- package/lib/typescript/src/shared/logger.d.ts +1 -1
- package/lib/typescript/src/shared/pubsub.d.ts +2 -2
- package/lib/typescript/src/shared/regex.d.ts +8 -0
- package/lib/typescript/src/shared/replace.d.ts +2 -0
- package/lib/typescript/src/types.d.ts +42 -35
- package/lib/typescript/src/ui-format/common.d.ts +7 -6
- package/package.json +3 -3
- package/src/hooks/index.ts +11 -0
- package/src/index.ts +14 -2
- package/src/sendbird/channel.ts +11 -4
- package/src/sendbird/message.ts +13 -3
- package/src/sendbird/user.ts +21 -0
- package/src/shared/bufferedRequest.ts +37 -12
- package/src/shared/regex.ts +35 -0
- package/src/shared/replace.ts +5 -0
- package/src/types.ts +21 -3
- package/src/ui-format/common.ts +9 -7
- package/src/ui-format/groupChannel.ts +5 -4
package/src/hooks/index.ts
CHANGED
|
@@ -56,6 +56,17 @@ export const useIsMountedRef = () => {
|
|
|
56
56
|
return isMounted;
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
export const useIsFirstMount = () => {
|
|
60
|
+
const isFirstMount = useRef(true);
|
|
61
|
+
|
|
62
|
+
if (isFirstMount.current) {
|
|
63
|
+
isFirstMount.current = false;
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return isFirstMount.current;
|
|
68
|
+
};
|
|
69
|
+
|
|
59
70
|
export const useFreshCallback = <T extends (...args: any[]) => any>(callback: T): T => {
|
|
60
71
|
const ref = useRef<T>(callback);
|
|
61
72
|
ref.current = callback;
|
package/src/index.ts
CHANGED
|
@@ -15,8 +15,11 @@ export {
|
|
|
15
15
|
normalizeFileName,
|
|
16
16
|
emailRegex,
|
|
17
17
|
phoneRegex,
|
|
18
|
+
replaceWithRegex,
|
|
19
|
+
createMentionTemplateRegex,
|
|
18
20
|
} from './shared/regex';
|
|
19
21
|
export { BufferedRequest } from './shared/bufferedRequest';
|
|
22
|
+
export { default as replace } from './shared/replace';
|
|
20
23
|
|
|
21
24
|
export * from './hooks';
|
|
22
25
|
export * from './ui-format/groupChannel';
|
|
@@ -24,6 +27,7 @@ export * from './ui-format/common';
|
|
|
24
27
|
export * from './sendbird/channel';
|
|
25
28
|
export * from './sendbird/message';
|
|
26
29
|
export * from './sendbird/attrs';
|
|
30
|
+
export * from './sendbird/user';
|
|
27
31
|
|
|
28
32
|
export const NOOP: () => void = () => void 0;
|
|
29
33
|
export const ASYNC_NOOP = async () => void 0;
|
|
@@ -35,11 +39,14 @@ export const SBErrorCode = {
|
|
|
35
39
|
};
|
|
36
40
|
export const SBErrorMessage = {
|
|
37
41
|
ACL:
|
|
38
|
-
|
|
39
|
-
'
|
|
42
|
+
'Sendbird provides various access control options when using the Chat SDK.\n' +
|
|
43
|
+
'By default, the Allow retrieving user list attribute is turned on to facilitate creating sample apps.\n' +
|
|
44
|
+
'However, this may grant access to unwanted data or operations, leading to potential security concerns.\n' +
|
|
45
|
+
'To manage your access control settings, you can turn on or off each setting on Sendbird Dashboard.',
|
|
40
46
|
};
|
|
41
47
|
|
|
42
48
|
export type {
|
|
49
|
+
UserStruct,
|
|
43
50
|
FilterByValueType,
|
|
44
51
|
UnionToIntersection,
|
|
45
52
|
OmittedValues,
|
|
@@ -76,4 +83,9 @@ export type {
|
|
|
76
83
|
SendbirdUserMessageUpdateParams,
|
|
77
84
|
SendbirdFileMessageUpdateParams,
|
|
78
85
|
SendbirdUserUpdateParams,
|
|
86
|
+
SendbirdRestrictedUser,
|
|
87
|
+
SendbirdReaction,
|
|
88
|
+
SendbirdEmojiContainer,
|
|
89
|
+
SendbirdEmoji,
|
|
90
|
+
SendbirdEmojiCategory,
|
|
79
91
|
} from './types';
|
package/src/sendbird/channel.ts
CHANGED
|
@@ -12,20 +12,23 @@ export function isDifferentChannel<T extends SendbirdBaseChannel>(a?: T, b?: T):
|
|
|
12
12
|
return a.url !== b.url;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const
|
|
16
|
-
|
|
15
|
+
export const getGroupChannelChatAvailableState = (channel: SendbirdGroupChannel) => {
|
|
16
|
+
const frozen = channel.isFrozen && channel.myRole !== 'operator';
|
|
17
|
+
const muted = channel.myMutedState === 'muted';
|
|
18
|
+
const disabled = frozen || muted;
|
|
19
|
+
return { disabled, frozen, muted };
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
export const confirmAndMarkAsRead = async (channels: SendbirdBaseChannel[]) => {
|
|
20
23
|
channels
|
|
21
24
|
.filter((it): it is SendbirdGroupChannel => it.isGroupChannel() && it.unreadMessageCount > 0)
|
|
22
|
-
.forEach((it) => BufferedRequest.markAsRead.push(() => it.markAsRead()));
|
|
25
|
+
.forEach((it) => BufferedRequest.markAsRead.push(() => it.markAsRead(), it.url));
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
export const confirmAndMarkAsDelivered = async (channels: SendbirdBaseChannel[]) => {
|
|
26
29
|
channels
|
|
27
30
|
.filter((it): it is SendbirdGroupChannel => it.isGroupChannel() && it.unreadMessageCount > 0)
|
|
28
|
-
.forEach((it) => BufferedRequest.markAsDelivered.push(() => it.markAsDelivered()));
|
|
31
|
+
.forEach((it) => BufferedRequest.markAsDelivered.push(() => it.markAsDelivered(), it.url));
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
export function isDefaultCoverImage(coverUrl: string) {
|
|
@@ -43,3 +46,7 @@ export function getGroupChannels(channels: SendbirdChannel[]): SendbirdGroupChan
|
|
|
43
46
|
export function getOpenChannels(channels: SendbirdChannel[]): SendbirdOpenChannel[] {
|
|
44
47
|
return channels.filter((c): c is SendbirdOpenChannel => c.isOpenChannel());
|
|
45
48
|
}
|
|
49
|
+
|
|
50
|
+
export function getChannelUniqId(channel: SendbirdChannel) {
|
|
51
|
+
return channel.url;
|
|
52
|
+
}
|
package/src/sendbird/message.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
SendbirdBaseChannel,
|
|
2
3
|
SendbirdBaseMessage,
|
|
3
4
|
SendbirdDataPayload,
|
|
4
5
|
SendbirdFileMessage,
|
|
5
6
|
SendbirdMessage,
|
|
7
|
+
SendbirdReaction,
|
|
6
8
|
SendbirdSendableMessage,
|
|
7
9
|
} from '../types';
|
|
8
|
-
import {
|
|
10
|
+
import { getMessageTimeFormat } from '../ui-format/common';
|
|
9
11
|
|
|
10
12
|
export function isNewMessage(msg: SendbirdMessage, currentUserId?: string) {
|
|
11
13
|
const myMessage = isMyMessage(msg, currentUserId);
|
|
@@ -67,7 +69,7 @@ export function calcMessageGrouping(
|
|
|
67
69
|
if (!prev) return false;
|
|
68
70
|
if (curr.isAdminMessage()) return false;
|
|
69
71
|
if (!hasSameSender(curr, prev)) return false;
|
|
70
|
-
if (
|
|
72
|
+
if (getMessageTimeFormat(new Date(curr.createdAt)) !== getMessageTimeFormat(new Date(prev.createdAt))) return false;
|
|
71
73
|
return true;
|
|
72
74
|
};
|
|
73
75
|
|
|
@@ -76,7 +78,7 @@ export function calcMessageGrouping(
|
|
|
76
78
|
if (!next) return false;
|
|
77
79
|
if (curr.isAdminMessage()) return false;
|
|
78
80
|
if (!hasSameSender(curr, next)) return false;
|
|
79
|
-
if (
|
|
81
|
+
if (getMessageTimeFormat(new Date(curr.createdAt)) !== getMessageTimeFormat(new Date(next.createdAt))) return false;
|
|
80
82
|
return true;
|
|
81
83
|
};
|
|
82
84
|
|
|
@@ -110,3 +112,11 @@ export function isSendbirdNotification(dataPayload?: {
|
|
|
110
112
|
export function parseSendbirdNotification(dataPayload: RawSendbirdDataPayload): SendbirdDataPayload {
|
|
111
113
|
return typeof dataPayload.sendbird === 'string' ? JSON.parse(dataPayload.sendbird) : dataPayload.sendbird;
|
|
112
114
|
}
|
|
115
|
+
|
|
116
|
+
export function shouldRenderReaction(channel: SendbirdBaseChannel, reactionEnabled: boolean) {
|
|
117
|
+
return channel.isGroupChannel() && !channel.isBroadcast && !channel.isSuper && reactionEnabled;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getReactionCount(reaction: SendbirdReaction) {
|
|
121
|
+
return reaction.userIds.length;
|
|
122
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Role } from '@sendbird/chat';
|
|
2
|
+
|
|
3
|
+
import type { UserStruct } from '../types';
|
|
4
|
+
|
|
5
|
+
export function ifOperator<T>(role: Role, then: T): T | undefined;
|
|
6
|
+
export function ifOperator<T, V>(role: Role, then: T, or: V): T | V;
|
|
7
|
+
export function ifOperator(role: Role, then: unknown, or?: unknown) {
|
|
8
|
+
if (role === 'operator') return then;
|
|
9
|
+
return or;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ifMuted<T>(muted: boolean, then: T): T | undefined;
|
|
13
|
+
export function ifMuted<T, V>(muted: boolean, then: T, or: V): T | V;
|
|
14
|
+
export function ifMuted(muted: boolean, then: unknown, or?: unknown) {
|
|
15
|
+
if (muted) return then;
|
|
16
|
+
return or;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getUserUniqId<T extends UserStruct>(user: T) {
|
|
20
|
+
return user.userId;
|
|
21
|
+
}
|
|
@@ -5,10 +5,21 @@ let REQ_PER_TIMEOUT = 5;
|
|
|
5
5
|
let TIMEOUT_MILLS = 1000;
|
|
6
6
|
const SAFE_TIMEOUT_BUFFER = 100;
|
|
7
7
|
|
|
8
|
+
function generateRandomId() {
|
|
9
|
+
return Math.random().toString(16).slice(2);
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
export class BufferedRequest {
|
|
9
13
|
public static markAsRead = BufferedRequest.create();
|
|
10
14
|
public static markAsDelivered = BufferedRequest.create();
|
|
11
15
|
|
|
16
|
+
public static updateMarkAsReadOptions(reqPerTimeout: number, timeoutMills: number) {
|
|
17
|
+
BufferedRequest.markAsRead = BufferedRequest.create(reqPerTimeout, timeoutMills);
|
|
18
|
+
}
|
|
19
|
+
public static updateMarkAsDeliveredOptions(reqPerTimeout: number, timeoutMills: number) {
|
|
20
|
+
BufferedRequest.markAsDelivered = BufferedRequest.create(reqPerTimeout, timeoutMills);
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
public static get reqPerTimeout() {
|
|
13
24
|
return REQ_PER_TIMEOUT;
|
|
14
25
|
}
|
|
@@ -28,28 +39,33 @@ export class BufferedRequest {
|
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
public static create(reqPerTimeout = REQ_PER_TIMEOUT, timeoutMills = TIMEOUT_MILLS) {
|
|
31
|
-
const waitQueue
|
|
32
|
-
const nextQueue
|
|
42
|
+
const waitQueue = new Map<string, Func>();
|
|
43
|
+
const nextQueue = new Map<string, Func>();
|
|
33
44
|
|
|
34
45
|
let state: State = 'idle';
|
|
35
46
|
let timeout: NodeJS.Timeout | undefined;
|
|
36
47
|
|
|
37
48
|
return {
|
|
38
|
-
push(func: Func) {
|
|
39
|
-
waitQueue.
|
|
49
|
+
push(func: Func, lane?: string) {
|
|
50
|
+
waitQueue.set(lane ?? generateRandomId(), func);
|
|
40
51
|
this.invoke();
|
|
41
52
|
},
|
|
42
53
|
shift() {
|
|
43
|
-
if (nextQueue.
|
|
44
|
-
const nextRemains = Math.min(reqPerTimeout - nextQueue.
|
|
54
|
+
if (nextQueue.size < reqPerTimeout) {
|
|
55
|
+
const nextRemains = Math.min(reqPerTimeout - nextQueue.size, waitQueue.size);
|
|
56
|
+
const lanes = [...waitQueue.keys()];
|
|
45
57
|
for (let n = 0; n < nextRemains; n++) {
|
|
46
|
-
const
|
|
47
|
-
|
|
58
|
+
const lane = lanes[n];
|
|
59
|
+
const func = waitQueue.get(lane);
|
|
60
|
+
if (func) {
|
|
61
|
+
waitQueue.delete(lane);
|
|
62
|
+
nextQueue.set(lane, func);
|
|
63
|
+
}
|
|
48
64
|
}
|
|
49
65
|
}
|
|
50
66
|
},
|
|
51
67
|
handleIdle() {
|
|
52
|
-
if (0 < nextQueue.
|
|
68
|
+
if (0 < nextQueue.size) {
|
|
53
69
|
state = 'processing';
|
|
54
70
|
this.invoke();
|
|
55
71
|
}
|
|
@@ -59,15 +75,24 @@ export class BufferedRequest {
|
|
|
59
75
|
|
|
60
76
|
timeout = setTimeout(() => {
|
|
61
77
|
timeout = undefined;
|
|
62
|
-
if (0 < nextQueue.
|
|
78
|
+
if (0 < nextQueue.size || 0 < waitQueue.size) {
|
|
63
79
|
this.invoke();
|
|
64
80
|
} else {
|
|
65
81
|
state = 'idle';
|
|
66
82
|
}
|
|
67
83
|
}, timeoutMills + SAFE_TIMEOUT_BUFFER);
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
|
|
85
|
+
let index = 0;
|
|
86
|
+
const nextRequestBaseTimeout = timeoutMills / nextQueue.size;
|
|
87
|
+
nextQueue.forEach((func) => {
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
func();
|
|
90
|
+
// TODO: Add retry
|
|
91
|
+
//.catch(() => waitQueue.set(lane, func));
|
|
92
|
+
}, nextRequestBaseTimeout * index);
|
|
93
|
+
index++;
|
|
94
|
+
});
|
|
95
|
+
nextQueue.clear();
|
|
71
96
|
},
|
|
72
97
|
async invoke() {
|
|
73
98
|
this.shift();
|
package/src/shared/regex.ts
CHANGED
|
@@ -9,6 +9,8 @@ export const phoneRegex = /[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,7}/
|
|
|
9
9
|
export const emailRegex = /\S+@\S+\.\S+/;
|
|
10
10
|
export const newLineRegex = /\r\n|\r|\n/g;
|
|
11
11
|
|
|
12
|
+
export const createMentionTemplateRegex = (trigger: string) => new RegExp(`(${trigger}[{])(.*?)([}])`, 'g');
|
|
13
|
+
|
|
12
14
|
// const cases = [
|
|
13
15
|
// {
|
|
14
16
|
// type: 'urlStrict',
|
|
@@ -28,6 +30,39 @@ export const newLineRegex = /\r\n|\r|\n/g;
|
|
|
28
30
|
// },
|
|
29
31
|
// ];
|
|
30
32
|
|
|
33
|
+
export const replaceWithRegex = <T>(
|
|
34
|
+
text: string,
|
|
35
|
+
regex: RegExp,
|
|
36
|
+
replacer: (params: {
|
|
37
|
+
match: string;
|
|
38
|
+
groups: string[];
|
|
39
|
+
matchIndex: number | undefined;
|
|
40
|
+
index: number;
|
|
41
|
+
keyPrefix: string;
|
|
42
|
+
}) => T,
|
|
43
|
+
keyPrefix: string,
|
|
44
|
+
) => {
|
|
45
|
+
const matches = [...text.matchAll(regex)];
|
|
46
|
+
const founds = matches.map((value) => {
|
|
47
|
+
const text = value[0];
|
|
48
|
+
const start = value.index ?? 0;
|
|
49
|
+
const end = start + text.length;
|
|
50
|
+
return { text, start, end, groups: value, matchIndex: value.index };
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const items: Array<T | string> = [text];
|
|
54
|
+
let cursor = 0;
|
|
55
|
+
founds.forEach(({ text, start, end, groups, matchIndex }, index) => {
|
|
56
|
+
const restText = items.pop() as string;
|
|
57
|
+
const head = restText.slice(0, start - cursor);
|
|
58
|
+
const mid = replacer({ match: text, groups, matchIndex, index, keyPrefix });
|
|
59
|
+
const tail = restText.slice(end - cursor);
|
|
60
|
+
items.push(head, mid, tail);
|
|
61
|
+
cursor = end;
|
|
62
|
+
});
|
|
63
|
+
return items;
|
|
64
|
+
};
|
|
65
|
+
|
|
31
66
|
export const replaceUrlAsComponents = <T>(originText: string, replacer: (url: string) => T, strict?: boolean) => {
|
|
32
67
|
const matches = [...originText.matchAll(strict ? urlRegexStrict : urlRegexRough)];
|
|
33
68
|
const founds = matches.map((value) => {
|
package/src/types.ts
CHANGED
|
@@ -4,7 +4,16 @@
|
|
|
4
4
|
import type React from 'react';
|
|
5
5
|
|
|
6
6
|
import type SendbirdChat from '@sendbird/chat';
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
BaseChannel,
|
|
9
|
+
Emoji,
|
|
10
|
+
EmojiCategory,
|
|
11
|
+
EmojiContainer,
|
|
12
|
+
RestrictedUser,
|
|
13
|
+
SendbirdError as SBError,
|
|
14
|
+
User,
|
|
15
|
+
UserUpdateParams,
|
|
16
|
+
} from '@sendbird/chat';
|
|
8
17
|
import type {
|
|
9
18
|
GroupChannel,
|
|
10
19
|
GroupChannelCollection,
|
|
@@ -23,14 +32,13 @@ import type {
|
|
|
23
32
|
FileMessageCreateParams,
|
|
24
33
|
FileMessageUpdateParams,
|
|
25
34
|
PreviousMessageListQuery,
|
|
35
|
+
Reaction,
|
|
26
36
|
UserMessage,
|
|
27
37
|
UserMessageCreateParams,
|
|
28
38
|
UserMessageUpdateParams,
|
|
29
39
|
} from '@sendbird/chat/message';
|
|
30
40
|
import type { OpenChannel, OpenChannelModule } from '@sendbird/chat/openChannel';
|
|
31
41
|
|
|
32
|
-
import './';
|
|
33
|
-
|
|
34
42
|
export type FilterByValueType<T extends object, Type> = {
|
|
35
43
|
[K in keyof T as T[K] extends Type ? K : never]: T[K];
|
|
36
44
|
};
|
|
@@ -57,6 +65,10 @@ export type Optional<T> = T | undefined;
|
|
|
57
65
|
|
|
58
66
|
export type ContextValue<T extends React.Context<any>> = T extends React.Context<infer V> ? V : never;
|
|
59
67
|
|
|
68
|
+
export interface UserStruct {
|
|
69
|
+
userId: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
60
72
|
export type SendbirdChatSDK = SendbirdChat & ModuleNamespaces<[GroupChannelModule, OpenChannelModule]>;
|
|
61
73
|
export type SendbirdMessage = BaseMessage | FileMessage | UserMessage | AdminMessage | SendableMessage;
|
|
62
74
|
export type SendbirdChannel = BaseChannel | GroupChannel | OpenChannel;
|
|
@@ -73,11 +85,17 @@ export type SendbirdGroupChannelCreateParams = GroupChannelCreateParams;
|
|
|
73
85
|
export type SendbirdGroupChannelUpdateParams = GroupChannelUpdateParams;
|
|
74
86
|
export type SendbirdUserUpdateParams = UserUpdateParams;
|
|
75
87
|
export type SendbirdUser = User;
|
|
88
|
+
export type SendbirdRestrictedUser = RestrictedUser;
|
|
76
89
|
export type SendbirdMember = Member;
|
|
77
90
|
export type SendbirdGroupChannel = GroupChannel;
|
|
78
91
|
export type SendbirdBaseChannel = BaseChannel;
|
|
79
92
|
export type SendbirdOpenChannel = OpenChannel;
|
|
80
93
|
|
|
94
|
+
export type SendbirdReaction = Reaction;
|
|
95
|
+
export type SendbirdEmoji = Emoji;
|
|
96
|
+
export type SendbirdEmojiCategory = EmojiCategory;
|
|
97
|
+
export type SendbirdEmojiContainer = EmojiContainer;
|
|
98
|
+
|
|
81
99
|
export type SendbirdGroupChannelCollection = GroupChannelCollection;
|
|
82
100
|
export type SendbirdGroupChannelListQuery = GroupChannelListQuery;
|
|
83
101
|
export type SendbirdMessageCollection = MessageCollection;
|
package/src/ui-format/common.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Locale } from 'date-fns';
|
|
2
|
-
import format from 'date-fns
|
|
2
|
+
import { format, isThisYear } from 'date-fns';
|
|
3
3
|
|
|
4
4
|
type TruncateMode = 'head' | 'mid' | 'tail';
|
|
5
5
|
type TruncateOption = { mode: TruncateMode; maxLen: number; separator: string };
|
|
@@ -38,15 +38,16 @@ export const truncate = (str: string, opts: Partial<TruncateOption> = defaultOpt
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Count truncate util
|
|
42
42
|
* If count exceed the limit, it comes in the form of "MAX+"
|
|
43
43
|
*
|
|
44
44
|
* @param {number} count
|
|
45
45
|
* @param {number} MAX default 99
|
|
46
|
+
* @param {string} MAX_SUFFIX default +
|
|
46
47
|
* @returns {string}
|
|
47
48
|
* */
|
|
48
|
-
export const
|
|
49
|
-
if (count >= MAX) return `${MAX}
|
|
49
|
+
export const truncatedCount = (count: number, MAX = 99, MAX_SUFFIX = '+') => {
|
|
50
|
+
if (count >= MAX) return `${MAX}${MAX_SUFFIX}`;
|
|
50
51
|
return `${count}`;
|
|
51
52
|
};
|
|
52
53
|
|
|
@@ -57,8 +58,9 @@ export const truncatedBadgeCount = (count: number, MAX = 99) => {
|
|
|
57
58
|
* @param {Locale} [locale]
|
|
58
59
|
* @returns {string}
|
|
59
60
|
* */
|
|
60
|
-
export const
|
|
61
|
-
return format(date, '
|
|
61
|
+
export const getDateSeparatorFormat = (date: Date, locale?: Locale): string => {
|
|
62
|
+
if (isThisYear(date)) return format(date, 'MMM dd, yyyy', { locale });
|
|
63
|
+
return format(date, 'E, MMM dd', { locale });
|
|
62
64
|
};
|
|
63
65
|
|
|
64
66
|
/**
|
|
@@ -68,6 +70,6 @@ export const dateSeparator = (date: Date, locale?: Locale): string => {
|
|
|
68
70
|
* @param {Locale} [locale]
|
|
69
71
|
* @returns {string}
|
|
70
72
|
* */
|
|
71
|
-
export const
|
|
73
|
+
export const getMessageTimeFormat = (date: Date, locale?: Locale): string => {
|
|
72
74
|
return format(date, 'p', { locale });
|
|
73
75
|
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { Locale } from 'date-fns';
|
|
2
|
-
import format from 'date-fns
|
|
3
|
-
import isToday from 'date-fns/isToday';
|
|
4
|
-
import isYesterday from 'date-fns/isYesterday';
|
|
2
|
+
import { format, isThisYear, isToday, isYesterday } from 'date-fns';
|
|
5
3
|
|
|
6
4
|
import type { SendbirdGroupChannel } from '../types';
|
|
7
5
|
import { truncate } from './common';
|
|
@@ -23,9 +21,12 @@ export const getGroupChannelTitle = (
|
|
|
23
21
|
|
|
24
22
|
export const getGroupChannelPreviewTime = (channel: SendbirdGroupChannel, locale?: Locale) => {
|
|
25
23
|
const timestamp = channel.lastMessage?.createdAt || channel.joinedAt * 1000 || channel.createdAt;
|
|
24
|
+
|
|
26
25
|
if (isToday(timestamp)) return format(timestamp, 'p', { locale });
|
|
27
26
|
if (isYesterday(timestamp)) return 'Yesterday';
|
|
28
|
-
return format(timestamp, 'MMM dd', { locale });
|
|
27
|
+
if (isThisYear(timestamp)) return format(timestamp, 'MMM dd', { locale });
|
|
28
|
+
|
|
29
|
+
return format(timestamp, 'yyyy/MM/dd', { locale });
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
export const getGroupChannelLastMessage = (channel: SendbirdGroupChannel, EMPTY_MESSAGE = '', MAX_LEN = 15) => {
|