feat: 增加引用时可以跳转到某个面板

pull/70/head
moonrailgun 2 years ago
parent 998e7a6707
commit 1e00834b1a

@ -19,7 +19,8 @@ regMessageRender((message) => {
}); });
regMessageTextDecorators(() => ({ regMessageTextDecorators(() => ({
url: (plain) => `[url]${plain}[/url]`, url: (url, label?) =>
label ? `[url=${url}]${label}[/url]` : `[url]${url}[/url]`,
image: (plain, attrs) => { image: (plain, attrs) => {
if (attrs.height && attrs.width) { if (attrs.height && attrs.width) {
return `[img height=${attrs.height} width=${attrs.width}]${plain}[/img]`; return `[img height=${attrs.height} width=${attrs.width}]${plain}[/img]`;

@ -1,3 +1,4 @@
import { Link } from '@capital/component';
import React from 'react'; import React from 'react';
import type { TagProps } from '../bbcode/type'; import type { TagProps } from '../bbcode/type';
@ -6,6 +7,11 @@ export const UrlTag: React.FC<TagProps> = React.memo((props) => {
const text = node.content.join(''); const text = node.content.join('');
const url = node.attrs.url ?? text; const url = node.attrs.url ?? text;
if (url.startsWith('/') || url.startsWith(window.location.origin)) {
// 内部地址,使用 react-router 进行导航
return <Link to={url}>{text}</Link>;
}
return ( return (
<a href={url} title={text} target="_blank" rel="noopener noreferrer"> <a href={url} title={text} target="_blank" rel="noopener noreferrer">
{text} {text}

@ -142,7 +142,7 @@ export const App: React.FC = React.memo(() => {
} }
/> />
<Route path="/" element={<Navigate to="/entry" replace={true} />} /> <Route path="/*" element={<Navigate to="/entry" replace={true} />} />
</Routes> </Routes>
</AppContainer> </AppContainer>
</AppProvider> </AppProvider>

@ -0,0 +1,19 @@
import React from 'react';
import { Icon } from 'tailchat-design';
/**
*
*/
export const MentionCommandItem: React.FC<{
icon: string;
label: string;
}> = React.memo((props) => {
return (
<div className="flex items-center py-2 px-3">
<Icon className="mr-1 text-lg" icon={props.icon} />
<div>{props.label}</div>
</div>
);
});
MentionCommandItem.displayName = 'MentionCommandItem';

@ -24,6 +24,7 @@ export function useChatInputActionContext() {
*/ */
interface ChatInputMentionsContextProps extends PropsWithChildren { interface ChatInputMentionsContextProps extends PropsWithChildren {
users: SuggestionDataItem[]; users: SuggestionDataItem[];
panels: SuggestionDataItem[];
placeholder?: string; placeholder?: string;
disabled?: boolean; disabled?: boolean;
} }
@ -47,6 +48,7 @@ export function useChatInputMentionsContext(): ChatInputMentionsContextProps {
return { return {
users: context?.users ?? [], users: context?.users ?? [],
panels: context?.panels ?? [],
placeholder: context?.placeholder, placeholder: context?.placeholder,
disabled: context?.disabled, disabled: context?.disabled,
}; };

@ -6,6 +6,7 @@ import { Mention, MentionsInput } from 'react-mentions';
import { t } from 'tailchat-shared'; import { t } from 'tailchat-shared';
import { useChatInputMentionsContext } from './context'; import { useChatInputMentionsContext } from './context';
import './input.less'; import './input.less';
import { MentionCommandItem } from './MentionCommandItem';
interface ChatInputBoxInputProps interface ChatInputBoxInputProps
extends Omit< extends Omit<
@ -18,7 +19,8 @@ interface ChatInputBoxInputProps
} }
export const ChatInputBoxInput: React.FC<ChatInputBoxInputProps> = React.memo( export const ChatInputBoxInput: React.FC<ChatInputBoxInputProps> = React.memo(
(props) => { (props) => {
const { users, placeholder, disabled } = useChatInputMentionsContext(); const { users, panels, placeholder, disabled } =
useChatInputMentionsContext();
return ( return (
<MentionsInput <MentionsInput
@ -51,6 +53,16 @@ export const ChatInputBoxInput: React.FC<ChatInputBoxInputProps> = React.memo(
)} )}
markup={getMessageTextDecorators().mention('__id__', '__display__')} markup={getMessageTextDecorators().mention('__id__', '__display__')}
/> />
<Mention
trigger="#"
data={panels}
displayTransform={(id, display) => `#${display}`}
appendSpaceOnAdd={true}
renderSuggestion={(suggestion) => (
<MentionCommandItem icon="mdi:pound" label={suggestion.display} />
)}
markup={getMessageTextDecorators().url('__id__', '#__display__')}
/>
</MentionsInput> </MentionsInput>
); );
} }

@ -11,6 +11,8 @@ import {
useInterval, useInterval,
useHasGroupPermission, useHasGroupPermission,
PERMISSION, PERMISSION,
useGroupInfo,
GroupPanelType,
} from 'tailchat-shared'; } from 'tailchat-shared';
import { GroupPanelWrapper } from './Wrapper'; import { GroupPanelWrapper } from './Wrapper';
@ -68,10 +70,15 @@ interface TextPanelProps {
} }
export const TextPanel: React.FC<TextPanelProps> = React.memo( export const TextPanel: React.FC<TextPanelProps> = React.memo(
({ groupId, panelId }) => { ({ groupId, panelId }) => {
const group = useGroupInfo(groupId);
const groupMembers = useGroupMemberInfos(groupId); const groupMembers = useGroupMemberInfos(groupId);
const panelInfo = useGroupPanelInfo(groupId, panelId); const panelInfo = useGroupPanelInfo(groupId, panelId);
const { disabled, placeholder } = useChatInputInfo(groupId); const { disabled, placeholder } = useChatInputInfo(groupId);
if (!group) {
return null;
}
if (!panelInfo) { if (!panelInfo) {
return null; return null;
} }
@ -83,6 +90,12 @@ export const TextPanel: React.FC<TextPanelProps> = React.memo(
id: m._id, id: m._id,
display: m.nickname, display: m.nickname,
}))} }))}
panels={group.panels
.filter((p) => p.type !== GroupPanelType.GROUP)
.map((p) => ({
id: `/main/group/${groupId}/${p.id}`,
display: p.name,
}))}
disabled={disabled} disabled={disabled}
placeholder={placeholder} placeholder={placeholder}
> >

@ -117,7 +117,7 @@ export const [getMessageRender, regMessageRender] = buildRegFn<
* *
*/ */
const defaultMessageTextDecorators = { const defaultMessageTextDecorators = {
url: (plain: string) => plain, url: (url: string, label?: string) => url,
image: (plain: string, attrs: Record<string, unknown>) => plain, image: (plain: string, attrs: Record<string, unknown>) => plain,
mention: (userId: string, userName: string) => `@${userName}`, mention: (userId: string, userName: string) => `@${userName}`,
emoji: (emojiCode: string) => emojiCode, emoji: (emojiCode: string) => emojiCode,

@ -27,6 +27,7 @@ export {
createMetaFormSchema, createMetaFormSchema,
metaFormFieldSchema, metaFormFieldSchema,
} from 'tailchat-design'; } from 'tailchat-design';
export { Link } from 'react-router-dom';
export { Image } from '@/components/Image'; export { Image } from '@/components/Image';
export { IconBtn } from '@/components/IconBtn'; export { IconBtn } from '@/components/IconBtn';

Loading…
Cancel
Save