You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/client/web/src/components/ChatBox/ChatInputBox/input.tsx

97 lines
3.1 KiB
TypeScript

import { UserListItem } from '@/components/UserListItem';
import { getMessageTextDecorators, useGroupIdContext } from '@/plugin/common';
import { stopPropagation } from '@/utils/dom-helper';
import React from 'react';
import { Mention, MentionsInput } from 'react-mentions';
import { getGroupConfigWithInfo, t, useGroupInfo } from 'tailchat-shared';
import { useChatInputMentionsContext } from './context';
import { MentionCommandItem } from './MentionCommandItem';
import './input.less';
const defaultChatInputBoxInputStyle = {
input: {
overflow: 'auto',
maxHeight: 70,
},
highlighter: {
boxSizing: 'border-box',
overflow: 'hidden',
maxHeight: 70,
},
};
interface ChatInputBoxInputProps
extends Omit<
React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>,
'value' | 'onChange'
> {
inputRef?: React.Ref<HTMLInputElement>;
value: string;
onChange: (message: string, mentions: string[]) => void;
}
export const ChatInputBoxInput: React.FC<ChatInputBoxInputProps> = React.memo(
(props) => {
const { users, panels, placeholder, disabled } =
useChatInputMentionsContext();
const groupId = useGroupIdContext();
const groupInfo = useGroupInfo(groupId);
const { hideGroupMemberDiscriminator } = getGroupConfigWithInfo(groupInfo);
return (
<MentionsInput
inputRef={props.inputRef}
className="chatbox-mention-input"
placeholder={placeholder ?? t('输入一些什么')}
disabled={disabled}
style={defaultChatInputBoxInputStyle}
maxLength={1000}
value={props.value}
onChange={(e, newValue, _, mentions) =>
props.onChange(
newValue,
mentions.filter((m) => m.display.startsWith('@')).map((m) => m.id) // 仅处理mention的数据进行记录
)
}
onKeyDown={props.onKeyDown}
onPaste={props.onPaste}
onContextMenu={stopPropagation}
allowSuggestionsAboveCursor={true}
forceSuggestionsAboveCursor={true}
>
<Mention
trigger="@"
data={
(query) =>
(users ?? [])
.filter((u) => u.display?.includes(query))
.slice(0, 20) // max display 20 item at most
}
displayTransform={(id, display) => `@${display}`}
appendSpaceOnAdd={true}
renderSuggestion={(suggestion) => (
<UserListItem
userId={String(suggestion.id)}
hideDiscriminator={hideGroupMemberDiscriminator}
/>
)}
markup={getMessageTextDecorators().mention('__id__', '__display__')}
/>
<Mention
trigger="#"
data={panels ?? []}
displayTransform={(id, display) => `#${display}`}
appendSpaceOnAdd={true}
renderSuggestion={(suggestion) => (
<MentionCommandItem
icon="mdi:pound"
label={suggestion.display ?? String(suggestion.id)}
/>
)}
markup={getMessageTextDecorators().url('__id__', '#__display__')}
/>
</MentionsInput>
);
}
);
ChatInputBoxInput.displayName = 'ChatInputBoxInput';