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 @@ -46,6 +46,7 @@ draftKeyFromThreadID, colorIsDark, } from 'lib/shared/thread-utils'; +import { getTypeaheadUserSuggestions } from 'lib/shared/typeahead-utils'; import type { CalendarQuery } from 'lib/types/entry-types'; import type { LoadingStatus } from 'lib/types/loading-types'; import type { PhotoPaste } from 'lib/types/media-types'; @@ -91,8 +92,10 @@ import { type AnimatedViewStyle, AnimatedView } from '../types/styles'; import { runTiming } from '../utils/animation-utils'; import { waitForAnimationFrameFlush } from '../utils/timers'; +import { nativeTypeaheadRegex } from '../utils/typeahead-utils'; import { ChatContext } from './chat-context'; import type { ChatNavigationProp } from './chat.react'; +import TypeaheadTooltip from './typeahead-tooltip.react'; /* eslint-disable import/no-named-as-default-member */ const { @@ -528,6 +531,56 @@ ); } + // we only try to match if there is end of text or whitespace after cursor + let typeaheadRegexMatches = null; + if ( + this.state.selection.start === this.state.selection.end && + (this.state.selection.start === this.state.text.length || + /\s/.test(this.state.text[this.state.selection.end])) + ) { + typeaheadRegexMatches = this.state.text + .slice(0, this.state.selection.start) + .match(nativeTypeaheadRegex); + } + + if ( + this.androidPreviousText && + this.state.selection.start === this.state.selection.end && + (this.state.selection.start === this.androidPreviousText.length || + /\s/.test(this.androidPreviousText[this.state.selection.end])) + ) { + typeaheadRegexMatches = this.androidPreviousText + .slice(0, this.state.selection.start) + .match(nativeTypeaheadRegex); + } + + let typeaheadTooltip = null; + + if (typeaheadRegexMatches) { + const typeaheadMatchedStrings = { + textBeforeAtSymbol: typeaheadRegexMatches[1] ?? '', + usernamePrefix: typeaheadRegexMatches[4] ?? '', + }; + + const suggestedUsers = getTypeaheadUserSuggestions( + this.props.userSearchIndex, + this.props.threadMembers, + this.props.viewerID, + typeaheadMatchedStrings.usernamePrefix, + ); + + if (suggestedUsers.length > 0) { + typeaheadTooltip = ( + + ); + } + } + let content; const defaultMembersAreVoiced = checkIfDefaultMembersAreVoiced( this.props.threadInfo, @@ -573,6 +626,7 @@ style={this.props.styles.container} onLayout={this.props.onInputBarLayout} > + {typeaheadTooltip} {joinButton} {content} {keyboardInputHost}