Typing indicator send
This commit is contained in:
@@ -206,17 +206,41 @@ function MessageInput({
|
|||||||
text,
|
text,
|
||||||
setText,
|
setText,
|
||||||
onEnter,
|
onEnter,
|
||||||
|
onTyping,
|
||||||
}: {
|
}: {
|
||||||
text: string;
|
text: string;
|
||||||
setText: SetState<string>;
|
setText: SetState<string>;
|
||||||
onEnter: () => void;
|
onEnter: () => void;
|
||||||
|
onTyping?: () => void;
|
||||||
}) {
|
}) {
|
||||||
|
const TYPING_INTERVAL = 2000;
|
||||||
const inputRef = useRef<any>(null);
|
const inputRef = useRef<any>(null);
|
||||||
|
const lastTypingSent = useRef(0);
|
||||||
|
const stopTypingTimeout = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
inputRef.current?.focus();
|
inputRef.current?.focus();
|
||||||
}, [inputRef]);
|
}, [inputRef]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!onTyping || !text) return;
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
if (now - lastTypingSent.current > TYPING_INTERVAL) {
|
||||||
|
lastTypingSent.current = now;
|
||||||
|
onTyping();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopTypingTimeout.current) {
|
||||||
|
clearTimeout(stopTypingTimeout.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
stopTypingTimeout.current = setTimeout(() => {
|
||||||
|
lastTypingSent.current = 0;
|
||||||
|
}, TYPING_INTERVAL);
|
||||||
|
}, [text]);
|
||||||
|
|
||||||
return text.includes("\n") ? (
|
return text.includes("\n") ? (
|
||||||
<Textarea
|
<Textarea
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
@@ -250,7 +274,9 @@ function MessageInput({
|
|||||||
placeholder="Type a message..."
|
placeholder="Type a message..."
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
value={text}
|
value={text}
|
||||||
onChange={(e) => setText(e.target.value)}
|
onChange={(e) => {
|
||||||
|
setText(e.target.value);
|
||||||
|
}}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
@@ -381,7 +407,21 @@ export default function MessageBox({
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
<footer className="flex gap-3 pr-5 w-full h-max">
|
<footer className="flex gap-3 pr-5 w-full h-max">
|
||||||
<MessageInput text={text} setText={setText} onEnter={sendMessage} />
|
<MessageInput
|
||||||
|
text={text}
|
||||||
|
setText={setText}
|
||||||
|
onEnter={sendMessage}
|
||||||
|
onTyping={() => {
|
||||||
|
console.log("Typing..");
|
||||||
|
if (!app.currentChannel) return;
|
||||||
|
sendRequest({
|
||||||
|
type: "typing",
|
||||||
|
params: {
|
||||||
|
channel_id: app.currentChannel.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ export type ClientMessage =
|
|||||||
| MessageType<"send_message", { channel_id: string; contents: string }>
|
| MessageType<"send_message", { channel_id: string; contents: string }>
|
||||||
| MessageType<"delete_message", { message_id: number }>
|
| MessageType<"delete_message", { message_id: number }>
|
||||||
| MessageType<"edit_message", { message_id: number; new_contents: string }>
|
| MessageType<"edit_message", { message_id: number; new_contents: string }>
|
||||||
| MessageType<"load_chunk", { channel_id: string; chunk_id: number }>;
|
| MessageType<"load_chunk", { channel_id: string; chunk_id: number }>
|
||||||
|
| MessageType<"typing", { channel_id: string }>;
|
||||||
|
|||||||
Reference in New Issue
Block a user