Skip to content

Commit ac15bf5

Browse files
authored
refactor: Migrate the SendbirdProvider and pubSub to TS (#437)
* Migrate `Sendbird.js` and `pubSub` files into the TypeScript [UIKIT-3187](https://sendbird.atlassian.net/browse/UIKIT-3187)
1 parent 89ad7dc commit ac15bf5

23 files changed

+174
-170
lines changed

src/hooks/VoicePlayer/dux/actionTypes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ObjectValues } from "../../../utils/typeHelpers/objectValues";
2+
13
export const actionTypes = {
24
INITIALIZE_AUDIO_UNIT: 'INITIALIZE_AUDIO_UNIT',
35
SET_CURRENT_PLAYER: 'SET_CURRENT_PLAYER',
@@ -6,7 +8,6 @@ export const actionTypes = {
68
ON_CURRENT_TIME_UPDATE: 'ON_CURRENT_TIME_UPDATE',
79
} as const;
810

9-
type ObjectValues<T> = T[keyof T];
1011
export type VoicePlayerActionType = ObjectValues<typeof actionTypes>;
1112

1213
export const INITIALIZE_AUDIO_UNIT: VoicePlayerActionType = 'INITIALIZE_AUDIO_UNIT';
Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
// Logger, pretty much explains it
22
// in SendbirdProvider
3+
4+
import { ObjectValues } from "../../utils/typeHelpers/objectValues";
5+
36
// const [logger, setLogger] = useState(LoggerFactory(logLevel));
47
export const LOG_LEVELS = {
58
DEBUG: 'debug',
69
WARNING: 'warning',
710
ERROR: 'error',
811
INFO: 'info',
912
ALL: 'all',
10-
};
13+
} as const;
14+
export type LogLevel = ObjectValues<typeof LOG_LEVELS>;
1115

12-
const colorLog = (level) => {
16+
const colorLog = (level: LogLevel): string => {
1317
switch (level) {
1418
case LOG_LEVELS.WARNING:
1519
return ('color: Orange');
@@ -20,29 +24,45 @@ const colorLog = (level) => {
2024
}
2125
};
2226

27+
interface PrintLogProps {
28+
level: LogLevel;
29+
title: string;
30+
description?: string;
31+
}
2332
export const printLog = ({
2433
level,
2534
title,
2635
description = '',
27-
}) => {
36+
}: PrintLogProps): void => {
2837
// eslint-disable-next-line no-console
2938
console.log(
3039
`%c SendbirdUIKit | ${level} | ${new Date().toISOString()} | ${title} ${description && '|'}`, colorLog(level),
3140
description,
3241
);
3342
};
3443

35-
export const getDefaultLogger = () => ({
36-
info: () => {},
37-
error: () => {},
38-
warning: () => {},
44+
type LoggerLogType = (title?: string, description?: string) => void;
45+
interface LoggerInterface {
46+
info: LoggerLogType;
47+
error: LoggerLogType;
48+
warning: LoggerLogType;
49+
}
50+
51+
const noop = () => {/* noop */};
52+
export const getDefaultLogger = (): LoggerInterface => ({
53+
info: noop,
54+
error: noop,
55+
warning: noop,
3956
});
4057

41-
export const LoggerFactory = (lvl, customInterface) => {
58+
export const LoggerFactory = (
59+
lvl: LogLevel,
60+
customInterface: () => void,
61+
): LoggerInterface => {
4262
const logInterface = customInterface || printLog;
43-
const lvlArray = Array.isArray(lvl) ? lvl : [lvl];
63+
const lvlArray: Array<LogLevel> = Array.isArray(lvl) ? lvl : [lvl];
4464

45-
const applyLog = (lgLvl) => (title, description) => logInterface({
65+
const applyLog = (lgLvl: LogLevel) => (title?: string, description?: string) => logInterface({
4666
level: lgLvl,
4767
title,
4868
description,
@@ -83,3 +103,5 @@ export const LoggerFactory = (lvl, customInterface) => {
83103
}, getDefaultLogger());
84104
return logger;
85105
};
106+
107+
// TODO: Make this to hook, useLogger
Lines changed: 88 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import './index.scss';
22
import './__experimental__typography.scss';
33

44
import React, { useEffect, useReducer, useState } from 'react';
5-
import PropTypes from 'prop-types';
5+
import { User } from '@sendbird/chat';
66

77
import { SendbirdSdkContext } from './SendbirdSdkContext';
88
import { handleConnection } from './dux/sdk/thunks';
@@ -26,39 +26,93 @@ import { MediaQueryProvider } from './MediaQueryContext';
2626
import getStringSet from '../ui/Label/stringSet';
2727
import { VOICE_RECORDER_DEFAULT_MAX, VOICE_RECORDER_DEFAULT_MIN } from '../utils/consts';
2828

29-
export default function Sendbird(props) {
30-
const {
31-
userId,
32-
dateLocale,
33-
appId,
34-
accessToken,
35-
configureSession,
36-
// mediaQueryBreakPoint,
37-
customApiHost,
38-
customWebSocketHost,
39-
children,
40-
disableUserProfile,
41-
disableMarkAsDelivered,
42-
renderUserProfile,
43-
onUserProfileMessage,
44-
allowProfileEdit,
45-
theme,
46-
nickname,
47-
profileUrl,
48-
userListQuery,
49-
config = {},
50-
colorSet,
51-
stringSet,
52-
imageCompression,
53-
isReactionEnabled,
54-
isMentionEnabled,
55-
isVoiceMessageEnabled,
56-
voiceRecord,
57-
isTypingIndicatorEnabledOnChannelList,
58-
isMessageReceiptStatusEnabledOnChannelList,
59-
replyType,
60-
} = props;
29+
export type UserListQueryType = {
30+
hasNext?: boolean;
31+
next: () => Promise<Array<User>>;
32+
}
33+
34+
interface VoiceRecordOptions {
35+
maxRecordingTime?: number;
36+
minRecordingTime?: number;
37+
}
38+
39+
export interface ImageCompressionOptions {
40+
compressionRate?: number;
41+
resizingWidth?: number | string;
42+
resizingHeight?: number | string;
43+
}
6144

45+
export interface SendbirdConfig {
46+
logLevel?: string | Array<string>;
47+
pubSub?: () => void;// TODO: Define pubSub type and apply it here
48+
userMention?: {
49+
maxMentionCount?: number;
50+
maxSuggestionCount?: number;
51+
};
52+
isREMUnitEnabled?: boolean;
53+
}
54+
55+
export interface SendbirdProviderProps {
56+
appId: string;
57+
userId: string;
58+
children: React.ReactElement;
59+
accessToken?: string;
60+
customApiHost?: string;
61+
customWebSocketHost?: string;
62+
configureSession?: () => void;
63+
theme?: 'light' | 'dark';
64+
config?: SendbirdConfig;
65+
nickname?: string;
66+
colorSet?: Record<string, string>;
67+
stringSet?: Record<string, string>;
68+
replyType?: 'NONE' | 'QUOTE_REPLY' | 'THREAD';
69+
dateLocale?: Locale;
70+
profileUrl?: string;
71+
voiceRecord?: VoiceRecordOptions;
72+
userListQuery?: UserListQueryType;
73+
imageCompression?: ImageCompressionOptions;
74+
allowProfileEdit?: boolean;
75+
isMentionEnabled?: boolean;
76+
isReactionEnabled?: boolean;
77+
disableUserProfile?: boolean;
78+
isVoiceMessageEnabled?: boolean;
79+
disableMarkAsDelivered?: boolean;
80+
isTypingIndicatorEnabledOnChannelList?: boolean;
81+
isMessageReceiptStatusEnabledOnChannelList?: boolean;
82+
renderUserProfile?: () => React.ReactElement;
83+
onUserProfileMessage?: () => void;
84+
}
85+
86+
const Sendbird = ({
87+
appId,
88+
userId,
89+
children,
90+
accessToken = '',
91+
customApiHost = '',
92+
customWebSocketHost = '',
93+
configureSession = null,
94+
theme = 'light',
95+
config = {},
96+
nickname = '',
97+
colorSet = null,
98+
stringSet = null,
99+
replyType = 'NONE',
100+
dateLocale = null,
101+
profileUrl = '',
102+
voiceRecord = { maxRecordingTime: VOICE_RECORDER_DEFAULT_MAX, minRecordingTime: VOICE_RECORDER_DEFAULT_MIN },
103+
userListQuery = null,
104+
imageCompression = {},
105+
allowProfileEdit = false,
106+
isMentionEnabled = false,
107+
isReactionEnabled = true,
108+
disableUserProfile = false,
109+
isVoiceMessageEnabled = true,
110+
disableMarkAsDelivered = false,
111+
isTypingIndicatorEnabledOnChannelList = false,
112+
isMessageReceiptStatusEnabledOnChannelList = false,
113+
renderUserProfile = null,
114+
onUserProfileMessage = null,
115+
}: SendbirdProviderProps): React.ReactElement => {
62116
const mediaQueryBreakPoint = false;
63117

64118
const {
@@ -223,98 +277,4 @@ export default function Sendbird(props) {
223277
);
224278
}
225279

226-
Sendbird.propTypes = {
227-
userId: PropTypes.string.isRequired,
228-
appId: PropTypes.string.isRequired,
229-
accessToken: PropTypes.string,
230-
customApiHost: PropTypes.string,
231-
customWebSocketHost: PropTypes.string,
232-
// mediaQueryBreakPoint: PropTypes.string,
233-
configureSession: PropTypes.func,
234-
children: PropTypes.oneOfType([
235-
PropTypes.element,
236-
PropTypes.arrayOf(PropTypes.element),
237-
PropTypes.any,
238-
]).isRequired,
239-
theme: PropTypes.string,
240-
nickname: PropTypes.string,
241-
dateLocale: PropTypes.shape({}),
242-
profileUrl: PropTypes.string,
243-
disableUserProfile: PropTypes.bool,
244-
disableMarkAsDelivered: PropTypes.bool,
245-
renderUserProfile: PropTypes.func,
246-
onUserProfileMessage: PropTypes.func,
247-
allowProfileEdit: PropTypes.bool,
248-
userListQuery: PropTypes.func,
249-
config: PropTypes.shape({
250-
// None Error Warning Info 'All/Debug'
251-
logLevel: PropTypes.oneOfType([
252-
PropTypes.string,
253-
PropTypes.arrayOf(PropTypes.string),
254-
]),
255-
pubSub: PropTypes.shape({
256-
subscribe: PropTypes.func,
257-
publish: PropTypes.func,
258-
}),
259-
userMention: PropTypes.shape({
260-
maxMentionCount: PropTypes.number,
261-
maxSuggestionCount: PropTypes.number,
262-
}),
263-
isREMUnitEnabled: PropTypes.bool,
264-
}),
265-
stringSet: PropTypes.objectOf(PropTypes.string),
266-
colorSet: PropTypes.objectOf(PropTypes.string),
267-
isReactionEnabled: PropTypes.bool,
268-
isMentionEnabled: PropTypes.bool,
269-
isVoiceMessageEnabled: PropTypes.bool,
270-
voiceRecord: PropTypes.shape({
271-
maxRecordingTime: PropTypes.number,
272-
minRecordingTime: PropTypes.number,
273-
}),
274-
imageCompression: PropTypes.shape({
275-
compressionRate: PropTypes.number,
276-
resizingWidth: PropTypes.oneOfType([
277-
PropTypes.number,
278-
PropTypes.string,
279-
]),
280-
resizingHeight: PropTypes.oneOfType([
281-
PropTypes.number,
282-
PropTypes.string,
283-
]),
284-
}),
285-
isTypingIndicatorEnabledOnChannelList: PropTypes.bool,
286-
isMessageReceiptStatusEnabledOnChannelList: PropTypes.bool,
287-
replyType: PropTypes.oneOf(['NONE', 'QUOTE_REPLY', 'THREAD']),
288-
};
289-
290-
Sendbird.defaultProps = {
291-
accessToken: '',
292-
customApiHost: null,
293-
customWebSocketHost: null,
294-
configureSession: null,
295-
theme: 'light',
296-
// mediaQueryBreakPoint: null,
297-
nickname: '',
298-
dateLocale: null,
299-
profileUrl: '',
300-
disableUserProfile: false,
301-
disableMarkAsDelivered: false,
302-
renderUserProfile: null,
303-
onUserProfileMessage: null,
304-
allowProfileEdit: false,
305-
userListQuery: null,
306-
config: {},
307-
stringSet: null,
308-
colorSet: null,
309-
imageCompression: {},
310-
isReactionEnabled: true,
311-
isMentionEnabled: false,
312-
isVoiceMessageEnabled: true,
313-
voiceRecord: {
314-
maxRecordingTime: VOICE_RECORDER_DEFAULT_MAX,
315-
minRecordingTime: VOICE_RECORDER_DEFAULT_MIN,
316-
},
317-
isTypingIndicatorEnabledOnChannelList: false,
318-
isMessageReceiptStatusEnabledOnChannelList: false,
319-
replyType: 'NONE',
320-
};
280+
export default Sendbird;
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import React from 'react';
22

3-
export const SendbirdSdkContext = React.createContext();
3+
type ContextAwareComponentType = {
4+
(props: any): JSX.Element;
5+
displayName: string;
6+
}
47

5-
const withSendbirdContext = (OriginalComponent, mapStoreToProps) => {
8+
export const SendbirdSdkContext = React.createContext({});
9+
10+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
11+
const withSendbirdContext = (OriginalComponent: any, mapStoreToProps: Record<string, any>): ContextAwareComponentType => {
612
const ContextAwareComponent = (props) => (
713
<SendbirdSdkContext.Consumer>
814
{(context) => {
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
// for example, if customer sends a message from their custom component
44
// without pubsub,we would not be able to listen to it
55
// in our ChannelList or Conversation
6-
export default () => {
6+
7+
interface PubSubTypes {
8+
__getTopics: () => Record<string, string>;
9+
subscribe: (topic: string, listener: unknown) => { remove: () => void };
10+
publish: (topic: string, info: unknown) => void;
11+
}
12+
13+
const pubSubFactory = (): PubSubTypes => {
714
const topics = {};
815
const hOP = topics.hasOwnProperty;
916

@@ -34,3 +41,5 @@ export default () => {
3441
},
3542
};
3643
};
44+
45+
export default pubSubFactory;

src/lib/pubSub/topics.js

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)