perf(realtime): debounce typing start/stop events
Some checks failed
CI / test (push) Failing after 55s
Some checks failed
CI / test (push) Failing after 55s
This commit is contained in:
@@ -109,6 +109,8 @@ export function MessageComposer() {
|
||||
const recordingStateRef = useRef<RecordingState>("idle");
|
||||
const lastEditingMessageIdRef = useRef<number | null>(null);
|
||||
const prevActiveChatIdRef = useRef<number | null>(null);
|
||||
const typingActiveRef = useRef(false);
|
||||
const typingStopTimerRef = useRef<number | null>(null);
|
||||
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
@@ -247,6 +249,9 @@ export function MessageComposer() {
|
||||
if (pointerUpHandlerRef.current) {
|
||||
window.removeEventListener("pointerup", pointerUpHandlerRef.current);
|
||||
}
|
||||
if (typingStopTimerRef.current !== null) {
|
||||
window.clearTimeout(typingStopTimerRef.current);
|
||||
}
|
||||
};
|
||||
}, [previewUrl]);
|
||||
|
||||
@@ -261,6 +266,11 @@ export function MessageComposer() {
|
||||
if (prev && prev !== activeChatId) {
|
||||
const ws = getWs();
|
||||
ws?.send(JSON.stringify({ event: "typing_stop", payload: { chat_id: prev } }));
|
||||
typingActiveRef.current = false;
|
||||
if (typingStopTimerRef.current !== null) {
|
||||
window.clearTimeout(typingStopTimerRef.current);
|
||||
typingStopTimerRef.current = null;
|
||||
}
|
||||
}
|
||||
prevActiveChatIdRef.current = activeChatId;
|
||||
}, [activeChatId]);
|
||||
@@ -333,6 +343,46 @@ export function MessageComposer() {
|
||||
ws?.send(JSON.stringify({ event: eventName, payload: { chat_id: activeChatId } }));
|
||||
}
|
||||
|
||||
function emitTypingStopIfActive() {
|
||||
if (!activeChatId) {
|
||||
return;
|
||||
}
|
||||
if (typingStopTimerRef.current !== null) {
|
||||
window.clearTimeout(typingStopTimerRef.current);
|
||||
typingStopTimerRef.current = null;
|
||||
}
|
||||
if (typingActiveRef.current) {
|
||||
sendRealtimeChatEvent("typing_stop");
|
||||
typingActiveRef.current = false;
|
||||
}
|
||||
}
|
||||
|
||||
function syncTypingForText(nextText: string) {
|
||||
if (!activeChatId) {
|
||||
return;
|
||||
}
|
||||
const hasText = nextText.trim().length > 0;
|
||||
if (!hasText) {
|
||||
emitTypingStopIfActive();
|
||||
return;
|
||||
}
|
||||
if (!typingActiveRef.current) {
|
||||
sendRealtimeChatEvent("typing_start");
|
||||
typingActiveRef.current = true;
|
||||
}
|
||||
if (typingStopTimerRef.current !== null) {
|
||||
window.clearTimeout(typingStopTimerRef.current);
|
||||
}
|
||||
typingStopTimerRef.current = window.setTimeout(() => {
|
||||
if (!typingActiveRef.current) {
|
||||
return;
|
||||
}
|
||||
sendRealtimeChatEvent("typing_stop");
|
||||
typingActiveRef.current = false;
|
||||
typingStopTimerRef.current = null;
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
async function handleSend() {
|
||||
if (!activeChatId || !text.trim() || !me || !canSendInActiveChat) {
|
||||
return;
|
||||
@@ -373,7 +423,7 @@ export function MessageComposer() {
|
||||
setText("");
|
||||
clearDraft(activeChatId);
|
||||
setReplyToMessage(activeChatId, null);
|
||||
sendRealtimeChatEvent("typing_stop");
|
||||
emitTypingStopIfActive();
|
||||
} catch {
|
||||
removeOptimisticMessage(activeChatId, clientMessageId);
|
||||
setUploadError("Message send failed. Please try again.");
|
||||
@@ -644,7 +694,7 @@ export function MessageComposer() {
|
||||
recordingStartedAtRef.current = Date.now();
|
||||
setRecordSeconds(0);
|
||||
setRecordingState("recording");
|
||||
sendRealtimeChatEvent("typing_stop");
|
||||
emitTypingStopIfActive();
|
||||
sendRealtimeChatEvent("recording_voice_start");
|
||||
return true;
|
||||
} catch {
|
||||
@@ -1304,13 +1354,11 @@ export function MessageComposer() {
|
||||
setText(next);
|
||||
if (activeChatId) {
|
||||
setDraft(activeChatId, next);
|
||||
sendRealtimeChatEvent(next.trim().length > 0 ? "typing_start" : "typing_stop");
|
||||
syncTypingForText(next);
|
||||
}
|
||||
}}
|
||||
onBlur={() => {
|
||||
if (activeChatId) {
|
||||
sendRealtimeChatEvent("typing_stop");
|
||||
}
|
||||
emitTypingStopIfActive();
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user