fix: corrige sincronizacao de estado do chat entre abas
O BroadcastChannel nao estava funcionando corretamente porque cada aba restaurava do localStorage independentemente na montagem. Mudanca: - Substituido BroadcastChannel pelo evento 'storage' do localStorage - O evento storage dispara automaticamente em TODAS as outras abas quando o localStorage e alterado (mais confiavel) - Removido broadcastChannelRef e CHAT_WIDGET_CHANNEL nao mais usados Comportamento: - Abrir/fechar/minimizar chat em uma aba sincroniza com todas as outras - Estado persiste entre reloads via localStorage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
366bc4bf12
commit
082f2d67f1
1 changed files with 19 additions and 25 deletions
|
|
@ -38,7 +38,6 @@ import {
|
||||||
const MAX_MESSAGE_LENGTH = 4000
|
const MAX_MESSAGE_LENGTH = 4000
|
||||||
const MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024 // 5MB
|
const MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024 // 5MB
|
||||||
const MAX_ATTACHMENTS = 5
|
const MAX_ATTACHMENTS = 5
|
||||||
const CHAT_WIDGET_CHANNEL = "chat-widget-sync"
|
|
||||||
const STORAGE_KEY = "chat-widget-state"
|
const STORAGE_KEY = "chat-widget-state"
|
||||||
|
|
||||||
type ChatWidgetState = {
|
type ChatWidgetState = {
|
||||||
|
|
@ -281,7 +280,6 @@ export function ChatWidget() {
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
const [draft, setDraft] = useState("")
|
const [draft, setDraft] = useState("")
|
||||||
const broadcastChannelRef = useRef<BroadcastChannel | null>(null)
|
|
||||||
const [isSending, setIsSending] = useState(false)
|
const [isSending, setIsSending] = useState(false)
|
||||||
const [isEndingChat, setIsEndingChat] = useState(false)
|
const [isEndingChat, setIsEndingChat] = useState(false)
|
||||||
const [attachments, setAttachments] = useState<UploadedFile[]>([])
|
const [attachments, setAttachments] = useState<UploadedFile[]>([])
|
||||||
|
|
@ -320,31 +318,32 @@ export function ChatWidget() {
|
||||||
const machineOnline = liveChat?.machineOnline ?? false
|
const machineOnline = liveChat?.machineOnline ?? false
|
||||||
const machineHostname = liveChat?.machineHostname
|
const machineHostname = liveChat?.machineHostname
|
||||||
|
|
||||||
// Sincronizar estado entre abas usando BroadcastChannel
|
// Sincronizar estado entre abas usando evento storage do localStorage
|
||||||
|
// O evento storage dispara automaticamente em TODAS as outras abas quando localStorage muda
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window === "undefined") return
|
if (typeof window === "undefined") return
|
||||||
|
|
||||||
// Criar canal de broadcast
|
const handleStorageChange = (event: StorageEvent) => {
|
||||||
const channel = new BroadcastChannel(CHAT_WIDGET_CHANNEL)
|
// Ignorar mudancas em outras chaves
|
||||||
broadcastChannelRef.current = channel
|
if (event.key !== STORAGE_KEY) return
|
||||||
|
// Ignorar se nao tem valor novo
|
||||||
|
if (!event.newValue) return
|
||||||
|
|
||||||
// Ouvir mensagens de outras abas
|
try {
|
||||||
channel.onmessage = (event: MessageEvent<ChatWidgetState>) => {
|
const state = JSON.parse(event.newValue) as ChatWidgetState
|
||||||
const state = event.data
|
setIsOpen(state.isOpen)
|
||||||
setIsOpen(state.isOpen)
|
setIsMinimized(state.isMinimized)
|
||||||
setIsMinimized(state.isMinimized)
|
if (state.activeTicketId) {
|
||||||
if (state.activeTicketId) {
|
setActiveTicketId(state.activeTicketId)
|
||||||
setActiveTicketId(state.activeTicketId)
|
}
|
||||||
}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
window.addEventListener("storage", handleStorageChange)
|
||||||
channel.close()
|
return () => window.removeEventListener("storage", handleStorageChange)
|
||||||
broadcastChannelRef.current = null
|
|
||||||
}
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// Salvar estado no localStorage e broadcast para outras abas quando muda
|
// Salvar estado no localStorage quando muda (dispara evento storage em outras abas)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window === "undefined") return
|
if (typeof window === "undefined") return
|
||||||
|
|
||||||
|
|
@ -354,15 +353,10 @@ export function ChatWidget() {
|
||||||
activeTicketId,
|
activeTicketId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Salvar no localStorage para persistir entre reloads
|
// Salvar no localStorage (isso dispara evento storage em outras abas automaticamente)
|
||||||
try {
|
try {
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
// Broadcast para outras abas
|
|
||||||
if (broadcastChannelRef.current) {
|
|
||||||
broadcastChannelRef.current.postMessage(state)
|
|
||||||
}
|
|
||||||
}, [isOpen, isMinimized, activeTicketId])
|
}, [isOpen, isMinimized, activeTicketId])
|
||||||
|
|
||||||
// Auto-selecionar primeira sessão se nenhuma selecionada
|
// Auto-selecionar primeira sessão se nenhuma selecionada
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue