diff --git a/lib/shared/mention-utils.js b/lib/shared/mention-utils.js --- a/lib/shared/mention-utils.js +++ b/lib/shared/mention-utils.js @@ -83,20 +83,18 @@ function getNewTextAndSelection( textBeforeAtSymbol: string, entireText: string, - usernamePrefix: string, - user: RelativeMemberInfo, + textPrefix: string, + suggestionText: string, ): { newText: string, newSelectionStart: number, } { - const totalMatchLength = - textBeforeAtSymbol.length + usernamePrefix.length + 1; // 1 for @ char + const totalMatchLength = textBeforeAtSymbol.length + textPrefix.length + 1; // 1 for @ char let newSuffixText = entireText.slice(totalMatchLength); newSuffixText = (newSuffixText[0] !== ' ' ? ' ' : '') + newSuffixText; - const newText = - textBeforeAtSymbol + '@' + stringForUserExplicit(user) + newSuffixText; + const newText = textBeforeAtSymbol + suggestionText + newSuffixText; const newSelectionStart = newText.length - newSuffixText.length + 1; diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js --- a/native/chat/chat-input-bar.react.js +++ b/native/chat/chat-input-bar.react.js @@ -59,6 +59,7 @@ draftKeyFromThreadID, useThreadChatMentionCandidates, } from 'lib/shared/thread-utils.js'; +import { stringForUserExplicit } from 'lib/shared/user-utils.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { PhotoPaste } from 'lib/types/media-types.js'; @@ -90,6 +91,7 @@ } from './message-editing-context.react.js'; import type { RemoveEditMode } from './message-list-types.js'; import TypeaheadTooltip from './typeahead-tooltip.react.js'; +import UserAvatar from '../avatars/user-avatar.react.js'; import Button from '../components/button.react.js'; // eslint-disable-next-line import/extensions import ClearableTextInput from '../components/clearable-text-input.react'; @@ -495,6 +497,23 @@ return checkIfDefaultMembersAreVoiced(this.props.threadInfo); } + typeaheadTooltipButton = ({ item, suggestionText, styles }) => { + return ( + <> + + + {suggestionText} + + + ); + }; + + typeaheadTooltipSuggestionTextExtractor = ( + item: RelativeMemberInfo, + ): string => { + return `@${stringForUserExplicit(item)}`; + }; + render() { const isMember = viewerIsMember(this.props.threadInfo); const canJoin = threadHasPermission( @@ -567,8 +586,12 @@ ); } diff --git a/native/chat/typeahead-tooltip.react.js b/native/chat/typeahead-tooltip.react.js --- a/native/chat/typeahead-tooltip.react.js +++ b/native/chat/typeahead-tooltip.react.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react'; -import { Platform, Text } from 'react-native'; +import { Platform } from 'react-native'; import { PanGestureHandler, FlatList } from 'react-native-gesture-handler'; import { @@ -9,25 +9,33 @@ type Selection, getNewTextAndSelection, } from 'lib/shared/mention-utils.js'; -import type { RelativeMemberInfo } from 'lib/types/thread-types.js'; -import UserAvatar from '../avatars/user-avatar.react.js'; import Button from '../components/button.react.js'; import { useStyles } from '../themes/colors.js'; -export type TypeaheadTooltipProps = { +export type TypeaheadTooltipProps = { +text: string, +matchedStrings: TypeaheadMatchedStrings, - +suggestedUsers: $ReadOnlyArray, + +suggestions: $ReadOnlyArray, +focusAndUpdateTextAndSelection: (text: string, selection: Selection) => void, + +typeaheadButtonRenderer: ({ + +item: EntryType, + +suggestionText: string, + +styles: typeof unboundStyles, + }) => React.Node, + +suggestionTextExtractor: (entry: EntryType) => string, }; -function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node { +function TypeaheadTooltip( + props: TypeaheadTooltipProps, +): React.Node { const { text, matchedStrings, - suggestedUsers, + suggestions, focusAndUpdateTextAndSelection, + typeaheadButtonRenderer, + suggestionTextExtractor, } = props; const { textBeforeAtSymbol, textPrefix } = matchedStrings; @@ -35,13 +43,14 @@ const styles = useStyles(unboundStyles); const renderTypeaheadButton = React.useCallback( - ({ item }: { item: RelativeMemberInfo, ... }) => { + ({ item }: { item: EntryType, ... }) => { + const suggestionText = suggestionTextExtractor(item); const onPress = () => { const { newText, newSelectionStart } = getNewTextAndSelection( textBeforeAtSymbol, text, textPrefix, - item, + suggestionText, ); focusAndUpdateTextAndSelection(newText, { @@ -52,16 +61,18 @@ return ( ); }, [ - styles.button, - styles.buttonLabel, + suggestionTextExtractor, + styles, + typeaheadButtonRenderer, textBeforeAtSymbol, text, textPrefix, @@ -95,7 +106,7 @@ @@ -104,7 +115,7 @@ renderTypeaheadButton, styles.container, styles.contentContainer, - suggestedUsers, + suggestions, ], ); diff --git a/web/utils/typeahead-utils.js b/web/utils/typeahead-utils.js --- a/web/utils/typeahead-utils.js +++ b/web/utils/typeahead-utils.js @@ -107,7 +107,7 @@ textBeforeAtSymbol, inputStateDraft, textPrefix, - suggestedUser, + stringForUserExplicit(suggestedUser), ); inputStateSetDraft(newText);