feat: enhance push notification management and error handling

- Implemented error handling for unhandled promise rejections related to message channels, improving stability during push notification operations.
- Updated the PushNotificationManager component to manage push subscription registration with timeouts, preventing application hangs.
- Enhanced the sidebar and chat components to display user avatars, improving user experience and visual consistency.
- Refactored email processing logic to support scheduled email sending, integrating new backend functionalities for better email management.
- Improved overall error handling and logging across components to reduce console spam and enhance debugging capabilities.
This commit is contained in:
2025-11-05 06:14:52 -03:00
parent f6671e0f16
commit aa3e3470cd
20 changed files with 2515 additions and 1665 deletions

View File

@@ -12,51 +12,116 @@
const client = useConvexClient();
// Capturar erros de Promise não tratados relacionados a message channel
// Este erro geralmente vem de extensões do Chrome ou comunicação com Service Worker
if (typeof window !== "undefined") {
window.addEventListener(
"unhandledrejection",
(event: PromiseRejectionEvent) => {
const reason = event.reason;
const errorMessage =
reason?.message || reason?.toString() || "";
// Filtrar apenas erros relacionados a message channel fechado
if (
errorMessage.includes("message channel closed") ||
errorMessage.includes("asynchronous response") ||
(errorMessage.includes("message channel") &&
errorMessage.includes("closed"))
) {
// Prevenir que o erro apareça no console
event.preventDefault();
// Silenciar o erro - é geralmente causado por extensões do Chrome
return false;
}
},
{ capture: true }
);
}
onMount(async () => {
let checkAuth: ReturnType<typeof setInterval> | null = null;
let mounted = true;
// Aguardar usuário estar autenticado
const checkAuth = setInterval(async () => {
if (authStore.usuario) {
clearInterval(checkAuth);
await registrarPushSubscription();
checkAuth = setInterval(async () => {
if (authStore.usuario && mounted) {
clearInterval(checkAuth!);
checkAuth = null;
try {
await registrarPushSubscription();
} catch (error) {
// Silenciar erros de push subscription para evitar spam no console
if (error instanceof Error && !error.message.includes("message channel")) {
console.error("Erro ao configurar push notifications:", error);
}
}
}
}, 500);
// Limpar intervalo após 30 segundos (timeout)
setTimeout(() => {
clearInterval(checkAuth);
const timeout = setTimeout(() => {
if (checkAuth) {
clearInterval(checkAuth);
checkAuth = null;
}
}, 30000);
return () => {
clearInterval(checkAuth);
mounted = false;
if (checkAuth) {
clearInterval(checkAuth);
}
clearTimeout(timeout);
};
});
async function registrarPushSubscription() {
try {
// Solicitar subscription
const subscription = await solicitarPushSubscription();
// Verificar se Service Worker está disponível antes de tentar
if (!("serviceWorker" in navigator) || !("PushManager" in window)) {
return;
}
// Solicitar subscription com timeout para evitar travamentos
const subscriptionPromise = solicitarPushSubscription();
const timeoutPromise = new Promise<null>((resolve) =>
setTimeout(() => resolve(null), 5000)
);
const subscription = await Promise.race([subscriptionPromise, timeoutPromise]);
if (!subscription) {
console.log(" Push subscription não disponível ou permissão negada");
// Não logar para evitar spam no console quando VAPID key não está configurada
return;
}
// Converter para formato serializável
const subscriptionData = subscriptionToJSON(subscription);
// Registrar no backend
const resultado = await client.mutation(api.pushNotifications.registrarPushSubscription, {
// Registrar no backend com timeout
const mutationPromise = client.mutation(api.pushNotifications.registrarPushSubscription, {
endpoint: subscriptionData.endpoint,
keys: subscriptionData.keys,
userAgent: navigator.userAgent,
});
const timeoutMutationPromise = new Promise<{ sucesso: false; erro: string }>((resolve) =>
setTimeout(() => resolve({ sucesso: false, erro: "Timeout" }), 5000)
);
const resultado = await Promise.race([mutationPromise, timeoutMutationPromise]);
if (resultado.sucesso) {
console.log("✅ Push subscription registrada com sucesso");
} else {
} else if (resultado.erro && !resultado.erro.includes("Timeout")) {
console.error("❌ Erro ao registrar push subscription:", resultado.erro);
}
} catch (error) {
// Ignorar erros relacionados a message channel fechado
if (error instanceof Error && error.message.includes("message channel")) {
return;
}
console.error("❌ Erro ao configurar push notifications:", error);
}
}