SendMessageView.tsx 5.1 Ko
Télécharger le fichier
import { ModeratorInitData, ModMessageMessageComposer } from '@octane/renderer';
import { FC, useMemo, useRef, useState } from 'react';
import { localizeWithFallback, SendMessageComposer } from '../../../api';
import { showModAlert } from '../../../hooks';
import sendMessagesXml from '../../../assets/mod-tools/xml/send_msgs.xml?raw';
import { NativeWindowShell } from '../native/NativeWindowShell';
import { findNativeNode, nativeCaption, nativeNumber, NativeNode, parseNativeLayout } from '../native/NativeLayout';
import { Native0Button, Native0Dropmenu, Native0Frame, Native0Input, Native0Text } from '../native/NativeWindow0';
import { NativeTextTree } from '../../../common/native-text/NativeTextTree';
const rectOf = (node: NativeNode) => ({ x: nativeNumber(node, 'x'), y: nativeNumber(node, 'y'), width: nativeNumber(node, 'width'), height: nativeNumber(node, 'height') });
/** `$pe._rfaec9bccb2e7a4`: the topic id the free message carries. */
const SEND_MESSAGE_TOPIC = -999;
export interface SendMessageProps {
userId: number;
userName: string;
settings: ModeratorInitData;
x: number;
y: number;
onClose: () => void;
}
// Classic v75 send_msgs window ($pe): the caption is "Msg To: <name>", the first focus of the field clears its hint text, a template from the menu replaces the field text,
// and sending an empty (or still hinted) field raises the alert; otherwise the message goes out with the issue id of the moderator tool and the window closes. The character
// count under the field is kept from the earlier message window.
export const SendMessageView: FC<SendMessageProps> = ({ userId, userName, settings, x, y, onClose }) => {
const root = useMemo(() => parseNativeLayout(sendMessagesXml), []);
const menu = rectOf(findNativeNode(root, 'msgTemplatesSelect'));
const input = findNativeNode(root, 'message_input');
const send = findNativeNode(root, 'send_message_but');
const [message, setMessage] = useState(nativeCaption(input));
const [isHint, setIsHint] = useState(true);
const [inputActive, setInputActive] = useState(false);
const [selectedTemplate, setSelectedTemplate] = useState(-1);
const templates = settings.messageTemplates ?? [];
// the window is disposed by its first send: a second click before it is gone must not send again
const sentRef = useRef(false);
const onSend = () => {
if (sentRef.current) return;
if (isHint || message === '') {
showModAlert('You must input a message to the user');
return;
}
sentRef.current = true;
SendMessageComposer(new ModMessageMessageComposer(userId, message, SEND_MESSAGE_TOPIC));
onClose();
};
return (
<NativeTextTree>
<NativeWindowShell type="sendMessage" windowKey={userName} x={x} y={y}>
<Native0Frame caption={`Msg To: ${userName}`} height={nativeNumber(root, 'height')} width={nativeNumber(root, 'width')} onClose={onClose}>
<Native0Input
active={inputActive}
height={nativeNumber(input, 'height')}
value={message}
width={nativeNumber(input, 'width')}
x={nativeNumber(input, 'x')}
y={nativeNumber(input, 'y')}
onChange={(value) => setMessage(value)}
onFocus={() => {
if (isHint) {
setMessage('');
setIsHint(false);
}
setInputActive(true);
}}
/>
{!isHint && (
<Native0Text
color={0xffffff}
text={localizeWithFallback('modtools.native.chars', `${message.trim().length} characters`, ['count'], [`${message.trim().length}`])}
width={nativeNumber(input, 'width')}
x={nativeNumber(input, 'x')}
y={nativeNumber(input, 'y') + nativeNumber(input, 'height') + 4}
/>
)}
<Native0Button height={nativeNumber(send, 'height')} label={nativeCaption(send)} width={nativeNumber(send, 'width')} x={nativeNumber(send, 'x')} y={nativeNumber(send, 'y')} onClick={onSend} />
<Native0Dropmenu
caption={selectedTemplate >= 0 ? templates[selectedTemplate] : nativeCaption(findNativeNode(root, 'msgTemplatesSelect'))}
height={menu.height}
items={templates}
width={menu.width}
x={menu.x}
y={menu.y}
onSelect={(index) => {
setSelectedTemplate(index);
setMessage(templates[index]);
setIsHint(false);
setInputActive(true);
}}
/>
</Native0Frame>
</NativeWindowShell>
</NativeTextTree>
);
};
