@sendbird/uikit-react-native-foundation 3.0.4 → 3.1.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 (86) hide show
  1. package/lib/commonjs/components/Icon/index.js +12 -0
  2. package/lib/commonjs/components/Icon/index.js.map +1 -1
  3. package/lib/commonjs/components/VideoThumbnail/index.js +108 -0
  4. package/lib/commonjs/components/VideoThumbnail/index.js.map +1 -0
  5. package/lib/commonjs/index.js +7 -0
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/theme/DarkUIKitTheme.js +2 -1
  8. package/lib/commonjs/theme/DarkUIKitTheme.js.map +1 -1
  9. package/lib/commonjs/theme/LightUIKitTheme.js +2 -1
  10. package/lib/commonjs/theme/LightUIKitTheme.js.map +1 -1
  11. package/lib/commonjs/types.js.map +1 -1
  12. package/lib/commonjs/ui/BottomSheet/index.js +1 -0
  13. package/lib/commonjs/ui/BottomSheet/index.js.map +1 -1
  14. package/lib/commonjs/ui/Dialog/DialogSheet.js +4 -3
  15. package/lib/commonjs/ui/Dialog/DialogSheet.js.map +1 -1
  16. package/lib/commonjs/ui/GroupChannelMessage/Message.file.js +6 -9
  17. package/lib/commonjs/ui/GroupChannelMessage/Message.file.js.map +1 -1
  18. package/lib/commonjs/ui/GroupChannelMessage/Message.file.video.js +9 -71
  19. package/lib/commonjs/ui/GroupChannelMessage/Message.file.video.js.map +1 -1
  20. package/lib/commonjs/ui/GroupChannelMessage/MessageContainer.js +7 -5
  21. package/lib/commonjs/ui/GroupChannelMessage/MessageContainer.js.map +1 -1
  22. package/lib/commonjs/ui/GroupChannelMessage/MessageOpenGraph.js +2 -2
  23. package/lib/commonjs/ui/GroupChannelMessage/MessageOpenGraph.js.map +1 -1
  24. package/lib/commonjs/ui/GroupChannelMessage/index.js.map +1 -1
  25. package/lib/commonjs/ui/OpenChannelMessage/Message.file.js +2 -8
  26. package/lib/commonjs/ui/OpenChannelMessage/Message.file.js.map +1 -1
  27. package/lib/commonjs/ui/OpenChannelMessage/Message.file.video.js +10 -77
  28. package/lib/commonjs/ui/OpenChannelMessage/Message.file.video.js.map +1 -1
  29. package/lib/commonjs/ui/OpenChannelMessage/Message.user.og.js +1 -1
  30. package/lib/commonjs/ui/OpenChannelMessage/Message.user.og.js.map +1 -1
  31. package/lib/module/components/Icon/index.js +12 -0
  32. package/lib/module/components/Icon/index.js.map +1 -1
  33. package/lib/module/components/VideoThumbnail/index.js +98 -0
  34. package/lib/module/components/VideoThumbnail/index.js.map +1 -0
  35. package/lib/module/index.js +1 -0
  36. package/lib/module/index.js.map +1 -1
  37. package/lib/module/theme/DarkUIKitTheme.js +2 -1
  38. package/lib/module/theme/DarkUIKitTheme.js.map +1 -1
  39. package/lib/module/theme/LightUIKitTheme.js +2 -1
  40. package/lib/module/theme/LightUIKitTheme.js.map +1 -1
  41. package/lib/module/types.js.map +1 -1
  42. package/lib/module/ui/BottomSheet/index.js +1 -0
  43. package/lib/module/ui/BottomSheet/index.js.map +1 -1
  44. package/lib/module/ui/Dialog/DialogSheet.js +4 -3
  45. package/lib/module/ui/Dialog/DialogSheet.js.map +1 -1
  46. package/lib/module/ui/GroupChannelMessage/Message.file.js +7 -10
  47. package/lib/module/ui/GroupChannelMessage/Message.file.js.map +1 -1
  48. package/lib/module/ui/GroupChannelMessage/Message.file.video.js +9 -69
  49. package/lib/module/ui/GroupChannelMessage/Message.file.video.js.map +1 -1
  50. package/lib/module/ui/GroupChannelMessage/MessageContainer.js +7 -5
  51. package/lib/module/ui/GroupChannelMessage/MessageContainer.js.map +1 -1
  52. package/lib/module/ui/GroupChannelMessage/MessageOpenGraph.js +2 -2
  53. package/lib/module/ui/GroupChannelMessage/MessageOpenGraph.js.map +1 -1
  54. package/lib/module/ui/GroupChannelMessage/index.js.map +1 -1
  55. package/lib/module/ui/OpenChannelMessage/Message.file.js +2 -8
  56. package/lib/module/ui/OpenChannelMessage/Message.file.js.map +1 -1
  57. package/lib/module/ui/OpenChannelMessage/Message.file.video.js +10 -75
  58. package/lib/module/ui/OpenChannelMessage/Message.file.video.js.map +1 -1
  59. package/lib/module/ui/OpenChannelMessage/Message.user.og.js +1 -1
  60. package/lib/module/ui/OpenChannelMessage/Message.user.og.js.map +1 -1
  61. package/lib/typescript/src/components/Icon/index.d.ts +5 -0
  62. package/lib/typescript/src/components/VideoThumbnail/index.d.ts +11 -0
  63. package/lib/typescript/src/index.d.ts +1 -0
  64. package/lib/typescript/src/types.d.ts +1 -1
  65. package/lib/typescript/src/ui/BottomSheet/index.d.ts +1 -0
  66. package/lib/typescript/src/ui/Dialog/DialogSheet.d.ts +2 -1
  67. package/lib/typescript/src/ui/GroupChannelMessage/MessageContainer.d.ts +2 -2
  68. package/lib/typescript/src/ui/GroupChannelMessage/MessageOpenGraph.d.ts +1 -1
  69. package/lib/typescript/src/ui/GroupChannelMessage/index.d.ts +8 -0
  70. package/package.json +3 -3
  71. package/src/components/Icon/index.tsx +11 -7
  72. package/src/components/VideoThumbnail/index.tsx +100 -0
  73. package/src/index.ts +1 -0
  74. package/src/theme/DarkUIKitTheme.ts +1 -0
  75. package/src/theme/LightUIKitTheme.ts +1 -0
  76. package/src/types.ts +1 -1
  77. package/src/ui/BottomSheet/index.tsx +2 -0
  78. package/src/ui/Dialog/DialogSheet.tsx +6 -3
  79. package/src/ui/GroupChannelMessage/Message.file.tsx +4 -6
  80. package/src/ui/GroupChannelMessage/Message.file.video.tsx +10 -58
  81. package/src/ui/GroupChannelMessage/MessageContainer.tsx +18 -13
  82. package/src/ui/GroupChannelMessage/MessageOpenGraph.tsx +3 -3
  83. package/src/ui/GroupChannelMessage/index.ts +1 -0
  84. package/src/ui/OpenChannelMessage/Message.file.tsx +1 -3
  85. package/src/ui/OpenChannelMessage/Message.file.video.tsx +10 -53
  86. package/src/ui/OpenChannelMessage/Message.user.og.tsx +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":["React","urlRegexRough","Box","ImageWithPlaceholder","PressBox","RegexText","Text","createStyleSheet","useUIKitTheme","MessageContainer","OpenGraphUserMessage","props","colors","onPress","onLongPress","onPressURL","rest","color","ui","openChannelMessage","default","createElement","_ref","_props$strings","pressed","_extends","body3","enabled","textMsg","patterns","regex","replacer","_ref2","match","parentProps","keyPrefix","index","key","primary","style","message","Boolean","updatedAt","textMsgPostfix","strings","edited","ogMetaData","grouped","styles","ogContainer","_props$message$ogMeta","url","_ref3","padding","borderRadius","backgroundColor","bubbleBackground","numberOfLines","caption2","onBackground02","ogUrl","body2","ogTitle","title","description","onBackground01","defaultImage","ogImage","source","uri","maxWidth","marginBottom","width","height","marginTop"],"sources":["Message.user.og.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { SendbirdUserMessage } from '@sendbird/uikit-utils';\nimport { urlRegexRough } from '@sendbird/uikit-utils';\n\nimport Box from '../../components/Box';\nimport ImageWithPlaceholder from '../../components/ImageWithPlaceholder';\nimport PressBox from '../../components/PressBox';\nimport RegexText from '../../components/RegexText';\nimport Text from '../../components/Text';\nimport createStyleSheet from '../../styles/createStyleSheet';\nimport useUIKitTheme from '../../theme/useUIKitTheme';\nimport MessageContainer from './MessageContainer';\nimport type { OpenChannelMessageProps } from './index';\n\ntype Props = {};\nconst OpenGraphUserMessage = (props: OpenChannelMessageProps<SendbirdUserMessage, Props>) => {\n const { colors } = useUIKitTheme();\n const { onPress, onLongPress, onPressURL, ...rest } = props;\n const color = colors.ui.openChannelMessage.default;\n\n return (\n <Box>\n <PressBox onPress={onPress} onLongPress={onLongPress}>\n {({ pressed }) => (\n <MessageContainer pressed={pressed} {...rest}>\n <Text body3 color={color.enabled.textMsg}>\n <RegexText\n body3\n color={color.enabled.textMsg}\n patterns={[\n {\n regex: urlRegexRough,\n replacer({ match, parentProps, keyPrefix, index }) {\n return (\n <Text\n {...parentProps}\n key={`${keyPrefix}-${index}`}\n onPress={() => onPressURL?.(match)}\n onLongPress={onLongPress}\n color={colors.primary}\n style={parentProps?.style}\n >\n {match}\n </Text>\n );\n },\n },\n ]}\n >\n {props.message.message}\n </RegexText>\n {Boolean(props.message.updatedAt) && (\n <Text body3 color={color.enabled.textMsgPostfix}>\n {props.strings?.edited ?? ' (edited)'}\n </Text>\n )}\n </Text>\n </MessageContainer>\n )}\n </PressBox>\n {props.message.ogMetaData && (\n <MessageContainer {...rest} grouped>\n <PressBox\n style={styles.ogContainer}\n onPress={() => props.message.ogMetaData?.url && onPressURL?.(props.message.ogMetaData.url)}\n onLongPress={onLongPress}\n >\n {({ pressed }) =>\n props.message.ogMetaData && (\n <Box\n padding={8}\n borderRadius={8}\n style={styles.ogContainer}\n backgroundColor={pressed ? color.pressed.bubbleBackground : color.enabled.bubbleBackground}\n >\n <Text numberOfLines={1} caption2 color={colors.onBackground02} style={styles.ogUrl}>\n {props.message.ogMetaData.url}\n </Text>\n\n <Text numberOfLines={2} body2 color={colors.primary} style={styles.ogTitle}>\n {props.message.ogMetaData.title}\n </Text>\n\n {Boolean(props.message.ogMetaData.description) && (\n <Text numberOfLines={2} caption2 color={colors.onBackground01}>\n {props.message.ogMetaData.description}\n </Text>\n )}\n\n {Boolean(props.message.ogMetaData.defaultImage) && (\n <ImageWithPlaceholder\n style={styles.ogImage}\n source={{ uri: props.message.ogMetaData.defaultImage.url }}\n />\n )}\n </Box>\n )\n }\n </PressBox>\n </MessageContainer>\n )}\n </Box>\n );\n};\n\nconst styles = createStyleSheet({\n ogContainer: {\n maxWidth: 296,\n },\n ogUrl: {\n marginBottom: 4,\n },\n ogTitle: {\n marginBottom: 8,\n },\n ogImage: {\n width: '100%',\n height: 156,\n marginTop: 12,\n },\n});\n\nexport default OpenGraphUserMessage;\n"],"mappings":"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"}
1
+ {"version":3,"names":["React","urlRegexRough","Box","ImageWithPlaceholder","PressBox","RegexText","Text","createStyleSheet","useUIKitTheme","MessageContainer","OpenGraphUserMessage","props","colors","onPress","onLongPress","onPressURL","rest","color","ui","openChannelMessage","default","createElement","_ref","_props$strings","pressed","_extends","body3","enabled","textMsg","patterns","regex","replacer","_ref2","match","parentProps","keyPrefix","index","key","primary","style","message","Boolean","updatedAt","textMsgPostfix","strings","edited","ogMetaData","grouped","styles","ogContainer","_props$message$ogMeta","url","_ref3","padding","borderRadius","backgroundColor","bubbleBackground","numberOfLines","caption2","onBackground02","ogUrl","body2","ogTitle","title","description","onBackground01","defaultImage","ogImage","source","uri","maxWidth","marginBottom","width","height","marginTop"],"sources":["Message.user.og.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { SendbirdUserMessage } from '@sendbird/uikit-utils';\nimport { urlRegexRough } from '@sendbird/uikit-utils';\n\nimport Box from '../../components/Box';\nimport ImageWithPlaceholder from '../../components/ImageWithPlaceholder';\nimport PressBox from '../../components/PressBox';\nimport RegexText from '../../components/RegexText';\nimport Text from '../../components/Text';\nimport createStyleSheet from '../../styles/createStyleSheet';\nimport useUIKitTheme from '../../theme/useUIKitTheme';\nimport MessageContainer from './MessageContainer';\nimport type { OpenChannelMessageProps } from './index';\n\ntype Props = {};\nconst OpenGraphUserMessage = (props: OpenChannelMessageProps<SendbirdUserMessage, Props>) => {\n const { colors } = useUIKitTheme();\n const { onPress, onLongPress, onPressURL, ...rest } = props;\n const color = colors.ui.openChannelMessage.default;\n\n return (\n <Box>\n <PressBox onPress={onPress} onLongPress={onLongPress}>\n {({ pressed }) => (\n <MessageContainer pressed={pressed} {...rest}>\n <Text body3 color={color.enabled.textMsg}>\n <RegexText\n body3\n color={color.enabled.textMsg}\n patterns={[\n {\n regex: urlRegexRough,\n replacer({ match, parentProps, keyPrefix, index }) {\n return (\n <Text\n {...parentProps}\n key={`${keyPrefix}-${index}`}\n onPress={() => onPressURL?.(match)}\n onLongPress={onLongPress}\n color={colors.primary}\n style={parentProps?.style}\n >\n {match}\n </Text>\n );\n },\n },\n ]}\n >\n {props.message.message}\n </RegexText>\n {Boolean(props.message.updatedAt) && (\n <Text body3 color={color.enabled.textMsgPostfix}>\n {props.strings?.edited ?? ' (edited)'}\n </Text>\n )}\n </Text>\n </MessageContainer>\n )}\n </PressBox>\n {props.message.ogMetaData && (\n <MessageContainer {...rest} grouped>\n <PressBox\n style={styles.ogContainer}\n onPress={() => props.message.ogMetaData?.url && onPressURL?.(props.message.ogMetaData.url)}\n onLongPress={onLongPress}\n >\n {({ pressed }) =>\n props.message.ogMetaData && (\n <Box\n padding={8}\n borderRadius={8}\n style={styles.ogContainer}\n backgroundColor={pressed ? color.pressed.bubbleBackground : color.enabled.bubbleBackground}\n >\n <Text numberOfLines={1} caption2 color={colors.onBackground02} style={styles.ogUrl}>\n {props.message.ogMetaData.url}\n </Text>\n\n <Text numberOfLines={2} body2 color={colors.primary} style={styles.ogTitle}>\n {props.message.ogMetaData.title}\n </Text>\n\n {Boolean(props.message.ogMetaData.description) && (\n <Text numberOfLines={2} caption2 color={colors.onBackground01}>\n {props.message.ogMetaData.description}\n </Text>\n )}\n\n {!!props.message.ogMetaData.defaultImage && (\n <ImageWithPlaceholder\n style={styles.ogImage}\n source={{ uri: props.message.ogMetaData.defaultImage.url }}\n />\n )}\n </Box>\n )\n }\n </PressBox>\n </MessageContainer>\n )}\n </Box>\n );\n};\n\nconst styles = createStyleSheet({\n ogContainer: {\n maxWidth: 296,\n },\n ogUrl: {\n marginBottom: 4,\n },\n ogTitle: {\n marginBottom: 8,\n },\n ogImage: {\n width: '100%',\n height: 156,\n marginTop: 12,\n },\n});\n\nexport default OpenGraphUserMessage;\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { ImageStyle, StyleProp, ViewStyle } from 'react-native';
2
+ import { FileType } from '@sendbird/uikit-utils';
2
3
  import IconAssets from '../../assets/icon';
3
4
  type IconNames = keyof typeof IconAssets;
4
5
  type Props = {
@@ -10,5 +11,9 @@ type Props = {
10
11
  };
11
12
  declare const Icon: ((props: Props) => JSX.Element) & {
12
13
  Assets: typeof IconAssets;
14
+ File: typeof FileIcon;
13
15
  };
16
+ declare const FileIcon: ({ fileType, ...props }: Omit<Props, "icon"> & {
17
+ fileType: FileType;
18
+ }) => JSX.Element;
14
19
  export default Icon;
@@ -0,0 +1,11 @@
1
+ import { StyleProp, ViewStyle } from 'react-native';
2
+ type Props = {
3
+ videoSource: string;
4
+ fetchThumbnailFromVideoSource: (uri: string) => Promise<{
5
+ path: string;
6
+ } | null>;
7
+ style?: StyleProp<ViewStyle>;
8
+ iconSize?: number;
9
+ };
10
+ export declare const VideoThumbnail: ({ fetchThumbnailFromVideoSource, style, videoSource, iconSize }: Props) => JSX.Element;
11
+ export {};
@@ -13,6 +13,7 @@ export type { RegexTextPattern } from './components/RegexText';
13
13
  export { default as Switch } from './components/Switch';
14
14
  export { default as Text } from './components/Text';
15
15
  export { default as TextInput } from './components/TextInput';
16
+ export { VideoThumbnail } from './components/VideoThumbnail';
16
17
  /** UI **/
17
18
  export { default as ActionMenu } from './ui/ActionMenu';
18
19
  export { default as Alert } from './ui/Alert';
@@ -72,7 +72,7 @@ export type ComponentColorTree = GetColorTree<{
72
72
  ColorPart: {
73
73
  Header: 'background' | 'borderBottom';
74
74
  Button: 'background' | 'content';
75
- Dialog: 'background' | 'text' | 'message' | 'highlight' | 'destructive';
75
+ Dialog: 'background' | 'text' | 'message' | 'highlight' | 'destructive' | 'blurred';
76
76
  Input: 'text' | 'placeholder' | 'background' | 'highlight';
77
77
  Badge: 'text' | 'background';
78
78
  Placeholder: 'content' | 'highlight';
@@ -8,6 +8,7 @@ export type BottomSheetItem = {
8
8
  iconColor?: string;
9
9
  title: string;
10
10
  titleColor?: string;
11
+ disabled?: boolean;
11
12
  onPress: () => void;
12
13
  }[];
13
14
  HeaderComponent?: (props: HeaderProps) => JSX.Element;
@@ -12,6 +12,7 @@ export type SheetItemProps = {
12
12
  iconColor?: string;
13
13
  title: string;
14
14
  titleColor?: string;
15
+ disabled?: boolean;
15
16
  };
16
- declare const SheetItem: ({ icon, title, iconColor, titleColor }: SheetItemProps) => JSX.Element;
17
+ declare const SheetItem: ({ icon, title, iconColor, titleColor, disabled }: SheetItemProps) => JSX.Element;
17
18
  export default DialogSheet;
@@ -3,7 +3,7 @@ import type { GroupChannelMessageProps } from './index';
3
3
  type Props = GroupChannelMessageProps<SendbirdMessage>;
4
4
  declare const MessageContainer: {
5
5
  (props: Props): JSX.Element;
6
- Incoming({ children, groupedWithNext, groupedWithPrev, message, onPressAvatar, strings, }: Props): JSX.Element;
7
- Outgoing({ children, message, groupedWithNext, strings, sendingStatus, }: Props): JSX.Element;
6
+ Incoming({ children, groupedWithNext, groupedWithPrev, message, onPressAvatar, strings, parentMessage, }: Props): JSX.Element;
7
+ Outgoing({ children, message, groupedWithNext, strings, sendingStatus, parentMessage, }: Props): JSX.Element;
8
8
  };
9
9
  export default MessageContainer;
@@ -1,6 +1,6 @@
1
1
  import type { SendbirdUserMessage } from '@sendbird/uikit-utils';
2
2
  declare const MessageOpenGraph: ({ onPressURL, onLongPress, ogMetaData, variant, }: {
3
- ogMetaData: Required<SendbirdUserMessage>['ogMetaData'];
3
+ ogMetaData: NonNullable<SendbirdUserMessage['ogMetaData']>;
4
4
  variant: 'outgoing' | 'incoming';
5
5
  onPressURL?: ((url: string) => void) | undefined;
6
6
  onLongPress?: (() => void) | undefined;
@@ -14,6 +14,7 @@ export type GroupChannelMessageProps<T extends SendbirdMessage, AdditionalProps
14
14
  };
15
15
  children?: React.ReactNode;
16
16
  sendingStatus?: React.ReactNode;
17
+ parentMessage?: React.ReactNode;
17
18
  groupedWithPrev: boolean;
18
19
  groupedWithNext: boolean;
19
20
  onPress?: () => void;
@@ -37,6 +38,7 @@ declare const GroupChannelMessage: {
37
38
  } | undefined;
38
39
  children?: React.ReactNode;
39
40
  sendingStatus?: React.ReactNode;
41
+ parentMessage?: React.ReactNode;
40
42
  groupedWithPrev: boolean;
41
43
  groupedWithNext: boolean;
42
44
  onPress?: (() => void) | undefined;
@@ -62,6 +64,7 @@ declare const GroupChannelMessage: {
62
64
  } | undefined;
63
65
  children?: React.ReactNode;
64
66
  sendingStatus?: React.ReactNode;
67
+ parentMessage?: React.ReactNode;
65
68
  groupedWithPrev: boolean;
66
69
  groupedWithNext: boolean;
67
70
  onPress?: (() => void) | undefined;
@@ -87,6 +90,7 @@ declare const GroupChannelMessage: {
87
90
  } | undefined;
88
91
  children?: React.ReactNode;
89
92
  sendingStatus?: React.ReactNode;
93
+ parentMessage?: React.ReactNode;
90
94
  groupedWithPrev: boolean;
91
95
  groupedWithNext: boolean;
92
96
  onPress?: (() => void) | undefined;
@@ -109,6 +113,7 @@ declare const GroupChannelMessage: {
109
113
  } | undefined;
110
114
  children?: React.ReactNode;
111
115
  sendingStatus?: React.ReactNode;
116
+ parentMessage?: React.ReactNode;
112
117
  groupedWithPrev: boolean;
113
118
  groupedWithNext: boolean;
114
119
  onPress?: (() => void) | undefined;
@@ -131,6 +136,7 @@ declare const GroupChannelMessage: {
131
136
  } | undefined;
132
137
  children?: React.ReactNode;
133
138
  sendingStatus?: React.ReactNode;
139
+ parentMessage?: React.ReactNode;
134
140
  groupedWithPrev: boolean;
135
141
  groupedWithNext: boolean;
136
142
  onPress?: (() => void) | undefined;
@@ -157,6 +163,7 @@ declare const GroupChannelMessage: {
157
163
  } | undefined;
158
164
  children?: React.ReactNode;
159
165
  sendingStatus?: React.ReactNode;
166
+ parentMessage?: React.ReactNode;
160
167
  groupedWithPrev: boolean;
161
168
  groupedWithNext: boolean;
162
169
  onPress?: (() => void) | undefined;
@@ -179,6 +186,7 @@ declare const GroupChannelMessage: {
179
186
  } | undefined;
180
187
  children?: React.ReactNode;
181
188
  sendingStatus?: React.ReactNode;
189
+ parentMessage?: React.ReactNode;
182
190
  groupedWithPrev: boolean;
183
191
  groupedWithNext: boolean;
184
192
  onPress?: (() => void) | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendbird/uikit-react-native-foundation",
3
- "version": "3.0.4",
3
+ "version": "3.1.0",
4
4
  "description": "A foundational UI kit for building chat-enabled React Native apps.",
5
5
  "keywords": [
6
6
  "sendbird",
@@ -47,7 +47,7 @@
47
47
  "access": "public"
48
48
  },
49
49
  "dependencies": {
50
- "@sendbird/uikit-utils": "3.0.4"
50
+ "@sendbird/uikit-utils": "3.1.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/react": "*",
@@ -89,5 +89,5 @@
89
89
  "readmeFile": "./README.md",
90
90
  "displayName": "@sendbird/uikit-react-native-foundation"
91
91
  },
92
- "gitHead": "bf8ff3723f82f75ccf994938d6e5468e6fb669be"
92
+ "gitHead": "1ff295c9b8df84b188fbc1f477d3e59708b8fb80"
93
93
  }
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
2
  import { Image, ImageStyle, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
3
3
 
4
+ import { FileType, convertFileTypeToMessageType, getFileIconFromMessageType } from '@sendbird/uikit-utils';
5
+
4
6
  import IconAssets from '../../assets/icon';
5
7
  import createStyleSheet from '../../styles/createStyleSheet';
6
8
  import useUIKitTheme from '../../theme/useUIKitTheme';
@@ -15,13 +17,10 @@ type Props = {
15
17
  style?: StyleProp<ImageStyle>;
16
18
  containerStyle?: StyleProp<ViewStyle>;
17
19
  };
18
- const Icon: ((props: Props) => JSX.Element) & { Assets: typeof IconAssets } = ({
19
- icon,
20
- color,
21
- size = 24,
22
- containerStyle,
23
- style,
24
- }) => {
20
+ const Icon: ((props: Props) => JSX.Element) & {
21
+ Assets: typeof IconAssets;
22
+ File: typeof FileIcon;
23
+ } = ({ icon, color, size = 24, containerStyle, style }) => {
25
24
  const sizeStyle = sizeStyles[size as SizeFactor] ?? { width: size, height: size };
26
25
  const { colors } = useUIKitTheme();
27
26
  return (
@@ -35,6 +34,10 @@ const Icon: ((props: Props) => JSX.Element) & { Assets: typeof IconAssets } = ({
35
34
  );
36
35
  };
37
36
 
37
+ const FileIcon = ({ fileType, ...props }: Omit<Props, 'icon'> & { fileType: FileType }) => {
38
+ return <Icon icon={getFileIconFromMessageType(convertFileTypeToMessageType(fileType))} {...props} />;
39
+ };
40
+
38
41
  const containerStyles = StyleSheet.create({
39
42
  container: {
40
43
  alignItems: 'center',
@@ -66,4 +69,5 @@ const sizeStyles = createStyleSheet({
66
69
  });
67
70
 
68
71
  Icon.Assets = IconAssets;
72
+ Icon.File = FileIcon;
69
73
  export default Icon;
@@ -0,0 +1,100 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
3
+
4
+ import createStyleSheet from '../../styles/createStyleSheet';
5
+ import useUIKitTheme from '../../theme/useUIKitTheme';
6
+ import Box from '../Box';
7
+ import Icon from '../Icon';
8
+ import ImageWithPlaceholder from '../ImageWithPlaceholder';
9
+
10
+ type Props = {
11
+ videoSource: string;
12
+ fetchThumbnailFromVideoSource: (uri: string) => Promise<{ path: string } | null>;
13
+
14
+ style?: StyleProp<ViewStyle>;
15
+ iconSize?: number;
16
+ };
17
+
18
+ export const VideoThumbnail = ({ fetchThumbnailFromVideoSource, style, videoSource, iconSize = 28 }: Props) => {
19
+ const { palette, select } = useUIKitTheme();
20
+ const { thumbnail, loading } = useRetry(() => fetchThumbnailFromVideoSource(videoSource));
21
+
22
+ return (
23
+ <Box style={style}>
24
+ {loading ? (
25
+ <Box
26
+ style={StyleSheet.absoluteFill}
27
+ backgroundColor={select({ dark: palette.background400, light: palette.background100 })}
28
+ />
29
+ ) : (
30
+ <ImageWithPlaceholder source={{ uri: thumbnail ?? 'invalid-image' }} style={StyleSheet.absoluteFill} />
31
+ )}
32
+
33
+ {(loading || thumbnail !== null) && iconSize > 0 && (
34
+ <Box style={StyleSheet.absoluteFill} alignItems={'center'} justifyContent={'center'}>
35
+ <Icon
36
+ icon={'play'}
37
+ size={iconSize}
38
+ color={palette.onBackgroundLight02}
39
+ containerStyle={[styles.playIcon, { backgroundColor: palette.onBackgroundDark01 }]}
40
+ />
41
+ </Box>
42
+ )}
43
+ </Box>
44
+ );
45
+ };
46
+
47
+ const useRetry = (fetch: () => Promise<{ path: string } | null>, retryCount = 5) => {
48
+ const [state, setState] = useState({ thumbnail: null as null | string, loading: true });
49
+ const retryCountRef = useRef(0);
50
+ const fetchThumbnail = useRef(fetch);
51
+ fetchThumbnail.current = fetch;
52
+
53
+ useEffect(() => {
54
+ let _timeout: NodeJS.Timeout;
55
+ let _cancelled = false;
56
+
57
+ if (!state.thumbnail) {
58
+ const tryFetchThumbnail = (timeout: number) => {
59
+ const retry = () => {
60
+ retryCountRef.current++;
61
+ tryFetchThumbnail(timeout + 5000);
62
+ };
63
+
64
+ const finish = (path: string | null) => {
65
+ if (!_cancelled) setState({ loading: false, thumbnail: path });
66
+ };
67
+
68
+ if (retryCountRef.current < retryCount) {
69
+ _timeout = setTimeout(() => {
70
+ fetchThumbnail
71
+ .current()
72
+ .then((result) => {
73
+ if (result === null) retry();
74
+ else finish(result.path);
75
+ })
76
+ .catch(() => retry());
77
+ }, timeout);
78
+ } else {
79
+ finish(null);
80
+ }
81
+ };
82
+
83
+ tryFetchThumbnail(0);
84
+ }
85
+
86
+ return () => {
87
+ _cancelled = true;
88
+ clearTimeout(_timeout);
89
+ };
90
+ }, [state.thumbnail]);
91
+
92
+ return state;
93
+ };
94
+
95
+ const styles = createStyleSheet({
96
+ playIcon: {
97
+ padding: 10,
98
+ borderRadius: 50,
99
+ },
100
+ });
package/src/index.ts CHANGED
@@ -14,6 +14,7 @@ export type { RegexTextPattern } from './components/RegexText';
14
14
  export { default as Switch } from './components/Switch';
15
15
  export { default as Text } from './components/Text';
16
16
  export { default as TextInput } from './components/TextInput';
17
+ export { VideoThumbnail } from './components/VideoThumbnail';
17
18
 
18
19
  /** UI **/
19
20
  export { default as ActionMenu } from './ui/ActionMenu';
@@ -99,6 +99,7 @@ const DarkUIKitTheme = createTheme({
99
99
  message: palette.onBackgroundDark02,
100
100
  highlight: palette.primary200,
101
101
  destructive: palette.error300,
102
+ blurred: palette.onBackgroundDark04,
102
103
  },
103
104
  },
104
105
  },
@@ -99,6 +99,7 @@ const LightUIKitTheme = createTheme({
99
99
  message: palette.onBackgroundLight02,
100
100
  highlight: palette.primary300,
101
101
  destructive: palette.error300,
102
+ blurred: palette.onBackgroundLight04,
102
103
  },
103
104
  },
104
105
  },
package/src/types.ts CHANGED
@@ -93,7 +93,7 @@ export type ComponentColorTree = GetColorTree<{
93
93
  ColorPart: {
94
94
  Header: 'background' | 'borderBottom';
95
95
  Button: 'background' | 'content';
96
- Dialog: 'background' | 'text' | 'message' | 'highlight' | 'destructive';
96
+ Dialog: 'background' | 'text' | 'message' | 'highlight' | 'destructive' | 'blurred';
97
97
  Input: 'text' | 'placeholder' | 'background' | 'highlight';
98
98
  Badge: 'text' | 'background';
99
99
  Placeholder: 'content' | 'highlight';
@@ -14,6 +14,7 @@ export type BottomSheetItem = {
14
14
  iconColor?: string;
15
15
  title: string;
16
16
  titleColor?: string;
17
+ disabled?: boolean;
17
18
  onPress: () => void;
18
19
  }[];
19
20
  HeaderComponent?: (props: HeaderProps) => JSX.Element;
@@ -44,6 +45,7 @@ const BottomSheet = ({ onDismiss, onHide, visible, sheetItems, HeaderComponent }
44
45
  activeOpacity={0.75}
45
46
  key={props.title + idx}
46
47
  style={{ paddingLeft: left, paddingRight: right }}
48
+ disabled={props.disabled}
47
49
  onPress={async () => {
48
50
  await onHide();
49
51
  try {
@@ -23,22 +23,25 @@ export type SheetItemProps = {
23
23
  iconColor?: string;
24
24
  title: string;
25
25
  titleColor?: string;
26
+ disabled?: boolean;
26
27
  };
27
- const SheetItem = ({ icon, title, iconColor, titleColor }: SheetItemProps) => {
28
+ const SheetItem = ({ icon, title, iconColor, titleColor, disabled = false }: SheetItemProps) => {
28
29
  const { colors } = useUIKitTheme();
29
30
  return (
30
31
  <View style={[styles.sheetItemContainer, { backgroundColor: colors.ui.dialog.default.none.background }]}>
31
32
  {icon && (
32
33
  <Icon
33
34
  icon={icon}
34
- color={iconColor ?? colors.ui.dialog.default.none.highlight}
35
+ color={
36
+ iconColor ?? (disabled ? colors.ui.dialog.default.none.blurred : colors.ui.dialog.default.none.highlight)
37
+ }
35
38
  containerStyle={styles.sheetItemIcon}
36
39
  />
37
40
  )}
38
41
  <Text
39
42
  subtitle1
40
43
  numberOfLines={1}
41
- color={titleColor ?? colors.ui.dialog.default.none.text}
44
+ color={titleColor ?? (disabled ? colors.ui.dialog.default.none.blurred : colors.ui.dialog.default.none.text)}
42
45
  style={styles.sheetItemText}
43
46
  >
44
47
  {title}
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
- import { SendbirdFileMessage, getFileExtension, getFileType } from '@sendbird/uikit-utils';
3
+ import { SendbirdFileMessage, getFileExtension, getFileType, truncate } from '@sendbird/uikit-utils';
4
4
 
5
5
  import Box from '../../components/Box';
6
6
  import Icon from '../../components/Icon';
@@ -11,8 +11,6 @@ import useUIKitTheme from '../../theme/useUIKitTheme';
11
11
  import MessageContainer from './MessageContainer';
12
12
  import type { GroupChannelMessageProps } from './index';
13
13
 
14
- const iconMapper = { audio: 'file-audio', image: 'photo', video: 'play', file: 'file-document' } as const;
15
-
16
14
  type Props = GroupChannelMessageProps<SendbirdFileMessage>;
17
15
 
18
16
  const FileMessage = (props: Props) => {
@@ -28,8 +26,8 @@ const FileMessage = (props: Props) => {
28
26
  {({ pressed }) => (
29
27
  <Box backgroundColor={pressed ? color.pressed.background : color.enabled.background} style={styles.container}>
30
28
  <Box style={styles.bubble}>
31
- <Icon
32
- icon={iconMapper[fileType]}
29
+ <Icon.File
30
+ fileType={fileType}
33
31
  size={24}
34
32
  containerStyle={{ backgroundColor: colors.background, padding: 2, borderRadius: 8, marginRight: 8 }}
35
33
  />
@@ -40,7 +38,7 @@ const FileMessage = (props: Props) => {
40
38
  color={pressed ? color.pressed.textMsg : color.enabled.textMsg}
41
39
  style={styles.name}
42
40
  >
43
- {props.strings?.fileName || props.message.name}
41
+ {truncate(props.strings?.fileName || props.message.name, { mode: 'mid', maxLen: 20 })}
44
42
  </Text>
45
43
  </Box>
46
44
  {props.children}
@@ -1,13 +1,11 @@
1
- import React, { useEffect, useRef, useState } from 'react';
2
- import { StyleSheet } from 'react-native';
1
+ import React from 'react';
3
2
 
4
3
  import type { SendbirdFileMessage } from '@sendbird/uikit-utils';
5
4
  import { getAvailableUriFromFileMessage } from '@sendbird/uikit-utils';
6
5
 
7
6
  import Box from '../../components/Box';
8
- import Icon from '../../components/Icon';
9
- import ImageWithPlaceholder from '../../components/ImageWithPlaceholder';
10
7
  import PressBox from '../../components/PressBox';
8
+ import { VideoThumbnail } from '../../components/VideoThumbnail';
11
9
  import createStyleSheet from '../../styles/createStyleSheet';
12
10
  import useUIKitTheme from '../../theme/useUIKitTheme';
13
11
  import MessageContainer from './MessageContainer';
@@ -15,41 +13,24 @@ import type { GroupChannelMessageProps } from './index';
15
13
 
16
14
  type Props = GroupChannelMessageProps<
17
15
  SendbirdFileMessage,
18
- {
19
- fetchThumbnailFromVideoSource: (uri: string) => Promise<{ path: string } | null>;
20
- }
16
+ { fetchThumbnailFromVideoSource: (uri: string) => Promise<{ path: string } | null> }
21
17
  >;
22
18
 
23
19
  const VideoFileMessage = (props: Props) => {
24
20
  const { onPress, onLongPress, variant = 'incoming' } = props;
25
21
 
26
- const { colors, palette, select } = useUIKitTheme();
22
+ const { colors } = useUIKitTheme();
27
23
  const uri = getAvailableUriFromFileMessage(props.message);
28
- const { thumbnail, loading } = useRetry(() => props.fetchThumbnailFromVideoSource(uri));
29
24
 
30
25
  return (
31
26
  <MessageContainer {...props}>
32
27
  <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
- )}
28
+ <PressBox activeOpacity={0.8} onPress={onPress} onLongPress={onLongPress}>
29
+ <VideoThumbnail
30
+ style={styles.image}
31
+ videoSource={uri}
32
+ fetchThumbnailFromVideoSource={props.fetchThumbnailFromVideoSource}
33
+ />
53
34
  </PressBox>
54
35
  {props.children}
55
36
  </Box>
@@ -57,35 +38,6 @@ const VideoFileMessage = (props: Props) => {
57
38
  );
58
39
  };
59
40
 
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
41
  const styles = createStyleSheet({
90
42
  container: {
91
43
  borderRadius: 16,
@@ -28,6 +28,7 @@ MessageContainer.Incoming = function MessageContainerIncoming({
28
28
  message,
29
29
  onPressAvatar,
30
30
  strings,
31
+ parentMessage,
31
32
  }: Props) {
32
33
  const { colors } = useUIKitTheme();
33
34
  const color = colors.ui.groupChannelMessage.incoming;
@@ -42,7 +43,8 @@ MessageContainer.Incoming = function MessageContainerIncoming({
42
43
  )}
43
44
  </Box>
44
45
  <Box flexShrink={1}>
45
- {!groupedWithPrev && (
46
+ {parentMessage}
47
+ {!groupedWithPrev && !message.parentMessage && (
46
48
  <Box marginLeft={12} marginBottom={4}>
47
49
  {(message.isFileMessage() || message.isUserMessage()) && (
48
50
  <Text caption1 color={color.enabled.textSenderName} numberOfLines={1}>
@@ -73,24 +75,27 @@ MessageContainer.Outgoing = function MessageContainerOutgoing({
73
75
  groupedWithNext,
74
76
  strings,
75
77
  sendingStatus,
78
+ parentMessage,
76
79
  }: Props) {
77
80
  const { colors } = useUIKitTheme();
78
81
  const color = colors.ui.groupChannelMessage.outgoing;
79
82
 
80
83
  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
- )}
84
+ <Box>
85
+ {parentMessage}
86
+ <Box flexDirection={'row'} justifyContent={'flex-end'} alignItems={'flex-end'}>
87
+ <Box flexDirection={'row'} alignItems={'flex-end'} justifyContent={'center'}>
88
+ {sendingStatus && <Box marginRight={4}>{sendingStatus}</Box>}
89
+ {!groupedWithNext && (
90
+ <Box marginRight={4}>
91
+ <Text caption4 color={color.enabled.textTime}>
92
+ {strings?.sentDate ?? getMessageTimeFormat(new Date(message.createdAt))}
93
+ </Text>
94
+ </Box>
95
+ )}
96
+ </Box>
97
+ <Box style={styles.bubble}>{children}</Box>
92
98
  </Box>
93
- <Box style={styles.bubble}>{children}</Box>
94
99
  </Box>
95
100
  );
96
101
  };