@sendbird/uikit-react-native-foundation 2.5.0 → 3.0.0-rc.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.
Files changed (112) hide show
  1. package/README.md +4 -0
  2. package/lib/commonjs/components/ImageWithPlaceholder/index.js +7 -1
  3. package/lib/commonjs/components/ImageWithPlaceholder/index.js.map +1 -1
  4. package/lib/commonjs/components/RegexText/index.js.map +1 -1
  5. package/lib/commonjs/index.js +8 -8
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/types.js.map +1 -1
  8. package/lib/commonjs/ui/Avatar/AvatarGroup.js +1 -1
  9. package/lib/commonjs/ui/Avatar/AvatarGroup.js.map +1 -1
  10. package/lib/commonjs/ui/GroupChannelMessage/Message.admin.js +37 -0
  11. package/lib/commonjs/ui/GroupChannelMessage/Message.admin.js.map +1 -0
  12. package/lib/commonjs/ui/GroupChannelMessage/Message.file.image.js +54 -0
  13. package/lib/commonjs/ui/GroupChannelMessage/Message.file.image.js.map +1 -0
  14. package/lib/commonjs/ui/GroupChannelMessage/Message.file.js +80 -0
  15. package/lib/commonjs/ui/GroupChannelMessage/Message.file.js.map +1 -0
  16. package/lib/commonjs/ui/GroupChannelMessage/Message.file.video.js +120 -0
  17. package/lib/commonjs/ui/GroupChannelMessage/Message.file.video.js.map +1 -0
  18. package/lib/commonjs/ui/GroupChannelMessage/Message.unknown.js +54 -0
  19. package/lib/commonjs/ui/GroupChannelMessage/Message.unknown.js.map +1 -0
  20. package/lib/commonjs/ui/GroupChannelMessage/Message.user.js +44 -0
  21. package/lib/commonjs/ui/GroupChannelMessage/Message.user.js.map +1 -0
  22. package/lib/commonjs/ui/GroupChannelMessage/Message.user.og.js +59 -0
  23. package/lib/commonjs/ui/GroupChannelMessage/Message.user.og.js.map +1 -0
  24. package/lib/commonjs/ui/GroupChannelMessage/MessageBubbleWithText.js +74 -0
  25. package/lib/commonjs/ui/GroupChannelMessage/MessageBubbleWithText.js.map +1 -0
  26. package/lib/commonjs/ui/GroupChannelMessage/MessageContainer.js +110 -0
  27. package/lib/commonjs/ui/GroupChannelMessage/MessageContainer.js.map +1 -0
  28. package/lib/commonjs/ui/GroupChannelMessage/MessageOpenGraph.js +91 -0
  29. package/lib/commonjs/ui/GroupChannelMessage/MessageOpenGraph.js.map +1 -0
  30. package/lib/commonjs/ui/GroupChannelMessage/index.js +26 -0
  31. package/lib/commonjs/ui/GroupChannelMessage/index.js.map +1 -0
  32. package/lib/commonjs/ui/OpenChannelMessage/Message.user.js +1 -1
  33. package/lib/commonjs/ui/OpenChannelMessage/Message.user.js.map +1 -1
  34. package/lib/commonjs/ui/OpenChannelMessage/Message.user.og.js +5 -2
  35. package/lib/commonjs/ui/OpenChannelMessage/Message.user.og.js.map +1 -1
  36. package/lib/commonjs/ui/OpenChannelMessage/index.js.map +1 -1
  37. package/lib/module/components/ImageWithPlaceholder/index.js +7 -1
  38. package/lib/module/components/ImageWithPlaceholder/index.js.map +1 -1
  39. package/lib/module/components/RegexText/index.js.map +1 -1
  40. package/lib/module/index.js +2 -2
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/types.js.map +1 -1
  43. package/lib/module/ui/Avatar/AvatarGroup.js +1 -1
  44. package/lib/module/ui/Avatar/AvatarGroup.js.map +1 -1
  45. package/lib/module/ui/GroupChannelMessage/Message.admin.js +29 -0
  46. package/lib/module/ui/GroupChannelMessage/Message.admin.js.map +1 -0
  47. package/lib/module/ui/GroupChannelMessage/Message.file.image.js +46 -0
  48. package/lib/module/ui/GroupChannelMessage/Message.file.image.js.map +1 -0
  49. package/lib/module/ui/GroupChannelMessage/Message.file.js +72 -0
  50. package/lib/module/ui/GroupChannelMessage/Message.file.js.map +1 -0
  51. package/lib/module/ui/GroupChannelMessage/Message.file.video.js +110 -0
  52. package/lib/module/ui/GroupChannelMessage/Message.file.video.js.map +1 -0
  53. package/lib/module/ui/GroupChannelMessage/Message.unknown.js +46 -0
  54. package/lib/module/ui/GroupChannelMessage/Message.unknown.js.map +1 -0
  55. package/lib/module/ui/GroupChannelMessage/Message.user.js +36 -0
  56. package/lib/module/ui/GroupChannelMessage/Message.user.js.map +1 -0
  57. package/lib/module/ui/GroupChannelMessage/Message.user.og.js +51 -0
  58. package/lib/module/ui/GroupChannelMessage/Message.user.og.js.map +1 -0
  59. package/lib/module/ui/GroupChannelMessage/MessageBubbleWithText.js +66 -0
  60. package/lib/module/ui/GroupChannelMessage/MessageBubbleWithText.js.map +1 -0
  61. package/lib/module/ui/GroupChannelMessage/MessageContainer.js +102 -0
  62. package/lib/module/ui/GroupChannelMessage/MessageContainer.js.map +1 -0
  63. package/lib/module/ui/GroupChannelMessage/MessageOpenGraph.js +83 -0
  64. package/lib/module/ui/GroupChannelMessage/MessageOpenGraph.js.map +1 -0
  65. package/lib/module/ui/GroupChannelMessage/index.js +18 -0
  66. package/lib/module/ui/GroupChannelMessage/index.js.map +1 -0
  67. package/lib/module/ui/OpenChannelMessage/Message.user.js +1 -1
  68. package/lib/module/ui/OpenChannelMessage/Message.user.js.map +1 -1
  69. package/lib/module/ui/OpenChannelMessage/Message.user.og.js +5 -2
  70. package/lib/module/ui/OpenChannelMessage/Message.user.og.js.map +1 -1
  71. package/lib/module/ui/OpenChannelMessage/index.js.map +1 -1
  72. package/lib/typescript/src/components/RegexText/index.d.ts +2 -2
  73. package/lib/typescript/src/index.d.ts +4 -2
  74. package/lib/typescript/src/types.d.ts +1 -9
  75. package/lib/typescript/src/ui/GroupChannelMessage/Message.admin.d.ts +4 -0
  76. package/lib/typescript/src/ui/GroupChannelMessage/Message.file.d.ts +5 -0
  77. package/lib/typescript/src/ui/GroupChannelMessage/Message.file.image.d.ts +4 -0
  78. package/lib/typescript/src/ui/GroupChannelMessage/Message.file.video.d.ts +9 -0
  79. package/lib/typescript/src/ui/GroupChannelMessage/Message.unknown.d.ts +4 -0
  80. package/lib/typescript/src/ui/GroupChannelMessage/Message.user.d.ts +9 -0
  81. package/lib/typescript/src/ui/GroupChannelMessage/Message.user.og.d.ts +9 -0
  82. package/lib/typescript/src/ui/GroupChannelMessage/MessageBubbleWithText.d.ts +10 -0
  83. package/lib/typescript/src/ui/GroupChannelMessage/MessageContainer.d.ts +9 -0
  84. package/lib/typescript/src/ui/GroupChannelMessage/MessageOpenGraph.d.ts +8 -0
  85. package/lib/typescript/src/ui/GroupChannelMessage/index.d.ts +191 -0
  86. package/lib/typescript/src/ui/OpenChannelMessage/index.d.ts +7 -7
  87. package/package.json +5 -6
  88. package/src/components/ImageWithPlaceholder/index.tsx +3 -2
  89. package/src/components/RegexText/index.tsx +2 -2
  90. package/src/index.ts +5 -2
  91. package/src/types.ts +1 -11
  92. package/src/ui/Avatar/AvatarGroup.tsx +1 -1
  93. package/src/ui/GroupChannelMessage/Message.admin.tsx +34 -0
  94. package/src/ui/GroupChannelMessage/Message.file.image.tsx +45 -0
  95. package/src/ui/GroupChannelMessage/Message.file.tsx +70 -0
  96. package/src/ui/GroupChannelMessage/Message.file.video.tsx +106 -0
  97. package/src/ui/GroupChannelMessage/Message.unknown.tsx +47 -0
  98. package/src/ui/GroupChannelMessage/Message.user.og.tsx +62 -0
  99. package/src/ui/GroupChannelMessage/Message.user.tsx +49 -0
  100. package/src/ui/GroupChannelMessage/MessageBubbleWithText.tsx +80 -0
  101. package/src/ui/GroupChannelMessage/MessageContainer.tsx +106 -0
  102. package/src/ui/GroupChannelMessage/MessageOpenGraph.tsx +84 -0
  103. package/src/ui/GroupChannelMessage/index.ts +48 -0
  104. package/src/ui/OpenChannelMessage/Message.user.og.tsx +6 -2
  105. package/src/ui/OpenChannelMessage/Message.user.tsx +1 -1
  106. package/src/ui/OpenChannelMessage/index.ts +1 -1
  107. package/lib/commonjs/components/URLParsedText/index.js +0 -46
  108. package/lib/commonjs/components/URLParsedText/index.js.map +0 -1
  109. package/lib/module/components/URLParsedText/index.js +0 -38
  110. package/lib/module/components/URLParsedText/index.js.map +0 -1
  111. package/lib/typescript/src/components/URLParsedText/index.d.ts +0 -8
  112. package/src/components/URLParsedText/index.tsx +0 -50
package/src/index.ts CHANGED
@@ -10,10 +10,10 @@ export { default as ImageWithPlaceholder } from './components/ImageWithPlacehold
10
10
  export { default as Modal } from './components/Modal';
11
11
  export { default as PressBox } from './components/PressBox';
12
12
  export { default as RegexText } from './components/RegexText';
13
+ export type { RegexTextPattern } from './components/RegexText';
13
14
  export { default as Switch } from './components/Switch';
14
15
  export { default as Text } from './components/Text';
15
16
  export { default as TextInput } from './components/TextInput';
16
- export { default as URLParsedText } from './components/URLParsedText';
17
17
 
18
18
  /** UI **/
19
19
  export { default as ActionMenu } from './ui/ActionMenu';
@@ -24,11 +24,14 @@ export { default as BottomSheet } from './ui/BottomSheet';
24
24
  export { default as Button } from './ui/Button';
25
25
  export { default as ChannelFrozenBanner } from './ui/ChannelFrozenBanner';
26
26
  export { DialogProvider, useActionMenu, useAlert, usePrompt, useBottomSheet } from './ui/Dialog';
27
- export { default as GroupChannelPreview } from './ui/GroupChannelPreview';
28
27
  export { default as Header } from './ui/Header';
29
28
  export { default as LoadingSpinner } from './ui/LoadingSpinner';
30
29
  export { default as MenuBar } from './ui/MenuBar';
31
30
  export type { MenuBarProps } from './ui/MenuBar';
31
+ export { default as GroupChannelMessage } from './ui/GroupChannelMessage';
32
+ export type { GroupChannelMessageProps } from './ui/GroupChannelMessage';
33
+ export { default as GroupChannelPreview } from './ui/GroupChannelPreview';
34
+
32
35
  export { default as OpenChannelMessage } from './ui/OpenChannelMessage';
33
36
  export type { OpenChannelMessageProps } from './ui/OpenChannelMessage';
34
37
  export { default as OpenChannelPreview } from './ui/OpenChannelPreview';
package/src/types.ts CHANGED
@@ -43,8 +43,7 @@ export type Component =
43
43
  | 'ProfileCard'
44
44
  | 'Reaction'
45
45
  | 'OpenChannelMessage'
46
- | 'OpenChannelPreview'
47
- | 'Message';
46
+ | 'OpenChannelPreview';
48
47
 
49
48
  export type GetColorTree<
50
49
  Tree extends {
@@ -75,8 +74,6 @@ export type ComponentColorTree = GetColorTree<{
75
74
  Reaction: 'default' | 'rounded';
76
75
  OpenChannelMessage: 'default';
77
76
  OpenChannelPreview: 'default';
78
- /** @deprecated **/
79
- Message: 'incoming' | 'outgoing';
80
77
  };
81
78
  State: {
82
79
  Header: 'none';
@@ -92,8 +89,6 @@ export type ComponentColorTree = GetColorTree<{
92
89
  Reaction: 'enabled' | 'selected';
93
90
  OpenChannelMessage: 'enabled' | 'pressed';
94
91
  OpenChannelPreview: 'none';
95
- /** @deprecated **/
96
- Message: 'enabled' | 'pressed';
97
92
  };
98
93
  ColorPart: {
99
94
  Header: 'background' | 'borderBottom';
@@ -133,9 +128,6 @@ export type ComponentColorTree = GetColorTree<{
133
128
  | 'background'
134
129
  | 'coverBackground'
135
130
  | 'separator';
136
-
137
- /** @deprecated **/
138
- Message: 'textMsg' | 'textEdited' | 'textSenderName' | 'textTime' | 'background';
139
131
  };
140
132
  }>;
141
133
  export type ComponentColors<T extends Component> = {
@@ -183,8 +175,6 @@ export interface UIKitColors {
183
175
  reaction: ComponentColors<'Reaction'>;
184
176
  openChannelMessage: ComponentColors<'OpenChannelMessage'>;
185
177
  openChannelPreview: ComponentColors<'OpenChannelPreview'>;
186
- /** @deprecated Please use `colors.ui.groupChannelMessage` **/
187
- message: ComponentColors<'Message'>;
188
178
  };
189
179
  }
190
180
 
@@ -71,7 +71,7 @@ const getWidthPoint = (idx: number, total: number) => {
71
71
  return 0.5;
72
72
  };
73
73
  const getTopPoint = (idx: number, total: number) => {
74
- if (total === 2) return -0.025;
74
+ if (total === 2) return 0;
75
75
  if (total === 3 && idx === 0) return -0.025;
76
76
  if (total === 3 && idx !== 0) return 0.525;
77
77
  if (idx === 0 || idx === 1) return -0.025;
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+
3
+ import type { SendbirdAdminMessage } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import Text from '../../components/Text';
7
+ import createStyleSheet from '../../styles/createStyleSheet';
8
+ import useUIKitTheme from '../../theme/useUIKitTheme';
9
+ import type { GroupChannelMessageProps } from './index';
10
+
11
+ const AdminMessage = (props: GroupChannelMessageProps<SendbirdAdminMessage>) => {
12
+ const { colors } = useUIKitTheme();
13
+
14
+ return (
15
+ <Box style={styles.container}>
16
+ <Text caption2 color={colors.onBackground02} style={styles.text}>
17
+ {props.message.message}
18
+ </Text>
19
+ </Box>
20
+ );
21
+ };
22
+
23
+ const styles = createStyleSheet({
24
+ container: {
25
+ width: 300,
26
+ alignSelf: 'center',
27
+ alignItems: 'center',
28
+ },
29
+ text: {
30
+ textAlign: 'center',
31
+ },
32
+ });
33
+
34
+ export default AdminMessage;
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+
3
+ import type { SendbirdFileMessage } from '@sendbird/uikit-utils';
4
+ import { getAvailableUriFromFileMessage } from '@sendbird/uikit-utils';
5
+
6
+ import Box from '../../components/Box';
7
+ import ImageWithPlaceholder from '../../components/ImageWithPlaceholder';
8
+ import PressBox from '../../components/PressBox';
9
+ import createStyleSheet from '../../styles/createStyleSheet';
10
+ import useUIKitTheme from '../../theme/useUIKitTheme';
11
+ import MessageContainer from './MessageContainer';
12
+ import type { GroupChannelMessageProps } from './index';
13
+
14
+ const ImageFileMessage = (props: GroupChannelMessageProps<SendbirdFileMessage>) => {
15
+ const { onPress, onLongPress, variant = 'incoming' } = props;
16
+
17
+ const { colors } = useUIKitTheme();
18
+
19
+ return (
20
+ <MessageContainer {...props}>
21
+ <Box style={styles.container} backgroundColor={colors.ui.groupChannelMessage[variant].enabled.background}>
22
+ <PressBox activeOpacity={0.8} onPress={onPress} onLongPress={onLongPress}>
23
+ <ImageWithPlaceholder source={{ uri: getAvailableUriFromFileMessage(props.message) }} style={styles.image} />
24
+ </PressBox>
25
+ {props.children}
26
+ </Box>
27
+ </MessageContainer>
28
+ );
29
+ };
30
+
31
+ const styles = createStyleSheet({
32
+ container: {
33
+ borderRadius: 16,
34
+ overflow: 'hidden',
35
+ },
36
+ image: {
37
+ maxWidth: 240,
38
+ width: 240,
39
+ height: 160,
40
+ borderRadius: 16,
41
+ overflow: 'hidden',
42
+ },
43
+ });
44
+
45
+ export default ImageFileMessage;
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+
3
+ import { SendbirdFileMessage, getFileExtension, getFileType } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import Icon from '../../components/Icon';
7
+ import PressBox from '../../components/PressBox';
8
+ import Text from '../../components/Text';
9
+ import createStyleSheet from '../../styles/createStyleSheet';
10
+ import useUIKitTheme from '../../theme/useUIKitTheme';
11
+ import MessageContainer from './MessageContainer';
12
+ import type { GroupChannelMessageProps } from './index';
13
+
14
+ const iconMapper = { audio: 'file-audio', image: 'photo', video: 'play', file: 'file-document' } as const;
15
+
16
+ type Props = GroupChannelMessageProps<SendbirdFileMessage>;
17
+
18
+ const FileMessage = (props: Props) => {
19
+ const { variant = 'incoming' } = props;
20
+ const { colors } = useUIKitTheme();
21
+
22
+ const fileType = getFileType(props.message.type || getFileExtension(props.message.name));
23
+ const color = colors.ui.groupChannelMessage[variant];
24
+
25
+ return (
26
+ <MessageContainer {...props}>
27
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
28
+ {({ pressed }) => (
29
+ <Box backgroundColor={pressed ? color.pressed.background : color.enabled.background} style={styles.container}>
30
+ <Box style={styles.bubble}>
31
+ <Icon
32
+ icon={iconMapper[fileType]}
33
+ size={24}
34
+ containerStyle={{ backgroundColor: colors.background, padding: 2, borderRadius: 8, marginRight: 8 }}
35
+ />
36
+ <Text
37
+ body3
38
+ ellipsizeMode={'middle'}
39
+ numberOfLines={1}
40
+ color={pressed ? color.pressed.textMsg : color.enabled.textMsg}
41
+ style={styles.name}
42
+ >
43
+ {props.strings?.fileName || props.message.name}
44
+ </Text>
45
+ </Box>
46
+ {props.children}
47
+ </Box>
48
+ )}
49
+ </PressBox>
50
+ </MessageContainer>
51
+ );
52
+ };
53
+
54
+ const styles = createStyleSheet({
55
+ container: {
56
+ overflow: 'hidden',
57
+ borderRadius: 16,
58
+ },
59
+ bubble: {
60
+ flexDirection: 'row',
61
+ alignItems: 'center',
62
+ paddingHorizontal: 12,
63
+ paddingVertical: 6,
64
+ },
65
+ name: {
66
+ flexShrink: 1,
67
+ },
68
+ });
69
+
70
+ export default FileMessage;
@@ -0,0 +1,106 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ import type { SendbirdFileMessage } from '@sendbird/uikit-utils';
5
+ import { getAvailableUriFromFileMessage } from '@sendbird/uikit-utils';
6
+
7
+ import Box from '../../components/Box';
8
+ import Icon from '../../components/Icon';
9
+ import ImageWithPlaceholder from '../../components/ImageWithPlaceholder';
10
+ import PressBox from '../../components/PressBox';
11
+ import createStyleSheet from '../../styles/createStyleSheet';
12
+ import useUIKitTheme from '../../theme/useUIKitTheme';
13
+ import MessageContainer from './MessageContainer';
14
+ import type { GroupChannelMessageProps } from './index';
15
+
16
+ type Props = GroupChannelMessageProps<
17
+ SendbirdFileMessage,
18
+ {
19
+ fetchThumbnailFromVideoSource: (uri: string) => Promise<{ path: string } | null>;
20
+ }
21
+ >;
22
+
23
+ const VideoFileMessage = (props: Props) => {
24
+ const { onPress, onLongPress, variant = 'incoming' } = props;
25
+
26
+ const { colors, palette, select } = useUIKitTheme();
27
+ const uri = getAvailableUriFromFileMessage(props.message);
28
+ const { thumbnail, loading } = useRetry(() => props.fetchThumbnailFromVideoSource(uri));
29
+
30
+ return (
31
+ <MessageContainer {...props}>
32
+ <Box style={styles.container} backgroundColor={colors.ui.groupChannelMessage[variant].enabled.background}>
33
+ <PressBox activeOpacity={0.8} onPress={onPress} onLongPress={onLongPress} style={styles.image}>
34
+ {loading ? (
35
+ <Box
36
+ style={StyleSheet.absoluteFill}
37
+ backgroundColor={select({ dark: palette.background400, light: palette.background100 })}
38
+ />
39
+ ) : (
40
+ <ImageWithPlaceholder source={{ uri: thumbnail ?? 'invalid-image' }} style={StyleSheet.absoluteFill} />
41
+ )}
42
+
43
+ {(loading || thumbnail !== null) && (
44
+ <Box style={StyleSheet.absoluteFill} alignItems={'center'} justifyContent={'center'}>
45
+ <Icon
46
+ icon={'play'}
47
+ size={28}
48
+ color={palette.onBackgroundLight02}
49
+ containerStyle={[styles.playIcon, { backgroundColor: palette.onBackgroundDark01 }]}
50
+ />
51
+ </Box>
52
+ )}
53
+ </PressBox>
54
+ {props.children}
55
+ </Box>
56
+ </MessageContainer>
57
+ );
58
+ };
59
+
60
+ const useRetry = (fetch: () => Promise<{ path: string } | null>, retryCount = 5) => {
61
+ const [state, setState] = useState({ thumbnail: null as null | string, loading: true });
62
+ const retryCountRef = useRef(0);
63
+ const retryTimeoutRef = useRef<NodeJS.Timeout>();
64
+ const fetchThumbnail = useRef(fetch);
65
+ fetchThumbnail.current = fetch;
66
+
67
+ useEffect(() => {
68
+ if (!state.thumbnail) {
69
+ const reloadReservation = () => {
70
+ if (retryCountRef.current < retryCount) {
71
+ retryTimeoutRef.current = setTimeout(() => {
72
+ retryCountRef.current++;
73
+ reloadReservation();
74
+ fetchThumbnail.current().then((result) => {
75
+ setState({ loading: false, thumbnail: result?.path ?? null });
76
+ });
77
+ }, retryCountRef.current * 5000);
78
+ }
79
+ };
80
+
81
+ return reloadReservation();
82
+ } else {
83
+ return clearTimeout(retryTimeoutRef.current);
84
+ }
85
+ }, [state.thumbnail]);
86
+
87
+ return state;
88
+ };
89
+ const styles = createStyleSheet({
90
+ container: {
91
+ borderRadius: 16,
92
+ overflow: 'hidden',
93
+ },
94
+ image: {
95
+ maxWidth: 240,
96
+ width: 240,
97
+ height: 160,
98
+ borderRadius: 16,
99
+ overflow: 'hidden',
100
+ },
101
+ playIcon: {
102
+ padding: 10,
103
+ borderRadius: 50,
104
+ },
105
+ });
106
+ export default VideoFileMessage;
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+
3
+ import type { SendbirdMessage } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import PressBox from '../../components/PressBox';
7
+ import Text from '../../components/Text';
8
+ import createStyleSheet from '../../styles/createStyleSheet';
9
+ import useUIKitTheme from '../../theme/useUIKitTheme';
10
+ import MessageContainer from './MessageContainer';
11
+ import type { GroupChannelMessageProps } from './index';
12
+
13
+ const UnknownMessage = (props: GroupChannelMessageProps<SendbirdMessage>) => {
14
+ const { variant = 'incoming' } = props;
15
+
16
+ const { colors } = useUIKitTheme();
17
+ const color = colors.ui.groupChannelMessage['incoming'];
18
+ const titleColor = variant === 'incoming' ? colors.onBackground01 : colors.onBackgroundReverse01;
19
+ const descColor = variant === 'incoming' ? colors.onBackground02 : colors.onBackgroundReverse02;
20
+
21
+ return (
22
+ <MessageContainer {...props}>
23
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
24
+ {({ pressed }) => (
25
+ <Box style={styles.bubble} backgroundColor={pressed ? color.pressed.background : color.enabled.background}>
26
+ <Text body3 color={titleColor}>
27
+ {props.strings?.unknownTitle ?? '(Unknown message type)'}
28
+ </Text>
29
+ <Text body3 color={descColor}>
30
+ {props.strings?.unknownDescription ?? 'Cannot read this message.'}
31
+ </Text>
32
+ </Box>
33
+ )}
34
+ </PressBox>
35
+ </MessageContainer>
36
+ );
37
+ };
38
+
39
+ const styles = createStyleSheet({
40
+ bubble: {
41
+ paddingVertical: 6,
42
+ paddingHorizontal: 12,
43
+ borderRadius: 16,
44
+ },
45
+ });
46
+
47
+ export default UnknownMessage;
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+
3
+ import type { SendbirdUserMessage } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import PressBox from '../../components/PressBox';
7
+ import type { RegexTextPattern } from '../../components/RegexText';
8
+ import createStyleSheet from '../../styles/createStyleSheet';
9
+ import useUIKitTheme from '../../theme/useUIKitTheme';
10
+ import MessageBubbleWithText from './MessageBubbleWithText';
11
+ import MessageContainer from './MessageContainer';
12
+ import MessageOpenGraph from './MessageOpenGraph';
13
+ import type { GroupChannelMessageProps } from './index';
14
+
15
+ type Props = GroupChannelMessageProps<
16
+ SendbirdUserMessage,
17
+ {
18
+ regexTextPatterns?: RegexTextPattern[];
19
+ renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
20
+ }
21
+ >;
22
+
23
+ const OpenGraphUserMessage = (props: Props) => {
24
+ const { variant = 'incoming' } = props;
25
+
26
+ const { palette, select, colors } = useUIKitTheme();
27
+ const color = colors.ui.groupChannelMessage[variant];
28
+ const containerBackgroundColor = select({ dark: palette.background400, light: palette.background100 });
29
+
30
+ return (
31
+ <MessageContainer {...props}>
32
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
33
+ {({ pressed }) => (
34
+ <Box backgroundColor={containerBackgroundColor} style={styles.container}>
35
+ <MessageBubbleWithText
36
+ backgroundColor={pressed ? color.pressed.background : color.enabled.background}
37
+ {...props}
38
+ />
39
+ {props.message.ogMetaData && (
40
+ <MessageOpenGraph
41
+ variant={variant}
42
+ ogMetaData={props.message.ogMetaData}
43
+ onLongPress={props.onLongPress}
44
+ onPressURL={props.onPressURL}
45
+ />
46
+ )}
47
+ {props.children}
48
+ </Box>
49
+ )}
50
+ </PressBox>
51
+ </MessageContainer>
52
+ );
53
+ };
54
+
55
+ const styles = createStyleSheet({
56
+ container: {
57
+ borderRadius: 16,
58
+ overflow: 'hidden',
59
+ },
60
+ });
61
+
62
+ export default OpenGraphUserMessage;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+
3
+ import type { SendbirdUserMessage } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import PressBox from '../../components/PressBox';
7
+ import type { RegexTextPattern } from '../../components/RegexText';
8
+ import createStyleSheet from '../../styles/createStyleSheet';
9
+ import useUIKitTheme from '../../theme/useUIKitTheme';
10
+ import MessageBubbleWithText from './MessageBubbleWithText';
11
+ import MessageContainer from './MessageContainer';
12
+ import type { GroupChannelMessageProps } from './index';
13
+
14
+ type Props = GroupChannelMessageProps<
15
+ SendbirdUserMessage,
16
+ {
17
+ regexTextPatterns?: RegexTextPattern[];
18
+ renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
19
+ }
20
+ >;
21
+
22
+ const UserMessage = (props: Props) => {
23
+ const { variant = 'incoming' } = props;
24
+
25
+ const { colors } = useUIKitTheme();
26
+ const color = colors.ui.groupChannelMessage[variant];
27
+
28
+ return (
29
+ <MessageContainer {...props}>
30
+ <PressBox onPress={props.onPress} onLongPress={props.onLongPress}>
31
+ {({ pressed }) => (
32
+ <Box backgroundColor={pressed ? color.pressed.background : color.enabled.background} style={styles.container}>
33
+ <MessageBubbleWithText {...props} />
34
+ {props.children}
35
+ </Box>
36
+ )}
37
+ </PressBox>
38
+ </MessageContainer>
39
+ );
40
+ };
41
+
42
+ const styles = createStyleSheet({
43
+ container: {
44
+ overflow: 'hidden',
45
+ borderRadius: 16,
46
+ },
47
+ });
48
+
49
+ export default UserMessage;
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+
3
+ import { SendbirdUserMessage, urlRegexStrict } from '@sendbird/uikit-utils';
4
+
5
+ import Box from '../../components/Box';
6
+ import RegexText, { RegexTextPattern } from '../../components/RegexText';
7
+ import Text from '../../components/Text';
8
+ import createStyleSheet from '../../styles/createStyleSheet';
9
+ import useUIKitTheme from '../../theme/useUIKitTheme';
10
+ import type { GroupChannelMessageProps } from './index';
11
+
12
+ type Props = GroupChannelMessageProps<
13
+ SendbirdUserMessage,
14
+ {
15
+ backgroundColor?: string;
16
+ regexTextPatterns?: RegexTextPattern[];
17
+ renderRegexTextChildren?: (message: SendbirdUserMessage) => string;
18
+ }
19
+ >;
20
+
21
+ const MessageBubbleWithText = ({
22
+ backgroundColor,
23
+ message,
24
+ onPressURL,
25
+ onLongPress,
26
+ strings,
27
+ variant = 'incoming',
28
+ regexTextPatterns = [],
29
+ renderRegexTextChildren = (msg) => msg.message,
30
+ }: Props) => {
31
+ const { colors } = useUIKitTheme();
32
+ const color = colors.ui.groupChannelMessage[variant];
33
+ return (
34
+ <Box backgroundColor={backgroundColor} style={styles.bubble}>
35
+ <Text body3 color={color.enabled.textMsg} suppressHighlighting>
36
+ <RegexText
37
+ body3
38
+ color={color.enabled.textMsg}
39
+ patterns={[
40
+ ...regexTextPatterns,
41
+ {
42
+ regex: urlRegexStrict,
43
+ replacer({ match, parentProps, keyPrefix, index }) {
44
+ return (
45
+ <Text
46
+ {...parentProps}
47
+ key={`${keyPrefix}-${index}`}
48
+ onPress={() => onPressURL?.(match)}
49
+ onLongPress={onLongPress}
50
+ style={[parentProps?.style, styles.urlText]}
51
+ >
52
+ {match}
53
+ </Text>
54
+ );
55
+ },
56
+ },
57
+ ]}
58
+ >
59
+ {renderRegexTextChildren(message)}
60
+ </RegexText>
61
+ {Boolean(message.updatedAt) && (
62
+ <Text body3 color={color.enabled.textEdited}>
63
+ {strings?.edited ?? ' (edited)'}
64
+ </Text>
65
+ )}
66
+ </Text>
67
+ </Box>
68
+ );
69
+ };
70
+
71
+ const styles = createStyleSheet({
72
+ bubble: {
73
+ paddingHorizontal: 12,
74
+ paddingVertical: 6,
75
+ },
76
+ urlText: {
77
+ textDecorationLine: 'underline',
78
+ },
79
+ });
80
+ export default MessageBubbleWithText;
@@ -0,0 +1,106 @@
1
+ import React from 'react';
2
+ import { Pressable } from 'react-native';
3
+
4
+ import type { SendbirdMessage } from '@sendbird/uikit-utils';
5
+ import { getMessageTimeFormat } from '@sendbird/uikit-utils';
6
+
7
+ import Box from '../../components/Box';
8
+ import Text from '../../components/Text';
9
+ import createStyleSheet from '../../styles/createStyleSheet';
10
+ import useUIKitTheme from '../../theme/useUIKitTheme';
11
+ import Avatar from '../Avatar';
12
+ import type { GroupChannelMessageProps } from './index';
13
+
14
+ type Props = GroupChannelMessageProps<SendbirdMessage>;
15
+
16
+ const MessageContainer = (props: Props) => {
17
+ if (props.variant === 'incoming') {
18
+ return <MessageContainer.Incoming {...props} />;
19
+ } else {
20
+ return <MessageContainer.Outgoing {...props} />;
21
+ }
22
+ };
23
+
24
+ MessageContainer.Incoming = function MessageContainerIncoming({
25
+ children,
26
+ groupedWithNext,
27
+ groupedWithPrev,
28
+ message,
29
+ onPressAvatar,
30
+ strings,
31
+ }: Props) {
32
+ const { colors } = useUIKitTheme();
33
+ const color = colors.ui.groupChannelMessage.incoming;
34
+
35
+ return (
36
+ <Box flexDirection={'row'} justifyContent={'flex-start'} alignItems={'flex-end'}>
37
+ <Box width={26} marginRight={12}>
38
+ {(message.isFileMessage() || message.isUserMessage()) && !groupedWithNext && (
39
+ <Pressable onPress={onPressAvatar}>
40
+ <Avatar size={26} uri={message.sender?.profileUrl} />
41
+ </Pressable>
42
+ )}
43
+ </Box>
44
+ <Box flexShrink={1}>
45
+ {!groupedWithPrev && (
46
+ <Box marginLeft={12} marginBottom={4}>
47
+ {(message.isFileMessage() || message.isUserMessage()) && (
48
+ <Text caption1 color={color.enabled.textSenderName} numberOfLines={1}>
49
+ {strings?.senderName ?? message.sender.nickname}
50
+ </Text>
51
+ )}
52
+ </Box>
53
+ )}
54
+
55
+ <Box flexDirection={'row'} alignItems={'flex-end'}>
56
+ <Box style={styles.bubble}>{children}</Box>
57
+ {!groupedWithNext && (
58
+ <Box marginLeft={4}>
59
+ <Text caption4 color={color.enabled.textTime}>
60
+ {strings?.sentDate ?? getMessageTimeFormat(new Date(message.createdAt))}
61
+ </Text>
62
+ </Box>
63
+ )}
64
+ </Box>
65
+ </Box>
66
+ </Box>
67
+ );
68
+ };
69
+
70
+ MessageContainer.Outgoing = function MessageContainerOutgoing({
71
+ children,
72
+ message,
73
+ groupedWithNext,
74
+ strings,
75
+ sendingStatus,
76
+ }: Props) {
77
+ const { colors } = useUIKitTheme();
78
+ const color = colors.ui.groupChannelMessage.outgoing;
79
+
80
+ return (
81
+ <Box flexDirection={'row'} justifyContent={'flex-end'} alignItems={'flex-end'}>
82
+ <Box flexDirection={'row'} alignItems={'flex-end'} justifyContent={'center'}>
83
+ {sendingStatus && <Box marginRight={4}>{sendingStatus}</Box>}
84
+
85
+ {!groupedWithNext && (
86
+ <Box marginRight={4}>
87
+ <Text caption4 color={color.enabled.textTime}>
88
+ {strings?.sentDate ?? getMessageTimeFormat(new Date(message.createdAt))}
89
+ </Text>
90
+ </Box>
91
+ )}
92
+ </Box>
93
+ <Box style={styles.bubble}>{children}</Box>
94
+ </Box>
95
+ );
96
+ };
97
+
98
+ const styles = createStyleSheet({
99
+ bubble: {
100
+ maxWidth: 240,
101
+ overflow: 'hidden',
102
+ flexShrink: 1,
103
+ },
104
+ });
105
+
106
+ export default MessageContainer;