fix(chat): melhora realtime e anexos no desktop
This commit is contained in:
parent
3d45fe3b04
commit
8cf13c43de
5 changed files with 603 additions and 141 deletions
|
|
@ -58,7 +58,9 @@ type ChatSession = {
|
|||
ticketRef: number
|
||||
ticketSubject: string
|
||||
sessionId: string
|
||||
agentId: string
|
||||
unreadCount: number
|
||||
lastActivityAt: number
|
||||
}
|
||||
|
||||
type UploadedFile = {
|
||||
|
|
@ -242,8 +244,8 @@ export function ChatWidget() {
|
|||
// pois o chat nativo do Tauri ja esta disponivel
|
||||
const isTauriContext = typeof window !== "undefined" && "__TAURI__" in window
|
||||
|
||||
const { convexUserId } = useAuth()
|
||||
const viewerId = convexUserId ?? null
|
||||
const { convexUserId, isStaff } = useAuth()
|
||||
const viewerId = isStaff ? (convexUserId ?? null) : null
|
||||
|
||||
// Inicializar estado a partir do localStorage (para persistir entre reloads)
|
||||
const [isOpen, setIsOpen] = useState(() => {
|
||||
|
|
@ -290,8 +292,8 @@ export function ChatWidget() {
|
|||
const inputRef = useRef<HTMLTextAreaElement | null>(null)
|
||||
const fileInputRef = useRef<HTMLInputElement | null>(null)
|
||||
const dropAreaRef = useRef<HTMLDivElement | null>(null)
|
||||
const prevSessionCountRef = useRef<number>(-1) // -1 indica "ainda nao inicializado"
|
||||
const hasRestoredStateRef = useRef<boolean>(false) // Flag para evitar sobrescrever estado do localStorage
|
||||
const hasInitializedSessionsRef = useRef(false)
|
||||
const prevSessionIdsRef = useRef<Set<string>>(new Set())
|
||||
|
||||
// Buscar sessões de chat ativas do agente
|
||||
const activeSessions = useQuery(
|
||||
|
|
@ -366,40 +368,32 @@ export function ChatWidget() {
|
|||
}
|
||||
}, [activeTicketId, activeSessions])
|
||||
|
||||
// Auto-abrir widget quando uma nova sessão é iniciada (apenas para sessoes NOVAS, nao na montagem inicial)
|
||||
// Auto-abrir o widget quando ESTE agente iniciar uma nova sessão de chat.
|
||||
// Nao roda na montagem inicial para nao sobrescrever o estado do localStorage.
|
||||
useEffect(() => {
|
||||
if (!activeSessions) return
|
||||
const currentCount = activeSessions.length
|
||||
const prevCount = prevSessionCountRef.current
|
||||
|
||||
// Primeira execucao: apenas inicializar o ref, nao abrir automaticamente
|
||||
// Isso preserva o estado do localStorage (se usuario tinha minimizado, mantem minimizado)
|
||||
if (prevCount === -1) {
|
||||
prevSessionCountRef.current = currentCount
|
||||
hasRestoredStateRef.current = true
|
||||
const currentIds = new Set(activeSessions.map((s) => s.sessionId))
|
||||
|
||||
if (!hasInitializedSessionsRef.current) {
|
||||
prevSessionIdsRef.current = currentIds
|
||||
hasInitializedSessionsRef.current = true
|
||||
return
|
||||
}
|
||||
|
||||
// Se aumentou o número de sessões APOS a montagem inicial, é uma nova sessão - abrir o widget expandido
|
||||
if (currentCount > prevCount && hasRestoredStateRef.current) {
|
||||
// O estado do widget e definido com base nas nao lidas.
|
||||
// Selecionar a sessão mais recente (última da lista ou primeira se única)
|
||||
const newestSession = activeSessions[activeSessions.length - 1] ?? activeSessions[0]
|
||||
const hasUnreadForAgent = (newestSession?.unreadCount ?? 0) > 0
|
||||
const newSessions = activeSessions.filter((s) => !prevSessionIdsRef.current.has(s.sessionId))
|
||||
prevSessionIdsRef.current = currentIds
|
||||
|
||||
if (!isOpen) {
|
||||
setIsOpen(true)
|
||||
setIsMinimized(!hasUnreadForAgent)
|
||||
} else if (isMinimized && hasUnreadForAgent) {
|
||||
setIsMinimized(false)
|
||||
}
|
||||
if (newestSession) {
|
||||
setActiveTicketId(newestSession.ticketId)
|
||||
}
|
||||
}
|
||||
if (newSessions.length === 0) return
|
||||
if (!viewerId) return
|
||||
|
||||
prevSessionCountRef.current = currentCount
|
||||
}, [activeSessions, isOpen, isMinimized])
|
||||
const mine = newSessions.find((s) => s.agentId === viewerId) ?? null
|
||||
if (!mine) return
|
||||
|
||||
setIsOpen(true)
|
||||
setIsMinimized(false)
|
||||
setActiveTicketId(mine.ticketId)
|
||||
}, [activeSessions, viewerId])
|
||||
|
||||
// Scroll para última mensagem
|
||||
useEffect(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue