Call audio video jitsi #40

Merged
deyvisonwanderley merged 9 commits from call-audio-video-jitsi into master 2025-11-23 01:41:20 +00:00
29 changed files with 3804 additions and 404 deletions
Showing only changes of commit aeaa3c903f - Show all commits

View File

@@ -1,10 +1,15 @@
<script lang="ts"> <script lang="ts">
import { useConvexClient } from "convex-svelte"; import { useConvexClient } from "convex-svelte";
import { useQuery } from "convex-svelte";
import { api } from "@sgse-app/backend/convex/_generated/api"; import { api } from "@sgse-app/backend/convex/_generated/api";
import { onMount } from "svelte"; import { onMount } from "svelte";
const client = useConvexClient(); const client = useConvexClient();
// Verificar se o usuário está autenticado antes de gerenciar presença
const currentUser = useQuery(api.auth.getCurrentUser, {});
const usuarioAutenticado = $derived(currentUser?.data !== null && currentUser?.data !== undefined);
// Token é passado automaticamente via interceptadores em +layout.svelte // Token é passado automaticamente via interceptadores em +layout.svelte
let heartbeatInterval: ReturnType<typeof setInterval> | null = null; let heartbeatInterval: ReturnType<typeof setInterval> | null = null;
@@ -13,6 +18,8 @@
// Detectar atividade do usuário // Detectar atividade do usuário
function handleActivity() { function handleActivity() {
if (!usuarioAutenticado) return;
lastActivity = Date.now(); lastActivity = Date.now();
// Limpar timeout de inatividade anterior // Limpar timeout de inatividade anterior
@@ -22,16 +29,29 @@
// Configurar novo timeout (5 minutos) // Configurar novo timeout (5 minutos)
inactivityTimeout = setTimeout(() => { inactivityTimeout = setTimeout(() => {
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" }); if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
}
}, 5 * 60 * 1000); }, 5 * 60 * 1000);
} }
onMount(() => { onMount(() => {
// Configurar como online ao montar // Só configurar presença se usuário estiver autenticado
if (!usuarioAutenticado) return;
// Configurar como online ao montar (apenas se autenticado)
client.mutation(api.chat.atualizarStatusPresenca, { status: "online" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "online" });
// Heartbeat a cada 30 segundos // Heartbeat a cada 30 segundos (apenas se autenticado)
heartbeatInterval = setInterval(() => { heartbeatInterval = setInterval(() => {
if (!usuarioAutenticado) {
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
return;
}
const timeSinceLastActivity = Date.now() - lastActivity; const timeSinceLastActivity = Date.now() - lastActivity;
// Se houve atividade nos últimos 5 minutos, manter online // Se houve atividade nos últimos 5 minutos, manter online
@@ -47,10 +67,14 @@
}); });
// Configurar timeout inicial de inatividade // Configurar timeout inicial de inatividade
handleActivity(); if (usuarioAutenticado) {
handleActivity();
}
// Detectar quando a aba fica inativa/ativa // Detectar quando a aba fica inativa/ativa
function handleVisibilityChange() { function handleVisibilityChange() {
if (!usuarioAutenticado) return;
if (document.hidden) { if (document.hidden) {
// Aba ficou inativa // Aba ficou inativa
client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" }); client.mutation(api.chat.atualizarStatusPresenca, { status: "ausente" });
@@ -65,8 +89,10 @@
// Cleanup // Cleanup
return () => { return () => {
// Marcar como offline ao desmontar // Marcar como offline ao desmontar (apenas se autenticado)
client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" }); if (usuarioAutenticado) {
client.mutation(api.chat.atualizarStatusPresenca, { status: "offline" });
}
if (heartbeatInterval) { if (heartbeatInterval) {
clearInterval(heartbeatInterval); clearInterval(heartbeatInterval);
@@ -86,4 +112,3 @@
</script> </script>
<!-- Componente invisível - apenas lógica --> <!-- Componente invisível - apenas lógica -->

View File

@@ -125,11 +125,23 @@
const funcionarioIdDisponivel = $derived(currentUser?.data?.funcionarioId ?? null); const funcionarioIdDisponivel = $derived(currentUser?.data?.funcionarioId ?? null);
const gestorIdDisponivel = $derived(currentUser?.data?._id ?? null); const gestorIdDisponivel = $derived(currentUser?.data?._id ?? null);
// ✅ CORRIGIDO: Queries no nível superior (sem argumentos) sempre criadas // Verificar autenticação antes de executar queries
const usuarioAutenticado = $derived(currentUser?.data !== null && currentUser?.data !== undefined);
// ✅ CORRIGIDO: Queries condicionais - só executar se usuário estiver autenticado
// Queries que não requerem argumentos são criadas uma vez // Queries que não requerem argumentos são criadas uma vez
const funcionarioQuery = useQuery(api.funcionarios.getCurrent, {}); const funcionarioQuery = useQuery(
const timesSubordinadosQuery = useQuery(api.times.listarSubordinadosDoGestorAtual, {}); api.funcionarios.getCurrent,
const chamadosQuery = useQuery(api.chamados.listarChamadosUsuario, {}); usuarioAutenticado ? {} : 'skip'
);
const timesSubordinadosQuery = useQuery(
api.times.listarSubordinadosDoGestorAtual,
usuarioAutenticado ? {} : 'skip'
);
const chamadosQuery = useQuery(
api.chamados.listarChamadosUsuario,
usuarioAutenticado ? {} : 'skip'
);
// ✅ CORRIGIDO: Queries com argumentos obrigatórios usando $derived.by para estabilidade // ✅ CORRIGIDO: Queries com argumentos obrigatórios usando $derived.by para estabilidade
// Usamos uma chave estável baseada no ID para evitar recriação desnecessária // Usamos uma chave estável baseada no ID para evitar recriação desnecessária