Feature: Obtener iconos automáticamente de las aplicaciones
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 54s

- Intentar meta_icon de Authentik primero
- Buscar apple-touch-icon.png del dominio (PWA)
- Intentar favicon.ico como fallback
- Mostrar icono por defecto si todo falla
- Sistema de retry inteligente para evitar requests duplicados
This commit is contained in:
2025-10-16 22:56:15 -06:00
parent bc19956e10
commit 8b94e81dc8

View File

@@ -57,10 +57,12 @@
>
<div class="app-card-content">
<div class="app-icon">
<UIcon
v-if="app.icon"
:name="app.icon"
class="w-7 h-7"
<img
v-if="getAppIconUrl(app)"
:src="getAppIconUrl(app)"
:alt="app.name"
class="w-7 h-7 object-contain"
@error="handleIconError($event, app)"
/>
<UIcon
v-else
@@ -123,6 +125,65 @@ const { data: applications, pending, error, refresh } = await useFetch<Applicati
// Estado de filtros
const selectedGroups = ref<string[]>([])
// Estado para iconos fallidos (para no intentar cargarlos de nuevo)
const failedIcons = ref<Set<string>>(new Set())
// Función para obtener la URL del icono de una app
const getAppIconUrl = (app: Application): string | null => {
// Si el icono ya falló, no intentar de nuevo
if (failedIcons.value.has(app.pk)) {
return null
}
// Si tiene meta_icon de Authentik, usarlo
if (app.icon) {
// Si es una URL completa
if (app.icon.startsWith('http://') || app.icon.startsWith('https://')) {
return app.icon
}
// Si es una ruta relativa, usar el dominio de la app
try {
const url = new URL(app.launchUrl)
return `${url.origin}${app.icon.startsWith('/') ? '' : '/'}${app.icon}`
} catch {
return null
}
}
// Intentar obtener el favicon de la URL
try {
const url = new URL(app.launchUrl)
// Intentar primero apple-touch-icon (suele ser de mejor calidad)
return `${url.origin}/apple-touch-icon.png`
} catch {
return null
}
}
// Manejar error al cargar icono
const handleIconError = (event: Event, app: Application) => {
const imgElement = event.target as HTMLImageElement
const currentSrc = imgElement.src
// Marcar como fallido
failedIcons.value.add(app.pk)
// Si estábamos intentando apple-touch-icon, intentar favicon.ico
if (currentSrc.includes('apple-touch-icon')) {
try {
const url = new URL(app.launchUrl)
imgElement.src = `${url.origin}/favicon.ico`
failedIcons.value.delete(app.pk) // Dar otra oportunidad
return
} catch {
// Si falla, el v-else mostrará el icono por defecto
}
}
// Ocultar la imagen para que se muestre el icono por defecto
imgElement.style.display = 'none'
}
// Extraer todos los grupos únicos de las aplicaciones
const availableGroups = computed(() => {
const groups = new Set<string>()