Page MenuHomePhabricator

D5876.diff
No OneTemporary

D5876.diff

diff --git a/lib/shared/typeahead-utils.js b/lib/shared/typeahead-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/shared/typeahead-utils.js
@@ -0,0 +1,26 @@
+// @flow
+
+import type { RelativeMemberInfo } from '../types/thread-types';
+import SearchIndex from './search-index';
+import { threadOtherMembers } from './thread-utils';
+import { stringForUserExplicit } from './user-utils';
+
+function getTypeaheadUserSuggestions(
+ userSearchIndex: SearchIndex,
+ threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
+ viewerID: ?string,
+ typedUsernamePrefix: string,
+): $ReadOnlyArray<RelativeMemberInfo> {
+ const userIDs = userSearchIndex.getSearchResults(typedUsernamePrefix);
+ const usersInThread = threadOtherMembers(threadMembers, viewerID);
+
+ return usersInThread
+ .filter(
+ user => typedUsernamePrefix.length === 0 || userIDs.includes(user.id),
+ )
+ .sort((userA, userB) =>
+ stringForUserExplicit(userA).localeCompare(stringForUserExplicit(userB)),
+ );
+}
+
+export { getTypeaheadUserSuggestions };
diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js
--- a/web/chat/chat-input-bar.react.js
+++ b/web/chat/chat-input-bar.react.js
@@ -51,9 +51,10 @@
import { useSelector } from '../redux/redux-utils';
import { nonThreadCalendarQuery } from '../selectors/nav-selectors';
import SWMansionIcon from '../SWMansionIcon.react';
+import { webTypeaheadRegex } from '../utils/typeahead-utils';
import css from './chat-input-bar.css';
import TypeaheadTooltip from './typeahead-tooltip.react';
-import { typeaheadRegex } from './typeahead-utils';
+
type BaseProps = {
+threadInfo: ThreadInfo,
+inputState: InputState,
@@ -77,7 +78,6 @@
+typeaheadMatchedStrings: ?TypeaheadMatchedStrings,
};
export type TypeaheadMatchedStrings = {
- +entireText: string,
+textBeforeAtSymbol: string,
+usernamePrefix: string,
};
@@ -573,7 +573,7 @@
() =>
inputSliceEndingAtCursor.length === props.inputState.draft.length ||
/\s/.test(props.inputState.draft[props.inputState.textCursorPosition])
- ? inputSliceEndingAtCursor.match(typeaheadRegex)
+ ? inputSliceEndingAtCursor.match(webTypeaheadRegex)
: null,
[
inputSliceEndingAtCursor,
@@ -586,9 +586,9 @@
() =>
typeaheadRegexMatches !== null
? {
- entireText: typeaheadRegexMatches[0],
- textBeforeAtSymbol: typeaheadRegexMatches[1],
- usernamePrefix: typeaheadRegexMatches[2],
+ textBeforeAtSymbol:
+ typeaheadRegexMatches.groups?.textPrefix ?? '',
+ usernamePrefix: typeaheadRegexMatches.groups?.username ?? '',
}
: null,
[typeaheadRegexMatches],
diff --git a/web/chat/typeahead-tooltip.react.js b/web/chat/typeahead-tooltip.react.js
--- a/web/chat/typeahead-tooltip.react.js
+++ b/web/chat/typeahead-tooltip.react.js
@@ -4,20 +4,19 @@
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 { InputState } from '../input/input-state';
-import { type TypeaheadMatchedStrings } from './chat-input-bar.react';
-import css from './typeahead-tooltip.css';
import {
getTypeaheadOverlayScroll,
getTypeaheadTooltipActions,
getTypeaheadTooltipButtons,
getTypeaheadTooltipPosition,
- getTypeaheadUserSuggestions,
getTypeaheadChosenActionPosition,
-} from './typeahead-utils';
+} from '../utils/typeahead-utils';
+import { type TypeaheadMatchedStrings } from './chat-input-bar.react';
+import css from './typeahead-tooltip.css';
export type TypeaheadTooltipProps = {
+inputState: InputState,
@@ -38,13 +37,9 @@
matchedStrings,
} = props;
- const {
- entireText: matchedText,
- textBeforeAtSymbol: matchedTextBeforeAtSymbol,
- usernamePrefix: matchedUsernamePrefix,
- } = matchedStrings;
+ const { textBeforeAtSymbol, usernamePrefix } = matchedStrings;
- const typedPrefix = matchedUsernamePrefix ?? '';
+ const typedUsernamePrefix = usernamePrefix ?? '';
const [isAnimation, setIsAnimation] = React.useState(false);
const overlayRef = React.useRef<?HTMLDivElement>();
@@ -59,10 +54,11 @@
() =>
getTypeaheadUserSuggestions(
userSearchIndex,
- threadOtherMembers(threadMembers, viewerID),
- typedPrefix,
+ threadMembers,
+ viewerID,
+ typedUsernamePrefix,
),
- [userSearchIndex, threadMembers, viewerID, typedPrefix],
+ [userSearchIndex, threadMembers, viewerID, typedUsernamePrefix],
);
const actions = React.useMemo(
@@ -72,27 +68,23 @@
inputStateSetDraft: inputState.setDraft,
inputStateSetTextCursorPosition: inputState.setTextCursorPosition,
suggestedUsers,
- matchedTextBeforeAtSymbol,
- matchedText,
+ textBeforeAtSymbol,
+ typedUsernamePrefix,
}),
[
inputState.draft,
inputState.setDraft,
inputState.setTextCursorPosition,
suggestedUsers,
- matchedTextBeforeAtSymbol,
- matchedText,
+ textBeforeAtSymbol,
+ typedUsernamePrefix,
],
);
const tooltipPosition = React.useMemo(
() =>
- getTypeaheadTooltipPosition(
- textarea,
- actions.length,
- matchedTextBeforeAtSymbol,
- ),
- [textarea, actions.length, matchedTextBeforeAtSymbol],
+ getTypeaheadTooltipPosition(textarea, actions.length, textBeforeAtSymbol),
+ [textarea, actions.length, textBeforeAtSymbol],
);
const tooltipPositionStyle = React.useMemo(
diff --git a/web/chat/typeahead-utils.js b/web/utils/typeahead-utils.js
rename from web/chat/typeahead-utils.js
rename to web/utils/typeahead-utils.js
--- a/web/chat/typeahead-utils.js
+++ b/web/utils/typeahead-utils.js
@@ -4,16 +4,15 @@
import * as React from 'react';
import { oldValidUsernameRegexString } from 'lib/shared/account-utils';
-import SearchIndex from 'lib/shared/search-index';
import { stringForUserExplicit } from 'lib/shared/user-utils';
import type { RelativeMemberInfo } from 'lib/types/thread-types';
+import { typeaheadStyle } from '../chat/chat-constants';
+import css from '../chat/typeahead-tooltip.css';
import Button from '../components/button.react';
import type { TypeaheadState } from '../input/input-state';
-import { typeaheadStyle } from './chat-constants';
-import css from './typeahead-tooltip.css';
-const typeaheadRegex: RegExp = new RegExp(
+const webTypeaheadRegex: RegExp = new RegExp(
`(?<textPrefix>(?:^(?:.|\n)*\\s+)|^)@(?<username>${oldValidUsernameRegexString})?$`,
);
@@ -28,20 +27,6 @@
+left: number,
};
-function getTypeaheadUserSuggestions(
- userSearchIndex: SearchIndex,
- usersInThread: $ReadOnlyArray<RelativeMemberInfo>,
- typedPrefix: string,
-): $ReadOnlyArray<RelativeMemberInfo> {
- const userIDs = userSearchIndex.getSearchResults(typedPrefix);
-
- return usersInThread
- .filter(user => typedPrefix.length === 0 || userIDs.includes(user.id))
- .sort((userA, userB) =>
- stringForUserExplicit(userA).localeCompare(stringForUserExplicit(userB)),
- );
-}
-
function getCaretOffsets(
textarea: HTMLTextAreaElement,
text: string,
@@ -94,8 +79,8 @@
inputStateSetDraft: (draft: string) => void,
inputStateSetTextCursorPosition: (newPosition: number) => void,
suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
- matchedTextBeforeAtSymbol: string,
- matchedText: string,
+ textBeforeAtSymbol: string,
+ typedUsernamePrefix: string,
};
function getTypeaheadTooltipActions(
@@ -106,8 +91,8 @@
inputStateSetDraft,
inputStateSetTextCursorPosition,
suggestedUsers,
- matchedTextBeforeAtSymbol,
- matchedText,
+ textBeforeAtSymbol,
+ typedUsernamePrefix,
} = params;
return suggestedUsers
.filter(
@@ -116,9 +101,12 @@
.map(suggestedUser => ({
key: suggestedUser.id,
onClick: () => {
- const newPrefixText = matchedTextBeforeAtSymbol;
+ const newPrefixText = textBeforeAtSymbol;
+
+ const totalMatchLength =
+ textBeforeAtSymbol.length + typedUsernamePrefix.length + 1; // 1 for @ char
- let newSuffixText = inputStateDraft.slice(matchedText.length);
+ let newSuffixText = inputStateDraft.slice(totalMatchLength);
newSuffixText = (newSuffixText[0] !== ' ' ? ' ' : '') + newSuffixText;
const newText =
@@ -195,11 +183,11 @@
function getTypeaheadTooltipPosition(
textarea: HTMLTextAreaElement,
actionsLength: number,
- matchedTextBefore: string,
+ textBeforeAtSymbol: string,
): TooltipPosition {
const { caretTopOffset, caretLeftOffset } = getCaretOffsets(
textarea,
- matchedTextBefore,
+ textBeforeAtSymbol,
);
const textareaBoundingClientRect = textarea.getBoundingClientRect();
@@ -234,8 +222,7 @@
}
export {
- typeaheadRegex,
- getTypeaheadUserSuggestions,
+ webTypeaheadRegex,
getCaretOffsets,
getTypeaheadTooltipActions,
getTypeaheadTooltipButtons,

File Metadata

Mime Type
text/plain
Expires
Tue, Dec 3, 11:10 AM (21 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2611467
Default Alt Text
D5876.diff (9 KB)

Event Timeline