mirror of https://github.com/msgbyte/tailchat
feat: 消息回复与显示
parent
312d96fb7a
commit
acceba8726
@ -0,0 +1,50 @@
|
||||
import React, { useCallback, useContext, useState } from 'react';
|
||||
import _noop from 'lodash/noop';
|
||||
import type { ReplyMsgType } from '../utils/msg-helper';
|
||||
|
||||
/**
|
||||
* 一个消息盒的上下文
|
||||
*/
|
||||
|
||||
interface ChatBoxContextProps {
|
||||
replyMsg: ReplyMsgType | null;
|
||||
setReplyMsg: (msg: ReplyMsgType | null) => void;
|
||||
}
|
||||
const ChatBoxContext = React.createContext<ChatBoxContextProps>({
|
||||
replyMsg: null,
|
||||
setReplyMsg: _noop,
|
||||
});
|
||||
ChatBoxContext.displayName = 'ChatBoxContext';
|
||||
|
||||
export const ChatBoxContextProvider: React.FC = React.memo((props) => {
|
||||
const [replyMsg, setReplyMsg] = useState<ReplyMsgType | null>(null);
|
||||
|
||||
return (
|
||||
<ChatBoxContext.Provider
|
||||
value={{
|
||||
replyMsg,
|
||||
setReplyMsg,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</ChatBoxContext.Provider>
|
||||
);
|
||||
});
|
||||
ChatBoxContextProvider.displayName = 'ChatBoxContextProvider';
|
||||
|
||||
export function useChatBoxContext(): ChatBoxContextProps & {
|
||||
hasContext: boolean;
|
||||
clearReplyMsg: () => void;
|
||||
} {
|
||||
const context = useContext(ChatBoxContext);
|
||||
const clearReplyMsg = useCallback(() => {
|
||||
context.setReplyMsg(null);
|
||||
}, [context.setReplyMsg]);
|
||||
|
||||
return {
|
||||
hasContext: context.setReplyMsg !== _noop,
|
||||
replyMsg: context.replyMsg,
|
||||
setReplyMsg: context.setReplyMsg,
|
||||
clearReplyMsg,
|
||||
};
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
import type { ChatMessage } from '../model/message';
|
||||
|
||||
const replyMsgFields = ['_id', 'content', 'author'] as const;
|
||||
export type ReplyMsgType = Pick<ChatMessage, typeof replyMsgFields[number]>;
|
@ -0,0 +1,22 @@
|
||||
import { Skeleton } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
export const ChatBoxPlaceholder: React.FC = React.memo(() => {
|
||||
const paragraph = { rows: 1 };
|
||||
|
||||
return (
|
||||
<div className="px-2 w-2/3">
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
<Skeleton className="mb-2" avatar={true} paragraph={paragraph} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
ChatBoxPlaceholder.displayName = 'ChatBoxPlaceholder';
|
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { t, useChatBoxContext } from 'tailchat-shared';
|
||||
import _isNil from 'lodash/isNil';
|
||||
import { getMessageRender } from '@/plugin/common';
|
||||
import { UserName } from '../UserName';
|
||||
import { Icon } from '@iconify/react';
|
||||
|
||||
export const ChatReply: React.FC = React.memo(() => {
|
||||
const { replyMsg, clearReplyMsg } = useChatBoxContext();
|
||||
|
||||
if (_isNil(replyMsg)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="absolute bottom-0 left-0 right-0 py-1 px-4">
|
||||
<div className="rounded bg-white p-2 max-h-44 overflow-auto shadow-sm relative">
|
||||
<span className="align-top">
|
||||
{t('回复')}{' '}
|
||||
{replyMsg.author && <UserName userId={replyMsg.author} />}:{' '}
|
||||
</span>
|
||||
|
||||
<span>{getMessageRender(replyMsg.content)}</span>
|
||||
|
||||
<Icon
|
||||
className="absolute right-1 top-0.5 text-lg cursor-pointer opacity-60 hover:opacity-80"
|
||||
icon="mdi:close-circle-outline"
|
||||
onClick={clearReplyMsg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
ChatReply.displayName = 'ChatReply';
|
Loading…
Reference in New Issue