Changeset View
Changeset View
Standalone View
Standalone View
native/chat/typeahead-tooltip.react.js
Show All 9 Lines | import { | ||||
type Selection, | type Selection, | ||||
getNewTextAndSelection, | getNewTextAndSelection, | ||||
} from 'lib/shared/mention-utils.js'; | } from 'lib/shared/mention-utils.js'; | ||||
import type { RelativeMemberInfo } from 'lib/types/thread-types.js'; | import type { RelativeMemberInfo } from 'lib/types/thread-types.js'; | ||||
import Avatar from '../components/avatar.react.js'; | import Avatar from '../components/avatar.react.js'; | ||||
import Button from '../components/button.react.js'; | import Button from '../components/button.react.js'; | ||||
import { useStyles } from '../themes/colors.js'; | import { useStyles } from '../themes/colors.js'; | ||||
import { useShouldRenderAvatars } from '../utils/avatar-utils.js'; | |||||
export type TypeaheadTooltipProps = { | export type TypeaheadTooltipProps = { | ||||
+text: string, | +text: string, | ||||
+matchedStrings: TypeaheadMatchedStrings, | +matchedStrings: TypeaheadMatchedStrings, | ||||
+suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>, | +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>, | ||||
+focusAndUpdateTextAndSelection: (text: string, selection: Selection) => void, | +focusAndUpdateTextAndSelection: (text: string, selection: Selection) => void, | ||||
}; | }; | ||||
function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node { | function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node { | ||||
const { | const { | ||||
text, | text, | ||||
matchedStrings, | matchedStrings, | ||||
suggestedUsers, | suggestedUsers, | ||||
focusAndUpdateTextAndSelection, | focusAndUpdateTextAndSelection, | ||||
} = props; | } = props; | ||||
const shouldRenderAvatars = useShouldRenderAvatars(); | |||||
const { textBeforeAtSymbol, usernamePrefix } = matchedStrings; | const { textBeforeAtSymbol, usernamePrefix } = matchedStrings; | ||||
const styles = useStyles(unboundStyles); | const styles = useStyles(unboundStyles); | ||||
const marginLeftStyle = React.useMemo( | |||||
() => ({ | |||||
marginLeft: shouldRenderAvatars ? 8 : 0, | |||||
}), | |||||
[shouldRenderAvatars], | |||||
); | |||||
const renderTypeaheadButton = React.useCallback( | const renderTypeaheadButton = React.useCallback( | ||||
({ item }: { item: RelativeMemberInfo, ... }) => { | ({ item }: { item: RelativeMemberInfo, ... }) => { | ||||
const onPress = () => { | const onPress = () => { | ||||
const { newText, newSelectionStart } = getNewTextAndSelection( | const { newText, newSelectionStart } = getNewTextAndSelection( | ||||
textBeforeAtSymbol, | textBeforeAtSymbol, | ||||
text, | text, | ||||
usernamePrefix, | usernamePrefix, | ||||
item, | item, | ||||
); | ); | ||||
focusAndUpdateTextAndSelection(newText, { | focusAndUpdateTextAndSelection(newText, { | ||||
start: newSelectionStart, | start: newSelectionStart, | ||||
end: newSelectionStart, | end: newSelectionStart, | ||||
}); | }); | ||||
}; | }; | ||||
const avatarInfo = getAvatarForUser(item); | const avatarInfo = getAvatarForUser(item); | ||||
return ( | return ( | ||||
<Button onPress={onPress} style={styles.button} iosActiveOpacity={0.85}> | <Button onPress={onPress} style={styles.button} iosActiveOpacity={0.85}> | ||||
<Avatar size="small" avatarInfo={avatarInfo} /> | <Avatar size="small" avatarInfo={avatarInfo} /> | ||||
<Text style={styles.buttonLabel} numberOfLines={1}> | <Text style={[styles.buttonLabel, marginLeftStyle]} numberOfLines={1}> | ||||
@{item.username} | @{item.username} | ||||
</Text> | </Text> | ||||
</Button> | </Button> | ||||
); | ); | ||||
}, | }, | ||||
[ | [ | ||||
focusAndUpdateTextAndSelection, | |||||
styles.button, | styles.button, | ||||
styles.buttonLabel, | styles.buttonLabel, | ||||
text, | marginLeftStyle, | ||||
textBeforeAtSymbol, | textBeforeAtSymbol, | ||||
text, | |||||
usernamePrefix, | usernamePrefix, | ||||
focusAndUpdateTextAndSelection, | |||||
], | ], | ||||
); | ); | ||||
// This is a hack that was introduced due to a buggy behavior of a | // This is a hack that was introduced due to a buggy behavior of a | ||||
// absolutely positioned FlatList on Android. | // absolutely positioned FlatList on Android. | ||||
// There was a bug that was present when there were too few items in a | // There was a bug that was present when there were too few items in a | ||||
// FlatList and it wasn't scrollable. It was only present on Android as | // FlatList and it wasn't scrollable. It was only present on Android as | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | button: { | ||||
innerHeight: 24, | innerHeight: 24, | ||||
padding: 8, | padding: 8, | ||||
color: 'typeaheadTooltipText', | color: 'typeaheadTooltipText', | ||||
}, | }, | ||||
buttonLabel: { | buttonLabel: { | ||||
color: 'white', | color: 'white', | ||||
fontSize: 16, | fontSize: 16, | ||||
fontWeight: '400', | fontWeight: '400', | ||||
marginLeft: 8, | |||||
}, | }, | ||||
}; | }; | ||||
export default TypeaheadTooltip; | export default TypeaheadTooltip; |