Ajusta auto-minimização do chat web e unifica realtime no desktop
This commit is contained in:
parent
c65e37e232
commit
3d45fe3b04
10 changed files with 279 additions and 635 deletions
|
|
@ -1,14 +1,10 @@
|
|||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
import { open } from "@tauri-apps/plugin-dialog"
|
||||
import { invoke } from "@tauri-apps/api/core"
|
||||
import { listen } from "@tauri-apps/api/event"
|
||||
import { Send, X, Loader2, MessageCircle, Paperclip, FileText, Image as ImageIcon, File, User, ChevronUp, Minimize2 } from "lucide-react"
|
||||
import type { ChatMessage } from "./types"
|
||||
import {
|
||||
subscribeMachineMessages,
|
||||
sendMachineMessage,
|
||||
markMachineMessagesRead,
|
||||
getMachineStoreConfig,
|
||||
} from "./convexMachineClient"
|
||||
import type { ChatMessage, ChatMessagesResponse, NewMessageEvent } from "./types"
|
||||
import { getMachineStoreConfig } from "./machineStore"
|
||||
|
||||
const MAX_MESSAGES_IN_MEMORY = 200 // Limite de mensagens para evitar memory leak
|
||||
|
||||
|
|
@ -56,7 +52,6 @@ export function ChatWidget({ ticketId, ticketRef }: ChatWidgetProps) {
|
|||
const [unreadCount, setUnreadCount] = useState(0)
|
||||
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null)
|
||||
const messagesSubRef = useRef<(() => void) | null>(null)
|
||||
const hadSessionRef = useRef<boolean>(false)
|
||||
|
||||
// Scroll para o final quando novas mensagens chegam
|
||||
|
|
@ -86,8 +81,78 @@ export function ChatWidget({ ticketId, ticketRef }: ChatWidgetProps) {
|
|||
isMinimizedRef.current = isMinimized
|
||||
}, [isMinimized])
|
||||
|
||||
// Inicializacao via Convex (WS) - NAO depende de isMinimized para evitar resubscriptions
|
||||
const configRef = useRef<{ apiBaseUrl: string; token: string } | null>(null)
|
||||
|
||||
const ensureConfig = useCallback(async () => {
|
||||
const cfg = configRef.current ?? (await getMachineStoreConfig())
|
||||
configRef.current = cfg
|
||||
return cfg
|
||||
}, [])
|
||||
|
||||
const loadMessages = useCallback(async () => {
|
||||
try {
|
||||
const cfg = await ensureConfig()
|
||||
const result = await invoke<ChatMessagesResponse>("fetch_chat_messages", {
|
||||
baseUrl: cfg.apiBaseUrl,
|
||||
token: cfg.token,
|
||||
ticketId,
|
||||
since: null,
|
||||
})
|
||||
|
||||
setHasSession(result.hasSession)
|
||||
hadSessionRef.current = hadSessionRef.current || result.hasSession
|
||||
setUnreadCount(result.unreadCount ?? 0)
|
||||
setMessages(result.messages.slice(-MAX_MESSAGES_IN_MEMORY))
|
||||
|
||||
if (result.messages.length > 0) {
|
||||
const first = result.messages[0]
|
||||
setTicketInfo((prevInfo) =>
|
||||
prevInfo ?? {
|
||||
ref: ticketRef ?? 0,
|
||||
subject: "",
|
||||
agentName: first.authorName ?? "Suporte",
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
setError(message || "Erro ao carregar mensagens.")
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}, [ensureConfig, ticketId, ticketRef])
|
||||
|
||||
// Carregar mensagens na montagem / troca de ticket
|
||||
useEffect(() => {
|
||||
setIsLoading(true)
|
||||
setMessages([])
|
||||
setUnreadCount(0)
|
||||
loadMessages()
|
||||
}, [loadMessages])
|
||||
|
||||
// Recarregar quando o Rust sinalizar novas mensagens para este ticket
|
||||
useEffect(() => {
|
||||
let unlisten: (() => void) | null = null
|
||||
listen<NewMessageEvent>("raven://chat/new-message", (event) => {
|
||||
const sessions = event.payload?.sessions ?? []
|
||||
if (sessions.some((s) => s.ticketId === ticketId)) {
|
||||
loadMessages()
|
||||
}
|
||||
})
|
||||
.then((u) => {
|
||||
unlisten = u
|
||||
})
|
||||
.catch((err) => console.error("Falha ao registrar listener new-message:", err))
|
||||
|
||||
return () => {
|
||||
unlisten?.()
|
||||
}
|
||||
}, [ticketId, loadMessages])
|
||||
|
||||
// Inicializacao via Convex (WS) - NAO depende de isMinimized para evitar resubscriptions
|
||||
/* useEffect(() => {
|
||||
setIsLoading(true)
|
||||
setMessages([])
|
||||
messagesSubRef.current?.()
|
||||
|
|
@ -128,7 +193,7 @@ export function ChatWidget({ ticketId, ticketRef }: ChatWidgetProps) {
|
|||
messagesSubRef.current?.()
|
||||
messagesSubRef.current = null
|
||||
}
|
||||
}, [ticketId]) // Removido isMinimized - evita memory leak de resubscriptions
|
||||
}, [ticketId]) */ // Removido isMinimized - evita memory leak de resubscriptions
|
||||
|
||||
// Sincroniza estado de minimizado com o tamanho da janela (apenas em resizes reais, nao na montagem)
|
||||
// O estado inicial isMinimized=true e definido no useState e nao deve ser sobrescrito na montagem
|
||||
|
|
@ -158,10 +223,19 @@ export function ChatWidget({ ticketId, ticketRef }: ChatWidgetProps) {
|
|||
if (unreadCount === 0) return
|
||||
const unreadIds = messages.filter(m => !m.isFromMachine).map(m => m.id as string)
|
||||
if (unreadIds.length > 0) {
|
||||
markMachineMessagesRead(ticketId, unreadIds).catch(err => console.error("mark read falhou", err))
|
||||
ensureConfig()
|
||||
.then((cfg) =>
|
||||
invoke("mark_chat_messages_read", {
|
||||
baseUrl: cfg.apiBaseUrl,
|
||||
token: cfg.token,
|
||||
ticketId,
|
||||
messageIds: unreadIds,
|
||||
})
|
||||
)
|
||||
.catch((err) => console.error("mark read falhou", err))
|
||||
}
|
||||
// Nao setamos unreadCount aqui - o backend vai zerar unreadByMachine e a subscription vai atualizar
|
||||
}, [isMinimized, messages, ticketId, unreadCount])
|
||||
}, [isMinimized, messages, ticketId, unreadCount, ensureConfig])
|
||||
|
||||
// Selecionar arquivo para anexar
|
||||
const handleAttach = async () => {
|
||||
|
|
@ -217,7 +291,10 @@ export function ChatWidget({ ticketId, ticketRef }: ChatWidgetProps) {
|
|||
|
||||
try {
|
||||
const bodyToSend = messageText || (attachmentsToSend.length > 0 ? "[Anexo]" : "")
|
||||
await sendMachineMessage({
|
||||
const cfg = await ensureConfig()
|
||||
await invoke("send_chat_message", {
|
||||
baseUrl: cfg.apiBaseUrl,
|
||||
token: cfg.token,
|
||||
ticketId,
|
||||
body: bodyToSend,
|
||||
attachments: attachmentsToSend.length > 0 ? attachmentsToSend : undefined,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue