Page MenuHomePhabricator

D8910.id31441.diff
No OneTemporary

D8910.id31441.diff

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
@@ -5,10 +5,11 @@
import { threadOtherMembers, chatNameMaxLength } from './thread-utils.js';
import { stringForUserExplicit } from './user-utils.js';
import { threadTypes } from '../types/thread-types-enum.js';
-import {
- type ThreadInfo,
- type RelativeMemberInfo,
- type ResolvedThreadInfo,
+import type {
+ ThreadInfo,
+ RelativeMemberInfo,
+ ResolvedThreadInfo,
+ ChatMentionCandidates,
} from '../types/thread-types.js';
import { idSchemaRegex } from '../utils/validation-utils.js';
@@ -108,6 +109,28 @@
.map(userInfo => ({ type: 'user', userInfo }));
}
+function getMentionTypeaheadChatSuggestions(
+ chatSearchIndex: SentencePrefixSearchIndex,
+ chatMentionCandidates: ChatMentionCandidates,
+ chatPrefix: string,
+): $ReadOnlyArray<MentionTypeaheadChatSuggestionItem> {
+ const result = [];
+ const threadIDs =
+ chatPrefix.length === 0
+ ? chatSearchIndex.entries
+ : chatSearchIndex.getSearchResults(chatPrefix);
+ for (const threadID of threadIDs) {
+ if (!chatMentionCandidates[threadID]) {
+ continue;
+ }
+ result.push({
+ type: 'chat',
+ threadInfo: chatMentionCandidates[threadID],
+ });
+ }
+ return result;
+}
+
function getNewTextAndSelection(
textBeforeAtSymbol: string,
entireText: string,
@@ -150,6 +173,7 @@
isUserMentioned,
extractUserMentionsFromText,
getMentionTypeaheadUserSuggestions,
+ getMentionTypeaheadChatSuggestions,
getNewTextAndSelection,
getTypeaheadRegexMatches,
getUserMentionsCandidates,
diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js
--- a/lib/shared/thread-utils.js
+++ b/lib/shared/thread-utils.js
@@ -112,8 +112,8 @@
const chatNameMaxLength = 191;
const chatNameMinLength = 0;
const secondCharRange = `{${chatNameMinLength},${chatNameMaxLength}}`;
-const validChatNameRegexString = `^.${secondCharRange}$`;
-const validChatNameRegex: RegExp = new RegExp(validChatNameRegexString);
+const validChatNameRegexString = `.${secondCharRange}`;
+const validChatNameRegex: RegExp = new RegExp(`^${validChatNameRegexString}$`);
function threadHasPermission(
threadInfo: ?(ThreadInfo | RawThreadInfo),
@@ -1901,6 +1901,7 @@
getAvailableThreadMemberActions,
threadMembersWithoutAddedAshoat,
validChatNameRegex,
+ validChatNameRegexString,
chatNameMaxLength,
patchThreadInfoToIncludeMentionedMembersOfParent,
threadInfoInsideCommunity,
diff --git a/native/avatars/thread-avatar.react.js b/native/avatars/thread-avatar.react.js
--- a/native/avatars/thread-avatar.react.js
+++ b/native/avatars/thread-avatar.react.js
@@ -8,13 +8,17 @@
} from 'lib/shared/avatar-utils.js';
import { getSingleOtherUser } from 'lib/shared/thread-utils.js';
import { threadTypes } from 'lib/types/thread-types-enum.js';
-import { type RawThreadInfo, type ThreadInfo } from 'lib/types/thread-types.js';
+import type {
+ RawThreadInfo,
+ ThreadInfo,
+ ResolvedThreadInfo,
+} from 'lib/types/thread-types.js';
import Avatar, { type AvatarSize } from './avatar.react.js';
import { useSelector } from '../redux/redux-utils.js';
type Props = {
- +threadInfo: RawThreadInfo | ThreadInfo,
+ +threadInfo: RawThreadInfo | ThreadInfo | ResolvedThreadInfo,
+size: AvatarSize,
};
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
@@ -38,6 +38,7 @@
import { useEditMessage } from 'lib/shared/edit-messages-utils.js';
import {
getMentionTypeaheadUserSuggestions,
+ getMentionTypeaheadChatSuggestions,
getTypeaheadRegexMatches,
type Selection,
getUserMentionsCandidates,
@@ -58,6 +59,7 @@
checkIfDefaultMembersAreVoiced,
draftKeyFromThreadID,
useThreadChatMentionCandidates,
+ useThreadChatMentionSearchIndex,
} from 'lib/shared/thread-utils.js';
import type { CalendarQuery } from 'lib/types/entry-types.js';
import type { LoadingStatus } from 'lib/types/loading-types.js';
@@ -74,6 +76,7 @@
ClientThreadJoinRequest,
ThreadJoinPayload,
RelativeMemberInfo,
+ ChatMentionCandidates,
} from 'lib/types/thread-types.js';
import { type UserInfos } from 'lib/types/user-types.js';
import {
@@ -173,6 +176,8 @@
+inputState: ?InputState,
+userSearchIndex: SentencePrefixSearchIndex,
+userMentionsCandidates: $ReadOnlyArray<RelativeMemberInfo>,
+ +chatMentionSearchIndex: SentencePrefixSearchIndex,
+ +chatMentionCandidates: ChatMentionCandidates,
+parentThreadInfo: ?ThreadInfo,
+editedMessagePreview: ?MessagePreviewResult,
+editedMessageInfo: ?MessageInfo,
@@ -565,13 +570,19 @@
this.props.viewerID,
typeaheadMatchedStrings.query,
);
+ const suggestedChats = getMentionTypeaheadChatSuggestions(
+ this.props.chatMentionSearchIndex,
+ this.props.chatMentionCandidates,
+ typeaheadMatchedStrings.query,
+ );
+ const suggestions = [...suggestedUsers, ...suggestedChats];
- if (suggestedUsers.length > 0) {
+ if (suggestions.length > 0) {
typeaheadTooltip = (
<TypeaheadTooltip
text={this.state.text}
matchedStrings={typeaheadMatchedStrings}
- suggestions={suggestedUsers}
+ suggestions={suggestions}
focusAndUpdateTextAndSelection={this.focusAndUpdateTextAndSelection}
typeaheadTooltipActionsGetter={mentionTypeaheadTooltipActions}
TypeaheadTooltipButtonComponent={MentionTypeaheadTooltipButton}
@@ -1255,6 +1266,10 @@
const userSearchIndex = useSelector(userStoreMentionSearchIndex);
+ const chatMentionSearchIndex = useThreadChatMentionSearchIndex(
+ props.threadInfo,
+ );
+
const { parentThreadID } = props.threadInfo;
const parentThreadInfo = useSelector(state =>
parentThreadID ? threadInfoSelector(state)[parentThreadID] : null,
@@ -1299,6 +1314,8 @@
inputState={inputState}
userSearchIndex={userSearchIndex}
userMentionsCandidates={userMentionsCandidates}
+ chatMentionSearchIndex={chatMentionSearchIndex}
+ chatMentionCandidates={chatMentionCandidates}
parentThreadInfo={parentThreadInfo}
editedMessagePreview={editedMessagePreview}
editedMessageInfo={editedMessageInfo}
diff --git a/native/chat/mention-typeahead-tooltip-button.react.js b/native/chat/mention-typeahead-tooltip-button.react.js
--- a/native/chat/mention-typeahead-tooltip-button.react.js
+++ b/native/chat/mention-typeahead-tooltip-button.react.js
@@ -8,6 +8,7 @@
MentionTypeaheadSuggestionItem,
} from 'lib/shared/mention-utils.js';
+import ThreadAvatar from '../avatars/thread-avatar.react.js';
import UserAvatar from '../avatars/user-avatar.react.js';
import Button from '../components/button.react.js';
import { useStyles } from '../themes/colors.js';
@@ -26,6 +27,14 @@
<UserAvatar size="small" userID={item.actionButtonContent.userInfo.id} />
);
typeaheadTooltipButtonText = item.actionButtonContent.userInfo.username;
+ } else if (item.actionButtonContent.type === 'chat') {
+ typeaheadTooltipButtonText = item.actionButtonContent.threadInfo.uiName;
+ avatarComponent = (
+ <ThreadAvatar
+ size="small"
+ threadInfo={item.actionButtonContent.threadInfo}
+ />
+ );
}
return (
diff --git a/native/utils/typeahead-utils.js b/native/utils/typeahead-utils.js
--- a/native/utils/typeahead-utils.js
+++ b/native/utils/typeahead-utils.js
@@ -2,7 +2,6 @@
import * as React from 'react';
-import { oldValidUsernameRegexString } from 'lib/shared/account-utils.js';
import {
getNewTextAndSelection,
getRawChatMention,
@@ -10,12 +9,13 @@
type TypeaheadTooltipActionItem,
type MentionTypeaheadSuggestionItem,
} from 'lib/shared/mention-utils.js';
+import { validChatNameRegexString } from 'lib/shared/thread-utils.js';
import { stringForUserExplicit } from 'lib/shared/user-utils.js';
// Native regex is a little bit different than web one as
// there are no named capturing groups yet on native.
const nativeMentionTypeaheadRegex: RegExp = new RegExp(
- `((^(.|\n)*\\s+)|^)@(${oldValidUsernameRegexString})?$`,
+ `((^(.|\n)*\\s+)|^)@(${validChatNameRegexString})?$`,
);
export type TypeaheadTooltipActionsParams<SuggestionItemType> = {

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 24, 6:57 AM (20 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2574366
Default Alt Text
D8910.id31441.diff (8 KB)

Event Timeline