fix: update dependencies and improve chat component structure
- Updated `lucide-svelte` dependency to version 0.552.0 across multiple files for consistency. - Refactored chat components to enhance structure and readability, including adjustments to the Sidebar, ChatList, and MessageInput components. - Improved notification handling in chat components to ensure better user experience and responsiveness. - Added type safety enhancements in various components to ensure better integration with backend data models.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
} from "$lib/stores/chatStore";
|
||||
import { useQuery } from "convex-svelte";
|
||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||
import type { Id } from "@sgse-app/backend/convex/_generated/dataModel";
|
||||
import ChatList from "./ChatList.svelte";
|
||||
import ChatWindow from "./ChatWindow.svelte";
|
||||
import { authStore } from "$lib/stores/auth.svelte";
|
||||
@@ -156,18 +157,70 @@
|
||||
activeConversation = $conversaAtiva;
|
||||
});
|
||||
|
||||
// Tipos para conversas
|
||||
type ConversaComTimestamp = {
|
||||
_id: string;
|
||||
ultimaMensagemTimestamp?: number;
|
||||
ultimaMensagemRemetenteId?: string; // ID do remetente da última mensagem
|
||||
ultimaMensagem?: string;
|
||||
nome?: string;
|
||||
outroUsuario?: { nome: string };
|
||||
};
|
||||
|
||||
// Detectar novas mensagens globalmente (mesmo quando chat está fechado/minimizado)
|
||||
const todasConversas = useQuery(api.chat.listarConversas, {});
|
||||
let ultimoTimestampGlobal = $state<number>(0);
|
||||
let mensagensNotificadasGlobal = $state<Set<string>>(new Set());
|
||||
let showGlobalNotificationPopup = $state(false);
|
||||
let globalNotificationMessage = $state<{ remetente: string; conteudo: string; conversaId: string } | null>(null);
|
||||
let globalNotificationTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
// Carregar mensagens já notificadas do localStorage ao montar
|
||||
let mensagensCarregadasGlobal = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
if (typeof window !== 'undefined' && !mensagensCarregadasGlobal) {
|
||||
const saved = localStorage.getItem('chat-mensagens-notificadas-global');
|
||||
if (saved) {
|
||||
try {
|
||||
const ids = JSON.parse(saved) as string[];
|
||||
mensagensNotificadasGlobal = new Set(ids);
|
||||
} catch {
|
||||
mensagensNotificadasGlobal = new Set();
|
||||
}
|
||||
}
|
||||
mensagensCarregadasGlobal = true;
|
||||
|
||||
// Marcar todas as mensagens atuais como já visualizadas (não tocar beep ao abrir)
|
||||
if (todasConversas?.data) {
|
||||
const conversas = todasConversas.data as ConversaComTimestamp[];
|
||||
conversas.forEach((conv) => {
|
||||
if (conv.ultimaMensagemTimestamp) {
|
||||
const mensagemId = `${conv._id}-${conv.ultimaMensagemTimestamp}`;
|
||||
mensagensNotificadasGlobal.add(mensagemId);
|
||||
}
|
||||
});
|
||||
salvarMensagensNotificadasGlobal();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Salvar mensagens notificadas no localStorage
|
||||
function salvarMensagensNotificadasGlobal() {
|
||||
if (typeof window !== 'undefined') {
|
||||
const ids = Array.from(mensagensNotificadasGlobal);
|
||||
// Limitar a 1000 IDs para não encher o localStorage
|
||||
const idsLimitados = ids.slice(-1000);
|
||||
localStorage.setItem('chat-mensagens-notificadas-global', JSON.stringify(idsLimitados));
|
||||
}
|
||||
}
|
||||
|
||||
// Função para tocar som de notificação
|
||||
function tocarSomNotificacaoGlobal() {
|
||||
try {
|
||||
const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
|
||||
const audioContext = new AudioContext();
|
||||
const AudioContextClass = window.AudioContext || (window as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;
|
||||
if (!AudioContextClass) return;
|
||||
|
||||
const audioContext = new AudioContextClass();
|
||||
if (audioContext.state === 'suspended') {
|
||||
audioContext.resume().then(() => {
|
||||
const oscillator = audioContext.createOscillator();
|
||||
@@ -200,32 +253,44 @@
|
||||
|
||||
$effect(() => {
|
||||
if (todasConversas?.data && authStore.usuario?._id) {
|
||||
// Encontrar o maior timestamp de todas as conversas
|
||||
let maiorTimestamp = 0;
|
||||
let conversaComNovaMensagem: any = null;
|
||||
const conversas = todasConversas.data as ConversaComTimestamp[];
|
||||
|
||||
todasConversas.data.forEach((conv: any) => {
|
||||
if (conv.ultimaMensagemTimestamp && conv.ultimaMensagemTimestamp > maiorTimestamp) {
|
||||
maiorTimestamp = conv.ultimaMensagemTimestamp;
|
||||
conversaComNovaMensagem = conv;
|
||||
// Encontrar conversas com novas mensagens
|
||||
const meuId = String(authStore.usuario._id);
|
||||
|
||||
conversas.forEach((conv) => {
|
||||
if (!conv.ultimaMensagemTimestamp) return;
|
||||
|
||||
// Verificar se a última mensagem foi enviada pelo usuário atual
|
||||
const remetenteIdStr = conv.ultimaMensagemRemetenteId ? String(conv.ultimaMensagemRemetenteId) : null;
|
||||
if (remetenteIdStr && remetenteIdStr === meuId) {
|
||||
// Mensagem enviada pelo próprio usuário - não tocar beep nem mostrar notificação
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Se há nova mensagem (timestamp maior) e não estamos vendo essa conversa, tocar som e mostrar popup
|
||||
if (maiorTimestamp > ultimoTimestampGlobal && conversaComNovaMensagem) {
|
||||
|
||||
// Criar ID único para esta mensagem: conversaId-timestamp
|
||||
const mensagemId = `${conv._id}-${conv.ultimaMensagemTimestamp}`;
|
||||
|
||||
// Verificar se já foi notificada
|
||||
if (mensagensNotificadasGlobal.has(mensagemId)) return;
|
||||
|
||||
const conversaAtivaId = activeConversation ? String(activeConversation) : null;
|
||||
const conversaIdStr = String(conversaComNovaMensagem._id);
|
||||
const conversaIdStr = String(conv._id);
|
||||
|
||||
// Só mostrar notificação se não estamos vendo essa conversa
|
||||
if (!isOpen || conversaAtivaId !== conversaIdStr) {
|
||||
// Tocar som de notificação
|
||||
// Marcar como notificada antes de tocar som (evita duplicação)
|
||||
mensagensNotificadasGlobal.add(mensagemId);
|
||||
salvarMensagensNotificadasGlobal();
|
||||
|
||||
// Tocar som de notificação (apenas uma vez)
|
||||
tocarSomNotificacaoGlobal();
|
||||
|
||||
// Mostrar popup de notificação
|
||||
globalNotificationMessage = {
|
||||
remetente: conversaComNovaMensagem.outroUsuario?.nome || conversaComNovaMensagem.nome || "Usuário",
|
||||
conteudo: conversaComNovaMensagem.ultimaMensagem || "",
|
||||
conversaId: conversaComNovaMensagem._id
|
||||
remetente: conv.outroUsuario?.nome || conv.nome || "Usuário",
|
||||
conteudo: conv.ultimaMensagem || "",
|
||||
conversaId: conv._id
|
||||
};
|
||||
showGlobalNotificationPopup = true;
|
||||
|
||||
@@ -238,9 +303,7 @@
|
||||
globalNotificationMessage = null;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
ultimoTimestampGlobal = maiorTimestamp;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -676,7 +739,7 @@
|
||||
}
|
||||
// Abrir chat e conversa ao clicar
|
||||
abrirChat();
|
||||
abrirConversa(globalNotificationMessage.conversaId as any);
|
||||
abrirConversa(globalNotificationMessage.conversaId as Id<"conversas">);
|
||||
}}
|
||||
>
|
||||
<div class="flex items-start gap-3">
|
||||
|
||||
Reference in New Issue
Block a user