feat: 回复消息时聚焦消息输入框并自动在前面追加被艾特的人

pull/81/head
moonrailgun 3 years ago
parent a868c2abb7
commit f9f7c6ac9a

@ -1,5 +1,7 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import type { SendMessagePayload } from '../model/message'; import { useEffect } from 'react';
import { useUpdateRef } from '../hooks/useUpdateRef';
import type { ChatMessage, SendMessagePayload } from '../model/message';
/** /**
* *
@ -21,6 +23,13 @@ export interface SharedEventMap {
* *
*/ */
sendMessage: (payload: SendMessagePayload) => void; sendMessage: (payload: SendMessagePayload) => void;
/**
*
*
* null
*/
replyMessage: (payload: ChatMessage | null) => void;
} }
export type SharedEventType = keyof SharedEventMap; export type SharedEventType = keyof SharedEventMap;
@ -43,3 +52,22 @@ export const sharedEvent = {
bus.emit(eventName, ...args); bus.emit(eventName, ...args);
}, },
}; };
export function useSharedEventHandler<
T extends SharedEventType,
H extends SharedEventMap[T]
>(eventName: T, handler: H) {
const handlerRef = useUpdateRef(handler);
useEffect(() => {
const _handler: SharedEventMap[T] = (...args: any[]) => {
(handlerRef.current as any)(...args);
};
sharedEvent.on(eventName, _handler);
return () => {
sharedEvent.off(eventName, _handler);
};
}, []);
}

@ -30,7 +30,7 @@ export {
} from './contexts/GroupInfoContext'; } from './contexts/GroupInfoContext';
// event // event
export { sharedEvent } from './event/index'; export { sharedEvent, useSharedEventHandler } from './event/index';
// helper // helper
export { getDMConverseName } from './helper/converse-helper'; export { getDMConverseName } from './helper/converse-helper';

@ -6,7 +6,12 @@ import { ClipboardHelper } from './clipboard-helper';
import { ChatInputActionContext } from './context'; import { ChatInputActionContext } from './context';
import { uploadMessageImage } from './utils'; import { uploadMessageImage } from './utils';
import { ChatInputBoxInput } from './input'; import { ChatInputBoxInput } from './input';
import type { SendMessagePayloadMeta } from 'tailchat-shared'; import {
getCachedUserInfo,
isValidStr,
SendMessagePayloadMeta,
useSharedEventHandler,
} from 'tailchat-shared';
interface ChatInputBoxProps { interface ChatInputBoxProps {
onSendMsg: (msg: string, meta?: SendMessagePayloadMeta) => void; onSendMsg: (msg: string, meta?: SendMessagePayloadMeta) => void;
@ -50,6 +55,22 @@ export const ChatInputBox: React.FC<ChatInputBoxProps> = React.memo((props) => {
[props.onSendMsg] [props.onSendMsg]
); );
useSharedEventHandler('replyMessage', async (payload) => {
if (inputRef.current) {
inputRef.current.focus();
console.log(payload);
if (payload && isValidStr(payload?.author)) {
const userInfo = await getCachedUserInfo(payload.author);
setMessage(
`${getMessageTextDecorators().mention(
payload.author,
userInfo.nickname
)} ${message}`
);
}
}
});
return ( return (
<ChatInputActionContext.Provider value={{ sendMsg: props.onSendMsg }}> <ChatInputActionContext.Provider value={{ sendMsg: props.onSendMsg }}>
<div className="px-4 py-2"> <div className="px-4 py-2">

@ -5,6 +5,7 @@ import {
ChatMessage, ChatMessage,
deleteMessage, deleteMessage,
recallMessage, recallMessage,
sharedEvent,
t, t,
useAsyncRequest, useAsyncRequest,
useChatBoxContext, useChatBoxContext,
@ -45,7 +46,7 @@ export function useChatMessageItemAction(
<Menu.Item <Menu.Item
key="reply" key="reply"
icon={<Icon icon="mdi:reply" />} icon={<Icon icon="mdi:reply" />}
onClick={() => context.setReplyMsg(payload)} onClick={() => sharedEvent.emit('replyMessage', payload)}
> >
{t('回复')} {t('回复')}
</Menu.Item> </Menu.Item>

@ -1,12 +1,20 @@
import React from 'react'; import React from 'react';
import { t, useChatBoxContext } from 'tailchat-shared'; import { t, useChatBoxContext, useSharedEventHandler } from 'tailchat-shared';
import _isNil from 'lodash/isNil'; import _isNil from 'lodash/isNil';
import { getMessageRender } from '@/plugin/common'; import { getMessageRender } from '@/plugin/common';
import { UserName } from '../UserName'; import { UserName } from '../UserName';
import { Icon } from '@/components/Icon'; import { Icon } from '@/components/Icon';
export const ChatReply: React.FC = React.memo(() => { export const ChatReply: React.FC = React.memo(() => {
const { replyMsg, clearReplyMsg } = useChatBoxContext(); const { replyMsg, setReplyMsg, clearReplyMsg } = useChatBoxContext();
useSharedEventHandler('replyMessage', (payload) => {
/**
*
*
*/
setReplyMsg(payload);
});
if (_isNil(replyMsg)) { if (_isNil(replyMsg)) {
return null; return null;

Loading…
Cancel
Save