mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-25 11:42:30 +01:00
typing indicators seem to work correctly now
This commit is contained in:
parent
534bc10531
commit
aa7a8327e4
@ -1,12 +1,12 @@
|
||||
import Channel from "../../stores/objects/Channel";
|
||||
|
||||
import { debounce } from "@mui/material";
|
||||
import { ChannelType } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import useLogger from "../../hooks/useLogger";
|
||||
import Guild from "../../stores/objects/Guild";
|
||||
import { debounce } from "../../utils/debounce";
|
||||
import MessageTextArea from "./MessageTextArea";
|
||||
import AttachmentUploadList from "./attachments/AttachmentUploadPreview";
|
||||
import FileUpload from "./attachments/FileUpload";
|
||||
@ -68,32 +68,39 @@ function MessageInput({ channel }: Props) {
|
||||
type: UploadStateType.NONE,
|
||||
files: [],
|
||||
});
|
||||
const [typing, setTyping] = React.useState<number | null>(null);
|
||||
const [typing, setTyping] = React.useState<number | boolean>();
|
||||
|
||||
/**
|
||||
* Starts typing for client user and triggers gateway event
|
||||
*/
|
||||
const startTyping = React.useCallback(() => {
|
||||
if (typing && typing > Date.now()) return;
|
||||
if (typeof typing === "number" && typing > +new Date()) return;
|
||||
|
||||
logger.debug("ShouldStartTyping");
|
||||
// TODO: send typing request
|
||||
setTyping(+Date.now() + 10000);
|
||||
setTyping(+new Date() + 10_000);
|
||||
}, [typing, setTyping]);
|
||||
|
||||
/**
|
||||
* Stops typing for client user
|
||||
*/
|
||||
const stopTyping = React.useCallback(() => {
|
||||
if (typing) {
|
||||
const stopTyping = React.useCallback(
|
||||
(force?: boolean) => {
|
||||
if (force || typing) {
|
||||
logger.debug("ShouldStopTyping");
|
||||
setTyping(null);
|
||||
setTyping(false);
|
||||
}
|
||||
}, [typing, setTyping]);
|
||||
},
|
||||
[typing, setTyping],
|
||||
);
|
||||
|
||||
/**
|
||||
* Debounced version of stopTyping
|
||||
*/
|
||||
const debouncedStopTyping = React.useCallback(debounce(stopTyping, 10000), [stopTyping]);
|
||||
const debouncedStopTyping = React.useCallback(debounce(stopTyping as (...args: unknown[]) => void, 10_000), [
|
||||
channel,
|
||||
stopTyping,
|
||||
]);
|
||||
|
||||
/**
|
||||
* @returns Whether or not a message can be sent given the current state
|
||||
@ -111,20 +118,15 @@ function MessageInput({ channel }: Props) {
|
||||
logger.debug("ShouldSendMessage");
|
||||
}, [content, uploadState, channel, canSendMessage]);
|
||||
|
||||
/**
|
||||
* Handles the change event of the textarea
|
||||
*/
|
||||
const onChange = React.useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setContent(e.target.value);
|
||||
}, []);
|
||||
|
||||
const onKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
const onKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
// TODO:
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
send();
|
||||
}
|
||||
}, []);
|
||||
|
||||
debouncedStopTyping(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
@ -177,8 +179,13 @@ function MessageInput({ channel }: Props) {
|
||||
uploadState.type === UploadStateType.UPLOADING ||
|
||||
uploadState.type === UploadStateType.SENDING
|
||||
}
|
||||
onChange={onChange}
|
||||
onKeyDown={onKeyDown}
|
||||
onChange={(e) => {
|
||||
setContent(e.target.value);
|
||||
startTyping();
|
||||
}}
|
||||
onKeyDown={() => {
|
||||
debouncedStopTyping();
|
||||
}}
|
||||
/>
|
||||
<ButtonWrapper>
|
||||
{/* <IconButton>
|
||||
|
17
src/utils/debounce.ts
Normal file
17
src/utils/debounce.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// https://github.com/revoltchat/revite/blob/master/src/lib/debounce.ts#L5
|
||||
|
||||
export function debounce(cb: (...args: unknown[]) => void, duration: number) {
|
||||
// Store the timer variable.
|
||||
let timer: NodeJS.Timeout;
|
||||
// This function is given to React.
|
||||
return (...args: unknown[]) => {
|
||||
// Get rid of the old timer.
|
||||
clearTimeout(timer);
|
||||
// Set a new timer.
|
||||
timer = setTimeout(() => {
|
||||
// Instead calling the new function.
|
||||
// (with the newer data)
|
||||
cb(...args);
|
||||
}, duration);
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user