|
1 | 1 | import React from 'react'; |
2 | 2 | import { StyleSheet, Text, View } from 'react-native'; |
3 | 3 |
|
| 4 | +import { CommandSuggestion, TextComposerSuggestion, UserSuggestion } from 'stream-chat'; |
| 5 | + |
4 | 6 | import { AutoCompleteSuggestionCommandIcon } from './AutoCompleteSuggestionCommandIcon'; |
5 | 7 |
|
6 | | -import type { |
7 | | - Suggestion, |
8 | | - SuggestionCommand, |
9 | | - SuggestionsContextValue, |
10 | | - SuggestionUser, |
11 | | -} from '../../contexts/suggestionsContext/SuggestionsContext'; |
12 | 8 | import { useTheme } from '../../contexts/themeContext/ThemeContext'; |
13 | 9 | import type { Emoji } from '../../emoji-data'; |
14 | 10 | import { AtMentions } from '../../icons/AtMentions'; |
15 | 11 |
|
16 | 12 | import { Avatar } from '../Avatar/Avatar'; |
17 | 13 |
|
18 | | -export type AutoCompleteSuggestionItemPropsWithContext = Pick< |
19 | | - SuggestionsContextValue, |
20 | | - 'triggerType' |
21 | | -> & { |
22 | | - itemProps: Suggestion; |
| 14 | +export type AutoCompleteSuggestionItemProps = { |
| 15 | + itemProps: TextComposerSuggestion; |
| 16 | + triggerType: string; |
| 17 | +}; |
| 18 | + |
| 19 | +export const MentionSuggestionItem = (item: UserSuggestion) => { |
| 20 | + const { id, image, name, online } = item; |
| 21 | + const { |
| 22 | + theme: { |
| 23 | + colors: { accent_blue, black }, |
| 24 | + messageInput: { |
| 25 | + suggestions: { |
| 26 | + mention: { avatarSize, column, container: mentionContainer, name: nameStyle }, |
| 27 | + }, |
| 28 | + }, |
| 29 | + }, |
| 30 | + } = useTheme(); |
| 31 | + return ( |
| 32 | + <View style={[styles.container, mentionContainer]}> |
| 33 | + <Avatar image={image} name={name} online={online} size={avatarSize} /> |
| 34 | + <View style={[styles.column, column]}> |
| 35 | + <Text style={[styles.name, { color: black }, nameStyle]} testID='mentions-item-name'> |
| 36 | + {name || id} |
| 37 | + </Text> |
| 38 | + </View> |
| 39 | + <AtMentions pathFill={accent_blue} /> |
| 40 | + </View> |
| 41 | + ); |
| 42 | +}; |
| 43 | + |
| 44 | +const EmojiSuggestionItem = (item: Emoji) => { |
| 45 | + const { unicode, name } = item; |
| 46 | + const { |
| 47 | + theme: { |
| 48 | + colors: { black }, |
| 49 | + messageInput: { |
| 50 | + suggestions: { |
| 51 | + emoji: { container: emojiContainer, text }, |
| 52 | + }, |
| 53 | + }, |
| 54 | + }, |
| 55 | + } = useTheme(); |
| 56 | + return ( |
| 57 | + <View style={[styles.container, emojiContainer]}> |
| 58 | + <Text style={[styles.text, { color: black }, text]} testID='emojis-item-unicode'> |
| 59 | + {unicode} |
| 60 | + </Text> |
| 61 | + <Text style={[styles.text, { color: black }, text]} testID='emojis-item-name'> |
| 62 | + {` ${name}`} |
| 63 | + </Text> |
| 64 | + </View> |
| 65 | + ); |
| 66 | +}; |
| 67 | + |
| 68 | +const CommandSuggestionItem = (item: CommandSuggestion) => { |
| 69 | + const { args, name } = item; |
| 70 | + const { |
| 71 | + theme: { |
| 72 | + colors: { black, grey }, |
| 73 | + messageInput: { |
| 74 | + suggestions: { |
| 75 | + command: { args: argsStyle, container: commandContainer, title }, |
| 76 | + }, |
| 77 | + }, |
| 78 | + }, |
| 79 | + } = useTheme(); |
| 80 | + |
| 81 | + return ( |
| 82 | + <View style={[styles.container, commandContainer]}> |
| 83 | + {name ? <AutoCompleteSuggestionCommandIcon name={name} /> : null} |
| 84 | + <Text style={[styles.title, { color: black }, title]} testID='commands-item-title'> |
| 85 | + {(name || '').replace(/^\w/, (char) => char.toUpperCase())} |
| 86 | + </Text> |
| 87 | + <Text style={[styles.args, { color: grey }, argsStyle]} testID='commands-item-args'> |
| 88 | + {`/${name} ${args}`} |
| 89 | + </Text> |
| 90 | + </View> |
| 91 | + ); |
| 92 | +}; |
| 93 | + |
| 94 | +export const AutoCompleteSuggestionItem = ({ |
| 95 | + itemProps, |
| 96 | + triggerType, |
| 97 | +}: AutoCompleteSuggestionItemProps) => { |
| 98 | + switch (triggerType) { |
| 99 | + case 'mention': |
| 100 | + return <MentionSuggestionItem {...(itemProps as UserSuggestion)} />; |
| 101 | + case 'emoji': |
| 102 | + return <EmojiSuggestionItem {...(itemProps as Emoji)} />; |
| 103 | + case 'command': |
| 104 | + return <CommandSuggestionItem {...itemProps} />; |
| 105 | + default: |
| 106 | + return null; |
| 107 | + } |
23 | 108 | }; |
24 | 109 |
|
25 | 110 | const styles = StyleSheet.create({ |
@@ -55,94 +140,3 @@ const styles = StyleSheet.create({ |
55 | 140 | paddingHorizontal: 8, |
56 | 141 | }, |
57 | 142 | }); |
58 | | - |
59 | | -const AutoCompleteSuggestionItemWithContext = ({ |
60 | | - itemProps, |
61 | | - triggerType, |
62 | | -}: AutoCompleteSuggestionItemPropsWithContext) => { |
63 | | - const { |
64 | | - theme: { |
65 | | - colors: { accent_blue, black, grey }, |
66 | | - messageInput: { |
67 | | - suggestions: { |
68 | | - command: { args: argsStyle, container: commandContainer, title }, |
69 | | - emoji: { container: emojiContainer, text }, |
70 | | - mention: { avatarSize, column, container: mentionContainer, name: nameStyle }, |
71 | | - }, |
72 | | - }, |
73 | | - }, |
74 | | - } = useTheme(); |
75 | | - |
76 | | - if (triggerType === 'mention') { |
77 | | - const { id, image, name, online } = itemProps as SuggestionUser; |
78 | | - return ( |
79 | | - <View style={[styles.container, mentionContainer]}> |
80 | | - <Avatar image={image} name={name} online={online} size={avatarSize} /> |
81 | | - <View style={[styles.column, column]}> |
82 | | - <Text style={[styles.name, { color: black }, nameStyle]} testID='mentions-item-name'> |
83 | | - {name || id} |
84 | | - </Text> |
85 | | - </View> |
86 | | - <AtMentions pathFill={accent_blue} /> |
87 | | - </View> |
88 | | - ); |
89 | | - } else if (triggerType === 'emoji') { |
90 | | - const { name, unicode } = itemProps as Emoji; |
91 | | - return ( |
92 | | - <View style={[styles.container, emojiContainer]}> |
93 | | - <Text style={[styles.text, { color: black }, text]} testID='emojis-item-unicode'> |
94 | | - {unicode} |
95 | | - </Text> |
96 | | - <Text style={[styles.text, { color: black }, text]} testID='emojis-item-name'> |
97 | | - {` ${name}`} |
98 | | - </Text> |
99 | | - </View> |
100 | | - ); |
101 | | - } else if (triggerType === 'command') { |
102 | | - const { args, name } = itemProps as SuggestionCommand; |
103 | | - return ( |
104 | | - <View style={[styles.container, commandContainer]}> |
105 | | - <AutoCompleteSuggestionCommandIcon name={name} /> |
106 | | - <Text style={[styles.title, { color: black }, title]} testID='commands-item-title'> |
107 | | - {(name || '').replace(/^\w/, (char) => char.toUpperCase())} |
108 | | - </Text> |
109 | | - <Text style={[styles.args, { color: grey }, argsStyle]} testID='commands-item-args'> |
110 | | - {`/${name} ${args}`} |
111 | | - </Text> |
112 | | - </View> |
113 | | - ); |
114 | | - } else { |
115 | | - return null; |
116 | | - } |
117 | | -}; |
118 | | - |
119 | | -const areEqual = ( |
120 | | - prevProps: AutoCompleteSuggestionItemPropsWithContext, |
121 | | - nextProps: AutoCompleteSuggestionItemPropsWithContext, |
122 | | -) => { |
123 | | - const { itemProps: prevItemProps, triggerType: prevType } = prevProps; |
124 | | - const { itemProps: nextItemProps, triggerType: nextType } = nextProps; |
125 | | - const itemPropsEqual = prevItemProps === nextItemProps; |
126 | | - if (!itemPropsEqual) { |
127 | | - return false; |
128 | | - } |
129 | | - const typeEqual = prevType === nextType; |
130 | | - if (!typeEqual) { |
131 | | - return false; |
132 | | - } |
133 | | - return true; |
134 | | -}; |
135 | | - |
136 | | -const MemoizedAutoCompleteSuggestionItem = React.memo( |
137 | | - AutoCompleteSuggestionItemWithContext, |
138 | | - areEqual, |
139 | | -) as typeof AutoCompleteSuggestionItemWithContext; |
140 | | - |
141 | | -export type AutoCompleteSuggestionItemProps = AutoCompleteSuggestionItemPropsWithContext; |
142 | | - |
143 | | -export const AutoCompleteSuggestionItem = (props: AutoCompleteSuggestionItemProps) => ( |
144 | | - <MemoizedAutoCompleteSuggestionItem {...props} /> |
145 | | -); |
146 | | - |
147 | | -AutoCompleteSuggestionItem.displayName = |
148 | | - 'AutoCompleteSuggestionItem{messageInput{suggestions{Item}}}'; |
0 commit comments