From 4899943cfc628c21db04fbe0fb4f84f8ad5c64d7 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Tue, 23 Dec 2025 14:06:39 +0100 Subject: [PATCH] DM typing indicator, and bug fix sending messages on connect --- src/app/chat/[id]/page.tsx | 10 +++++- src/app/server/[ip]/page.tsx | 36 ++------------------- src/components/channel/ChannelView.tsx | 5 ++- src/hooks/use-indicators.ts | 43 ++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 35 deletions(-) create mode 100644 src/hooks/use-indicators.ts diff --git a/src/app/chat/[id]/page.tsx b/src/app/chat/[id]/page.tsx index e42dafe..58a8bc3 100644 --- a/src/app/chat/[id]/page.tsx +++ b/src/app/chat/[id]/page.tsx @@ -4,10 +4,11 @@ import MessageBox from "@/components/channel/MessageBox"; import AppLayout from "@/components/app/AppLayout"; import { useParams, useRouter } from "next/navigation"; import useApp from "@/hooks/use-app"; -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import auth from "@/lib/auth"; import useAsync from "@/hooks/use-async"; import { Button } from "@/components/ui/button"; +import useIndicators from "@/hooks/use-indicators"; export default function DMs() { const { id } = useParams<{ id: string }>(); @@ -15,6 +16,7 @@ export default function DMs() { const targetNode = useRef(null); const { value: target, loading } = useAsync(() => app.getUserById(id)); const router = useRouter(); + const { indicators, addIndicator } = useIndicators(); useEffect(() => { async function connectTargetNode() { @@ -23,6 +25,7 @@ export default function DMs() { id: target.node_address, wsRef: targetNode, messageStore: app.privateMessages, + onIndicator: addIndicator, }); } @@ -48,6 +51,10 @@ export default function DMs() { )} sendRequest={(req) => { console.log("Sending request: ", req); + while ( + targetNode.current?.CONNECTING || + app.node.current?.CONNECTING + ) {} switch (req.type) { case "send_message": targetNode.current?.send(JSON.stringify(req)); @@ -61,6 +68,7 @@ export default function DMs() { break; } }} + indicators={indicators} /> ) : ( diff --git a/src/app/server/[ip]/page.tsx b/src/app/server/[ip]/page.tsx index a9133cd..562eea7 100644 --- a/src/app/server/[ip]/page.tsx +++ b/src/app/server/[ip]/page.tsx @@ -9,6 +9,7 @@ import useApp from "@/hooks/use-app"; import { useEffectOnceWhenReady } from "@/hooks/use-once"; import ChannelView from "@/components/channel/ChannelView"; import { IndicatorContext } from "@/types/protocol"; +import useIndicators from "@/hooks/use-indicators"; export default function Server() { const { ip } = useParams<{ ip: string }>(); @@ -16,7 +17,7 @@ export default function Server() { const serverRef = useRef(null); const app = useApp(); const messageStore = useMessages(); - const [indicators, setIndicators] = useState([]); + const { indicators, addIndicator } = useIndicators(); useEffectOnceWhenReady( () => { @@ -26,44 +27,13 @@ export default function Server() { wsRef: serverRef, setServer: app.setServer, messageStore: messageStore, - onIndicator: (i) => { - setIndicators((prev) => { - const combined = [...prev, { ...i }]; - const uniqueByUser = combined.reduce>( - (acc, curr) => { - const userId = curr.indicator.params.user_id; - if (!acc[userId] || curr.expires > acc[userId].expires) { - acc[userId] = curr; - } - return acc; - }, - {} - ); - - return Object.values(uniqueByUser); - }); - }, + onIndicator: addIndicator, }); }, [ip, messageStore.messages], [undefined, (v) => v] ); - useEffect(() => { - const interval = setInterval(() => { - setIndicators((prev) => - prev - .map((item) => ({ - ...item, - expires: item.expires - 1, - })) - .filter((item) => item.expires > 0) - ); - }, 1000); - - return () => clearInterval(interval); - }, []); - useEffect(() => { const channelId = searchParams.get("ch"); if (channelId) { diff --git a/src/components/channel/ChannelView.tsx b/src/components/channel/ChannelView.tsx index 8f39c46..bd78cfa 100644 --- a/src/components/channel/ChannelView.tsx +++ b/src/components/channel/ChannelView.tsx @@ -29,7 +29,10 @@ export default function ChannelView({ app={app} channelName={app.currentChannel.name} messages={messages} - sendRequest={(req) => serverRef.current?.send(JSON.stringify(req))} + sendRequest={(req) => { + while (serverRef.current?.CONNECTING) {} + serverRef.current?.send(JSON.stringify(req)); + }} indicators={indicators} /> ); diff --git a/src/hooks/use-indicators.ts b/src/hooks/use-indicators.ts new file mode 100644 index 0000000..9e033f7 --- /dev/null +++ b/src/hooks/use-indicators.ts @@ -0,0 +1,43 @@ +import { IndicatorContext } from "@/types/protocol"; +import { useEffect, useState } from "react"; + +export default function useIndicators() { + const [indicators, setIndicators] = useState([]); + + useEffect(() => { + const interval = setInterval(() => { + setIndicators((prev) => + prev + .map((item) => ({ + ...item, + expires: item.expires - 1, + })) + .filter((item) => item.expires > 0) + ); + }, 1000); + + return () => clearInterval(interval); + }, []); + + return { + indicators, + setIndicators, + addIndicator: (i: IndicatorContext) => { + setIndicators((prev) => { + const combined = [...prev, { ...i }]; + const uniqueByUser = combined.reduce>( + (acc, curr) => { + const userId = curr.indicator.params.user_id; + if (!acc[userId] || curr.expires > acc[userId].expires) { + acc[userId] = curr; + } + return acc; + }, + {} + ); + + return Object.values(uniqueByUser); + }); + }, + }; +}