Revert "Revert "fix: implementar manejo correcto de modo offline""
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 8s

This reverts commit 192d8a7e79.
This commit is contained in:
2025-10-17 16:10:38 -06:00
parent 192d8a7e79
commit 381d389b7f
2 changed files with 89 additions and 11 deletions

View File

@@ -60,7 +60,7 @@
<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { UserCheck, UserX, Loader, ShieldAlert, ChevronDown, RefreshCw, LogOut } from 'lucide-vue-next'
import { UserCheck, UserX, Loader, ShieldAlert, ChevronDown, RefreshCw, LogOut, WifiOff } from 'lucide-vue-next'
import { useAuth } from '~/composables/useAuth'
import { useMusicStore } from '~/stores/music'
@@ -68,6 +68,7 @@ const {
isAuthenticated,
authChecked,
isCheckingAuth,
isOffline,
authStatus,
userInfo,
checkAuth,
@@ -124,6 +125,12 @@ watch(() => musicStore.error, (error, oldError) => {
if (error && error !== oldError) {
console.log('[AuthIndicator] Music store error detected:', error)
// Si estamos offline, NO marcar como no autenticado
if (isOffline.value) {
console.log('[AuthIndicator] Ignoring error - offline mode')
return
}
// Detectar errores de autenticación (múltiples formas)
const isAuthError =
error.includes('401') ||
@@ -144,6 +151,12 @@ watch(() => musicStore.error, (error, oldError) => {
// Watch loading state - cuando termina de cargar, verificar si hubo errores de auth
watch(() => musicStore.loading, (loading, wasLoading) => {
if (wasLoading && !loading && musicStore.error) {
// Si estamos offline, NO marcar como no autenticado
if (isOffline.value) {
console.log('[AuthIndicator] Ignoring loading error - offline mode')
return
}
// Terminó de cargar con error, verificar si es de auth
const error = musicStore.error
const isAuthError =
@@ -169,6 +182,8 @@ const iconComponent = computed(() => {
return UserCheck
case 'unauthenticated':
return UserX
case 'offline':
return WifiOff
default:
return ShieldAlert
}
@@ -182,6 +197,8 @@ const statusText = computed(() => {
return 'Conectado'
case 'unauthenticated':
return 'Reautenticar'
case 'offline':
return 'Offline'
default:
return 'Verificando...'
}
@@ -195,6 +212,8 @@ const tooltipText = computed(() => {
return 'Estás autenticado. Click para verificar estado.'
case 'unauthenticated':
return 'Sesión expirada. Click para iniciar sesión de nuevo.'
case 'offline':
return 'Sin conexión. Puedes usar contenido guardado offline.'
default:
return 'Verificando estado de autenticación...'
}
@@ -228,7 +247,11 @@ const closeDropdown = () => {
const handleClick = () => {
if (isCheckingAuth.value) return
if (authStatus.value === 'unauthenticated') {
if (authStatus.value === 'offline') {
// En modo offline, no hacer nada (ya no se puede autenticar)
console.log('[AuthIndicator] Click ignored - offline mode')
return
} else if (authStatus.value === 'unauthenticated') {
// Forzar reload de la página para que Authentik intercepte
triggerAuth()
} else if (authStatus.value === 'authenticated') {
@@ -367,6 +390,16 @@ onUnmounted(() => {
--status-color: #3b82f6;
}
.auth-indicator.offline {
--status-color: #f59e0b;
border-color: rgba(245, 158, 11, 0.3);
}
.auth-indicator.offline:hover {
border-color: rgba(245, 158, 11, 0.5);
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.2);
}
/* Animation for loading state */
@keyframes spin {
from {

View File

@@ -5,6 +5,7 @@ const authChecked = ref(true) // Iniciamos como chequeado
const isAuthenticated = ref(true) // Asumimos autenticado al inicio (si la página cargó, es porque pasamos Authentik)
const isCheckingAuth = ref(false)
const lastCheckTime = ref(0)
const isOffline = ref(false) // Estado de conexión
// Estado de información del usuario
const userInfo = ref(null)
@@ -14,7 +15,34 @@ let visibilityChangeListener: (() => void) | null = null
let focusListener: (() => void) | null = null
export const useAuth = () => {
// Detectar cambios en el estado de conexión
if (import.meta.client) {
const updateOnlineStatus = () => {
const wasOffline = isOffline.value
isOffline.value = !navigator.onLine
if (wasOffline && !isOffline.value) {
console.log('[Auth] Connection restored - back online')
} else if (!wasOffline && isOffline.value) {
console.log('[Auth] Connection lost - now offline')
}
}
// Inicializar estado
updateOnlineStatus()
// Escuchar eventos de conexión
window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)
}
const checkAuth = async (force = false) => {
// Si estamos offline, no hacer requests
if (isOffline.value && !force) {
console.log('[Auth] Skipping check - offline')
return
}
// Si ya sabemos que NO estamos autenticados, no hacer más requests
// (evita loops innecesarios)
if (!isAuthenticated.value && !force) {
@@ -54,16 +82,22 @@ export const useAuth = () => {
} catch (error: any) {
console.warn('[Auth] Check failed:', error.message || error)
const wasAuthenticated = isAuthenticated.value
// Verificar si estamos offline AHORA (pudo cambiar durante el request)
if (!navigator.onLine) {
console.log('[Auth] Offline detected - maintaining current auth state')
isOffline.value = true
// NO cambiar isAuthenticated cuando estamos offline
// Mantener el último estado conocido
} else {
// Online pero el fetch falló = problema de autenticación
const wasAuthenticated = isAuthenticated.value
console.log('[Auth] Online but fetch failed - marking as unauthenticated')
isAuthenticated.value = false
authChecked.value = true
// Si el fetch falla completamente (CORS, redirect, etc), asumir no autenticado
// Esto pasa cuando Authentik redirige antes de que el endpoint pueda responder
console.log('[Auth] Fetch failed - marking as unauthenticated')
isAuthenticated.value = false
authChecked.value = true
if (wasAuthenticated) {
console.log('[Auth] Status changed: authenticated → unauthenticated')
if (wasAuthenticated) {
console.log('[Auth] Status changed: authenticated → unauthenticated')
}
}
lastCheckTime.value = now
@@ -129,6 +163,14 @@ export const useAuth = () => {
const markUnauthenticated = async () => {
// Helper para marcar como no autenticado (útil cuando detectamos 401/403)
// IMPORTANTE: NO llamar esto si estamos offline, solo si hay un error real de auth
// Si estamos offline, NO marcar como no autenticado
if (isOffline.value || !navigator.onLine) {
console.log('[Auth] Skipping markUnauthenticated - offline mode')
return
}
console.log('[Auth] Marking as unauthenticated')
isAuthenticated.value = false
authChecked.value = true
@@ -198,6 +240,8 @@ export const useAuth = () => {
}
const authStatus = computed(() => {
// Si estamos offline, mostrar estado offline
if (isOffline.value) return 'offline'
if (!authChecked.value) return 'unknown'
return isAuthenticated.value ? 'authenticated' : 'unauthenticated'
})
@@ -206,6 +250,7 @@ export const useAuth = () => {
isAuthenticated,
authChecked,
isCheckingAuth,
isOffline,
authStatus,
userInfo,
checkAuth,