diff --git a/apps/web/app/components/chat.tsx b/apps/web/app/components/chat.tsx index 6c3ae5a3..6827cd23 100644 --- a/apps/web/app/components/chat.tsx +++ b/apps/web/app/components/chat.tsx @@ -37,11 +37,11 @@ export function Chat() { }, }) - const handleSend = useCallback((text: string) => { + const handleSend = (text: string) => { if (!hub?.hubId || !activeAgentId) return addUserMessage(text, activeAgentId) send(hub.hubId, "message", { agentId: activeAgentId, content: text }) - }, [hub?.hubId, activeAgentId, addUserMessage, send]) + } const filtered = activeAgentId ? messages.filter(m => m.agentId === activeAgentId) diff --git a/apps/web/app/hooks/use-device-id.ts b/apps/web/app/hooks/use-device-id.ts index 5b76578f..842d4551 100644 --- a/apps/web/app/hooks/use-device-id.ts +++ b/apps/web/app/hooks/use-device-id.ts @@ -1,19 +1,26 @@ -import { useState, useEffect } from "react" +import { useSyncExternalStore } from "react" import { v7 as uuidv7 } from "uuid" const STORAGE_KEY = "multica-device-id" -export function useDeviceId(): string { - const [deviceId, setDeviceId] = useState("") - - useEffect(() => { - let id = localStorage.getItem(STORAGE_KEY) - if (!id) { - id = uuidv7() - localStorage.setItem(STORAGE_KEY, id) - } - setDeviceId(id) - }, []) - - return deviceId +function getSnapshot(): string { + let id = localStorage.getItem(STORAGE_KEY) + if (!id) { + id = uuidv7() + localStorage.setItem(STORAGE_KEY, id) + } + return id +} + +function subscribe(cb: () => void) { + window.addEventListener("storage", cb) + return () => window.removeEventListener("storage", cb) +} + +function getServerSnapshot(): string { + return "" +} + +export function useDeviceId(): string { + return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) } diff --git a/apps/web/app/hooks/use-gateway.ts b/apps/web/app/hooks/use-gateway.ts index f10e0f99..bda4fa0f 100644 --- a/apps/web/app/hooks/use-gateway.ts +++ b/apps/web/app/hooks/use-gateway.ts @@ -12,7 +12,10 @@ export function useGateway(options?: UseGatewayOptions) { const [state, setState] = useState("disconnected") const clientRef = useRef(null) const onMessageRef = useRef(options?.onMessage) - onMessageRef.current = options?.onMessage + + useEffect(() => { + onMessageRef.current = options?.onMessage + }) useEffect(() => { if (!deviceId) return diff --git a/apps/web/app/hooks/use-scroll-fade.ts b/apps/web/app/hooks/use-scroll-fade.ts index 6dc5b929..82709871 100644 --- a/apps/web/app/hooks/use-scroll-fade.ts +++ b/apps/web/app/hooks/use-scroll-fade.ts @@ -38,13 +38,14 @@ export function useScrollFade( const el = ref.current; if (!el) return; - update(); + const frame = requestAnimationFrame(update); el.addEventListener("scroll", update, { passive: true }); const ro = new ResizeObserver(update); ro.observe(el); return () => { + cancelAnimationFrame(frame); el.removeEventListener("scroll", update); ro.disconnect(); };