Changeset View
Changeset View
Standalone View
Standalone View
web/chat/typeahead-tooltip.react.js
// @flow | // @flow | ||||
import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import SearchIndex from 'lib/shared/search-index'; | |||||
import { threadOtherMembers } from 'lib/shared/thread-utils'; | |||||
import { getTypeaheadUserSuggestions } from 'lib/shared/typeahead-utils'; | |||||
import type { RelativeMemberInfo } from 'lib/types/thread-types'; | import type { RelativeMemberInfo } from 'lib/types/thread-types'; | ||||
import Button from '../components/button.react'; | import Button from '../components/button.react'; | ||||
import type { InputState } from '../input/input-state'; | import type { InputState } from '../input/input-state'; | ||||
import { | import { | ||||
getTypeaheadTooltipActions, | getTypeaheadTooltipActions, | ||||
getTypeaheadTooltipPosition, | getTypeaheadTooltipPosition, | ||||
} from '../utils/typeahead-utils'; | } from '../utils/typeahead-utils'; | ||||
import type { TypeaheadMatchedStrings } from './chat-input-bar.react'; | import type { TypeaheadMatchedStrings } from './chat-input-bar.react'; | ||||
import css from './typeahead-tooltip.css'; | import css from './typeahead-tooltip.css'; | ||||
export type TypeaheadTooltipProps = { | export type TypeaheadTooltipProps = { | ||||
+inputState: InputState, | +inputState: InputState, | ||||
+textarea: HTMLTextAreaElement, | +textarea: HTMLTextAreaElement, | ||||
+userSearchIndex: SearchIndex, | |||||
+threadMembers: $ReadOnlyArray<RelativeMemberInfo>, | |||||
+viewerID: ?string, | |||||
+matchedStrings: TypeaheadMatchedStrings, | +matchedStrings: TypeaheadMatchedStrings, | ||||
+suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>, | |||||
}; | }; | ||||
function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node { | function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node { | ||||
const { | const { inputState, textarea, matchedStrings, suggestedUsers } = props; | ||||
inputState, | |||||
textarea, | |||||
userSearchIndex, | |||||
threadMembers, | |||||
viewerID, | |||||
matchedStrings, | |||||
} = props; | |||||
const [isVisibleForAnimation, setIsVisibleForAnimation] = React.useState( | const [isVisibleForAnimation, setIsVisibleForAnimation] = React.useState( | ||||
false, | false, | ||||
); | ); | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setIsVisibleForAnimation(true); | setIsVisibleForAnimation(true); | ||||
return () => setIsVisibleForAnimation(false); | return () => setIsVisibleForAnimation(false); | ||||
}, []); | }, []); | ||||
const { | const { | ||||
entireText: matchedText, | entireText: matchedText, | ||||
textBeforeAtSymbol: matchedTextBeforeAtSymbol, | textBeforeAtSymbol: matchedTextBeforeAtSymbol, | ||||
usernamePrefix: matchedUsernamePrefix, | |||||
} = matchedStrings; | } = matchedStrings; | ||||
const typedPrefix = matchedUsernamePrefix ?? ''; | |||||
const suggestedUsers = React.useMemo( | |||||
() => | |||||
getTypeaheadUserSuggestions( | |||||
userSearchIndex, | |||||
threadOtherMembers(threadMembers, viewerID), | |||||
typedPrefix, | |||||
), | |||||
[userSearchIndex, threadMembers, viewerID, typedPrefix], | |||||
); | |||||
const actions = React.useMemo( | const actions = React.useMemo( | ||||
() => | () => | ||||
getTypeaheadTooltipActions( | getTypeaheadTooltipActions( | ||||
inputState, | inputState, | ||||
textarea, | textarea, | ||||
suggestedUsers, | suggestedUsers, | ||||
matchedTextBeforeAtSymbol, | matchedTextBeforeAtSymbol, | ||||
matchedText, | matchedText, | ||||
▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines |