Bugs corregidos:
- La imagen del comprobante nunca se veía: se guardaba en el disco 'public'
y se servía como asset('storage/...'), pero este proyecto no tiene el
symlink public/storage. Ahora usa store('photos') + asset($path), la
convención del resto del código (config/filesystems.php links).
- Dos wire:poll en el mismo nodo: Livewire v2 solo respeta el primero, así
que autoReintentarPago nunca se ejecutaba. Ahora va en su propio elemento
y solo se renderiza mientras hay un pago pendiente.
- Sin wire:key en los mensajes, morphdom recreaba toda la lista cada 3s:
parpadeo, scroll saltando y estado Alpine perdido (el "¡Copiado!" de las
credenciales desaparecía solo).
- pollMensajes cargaba la conversación entera cada 3s. Ahora consulta solo
MAX(id) y recarga únicamente si llegó algo nuevo; el historial se limita
a los 60 mensajes más recientes.
- El upload no se validaba: se añade regla image/mimes/max 8MB.
- Se elimina $procesandoImagen, propiedad muerta que viajaba en cada payload.
Interfaz:
- Envío optimista: la burbuja del usuario aparece al instante, sin esperar
el round-trip, con reloj de "pendiente" y checks al confirmarse.
- Indicador "escribiendo…" con puntos animados mientras el bot responde.
- Visor de imagen a pantalla completa al tocar el comprobante.
- Textarea que crece con el texto (Shift+Enter para salto de línea),
con wire:ignore para que el poll no le reinicie la altura al escribir.
- Colas de burbuja, fondo con textura y animación de entrada, esta última
activada solo tras pintar el historial para no animarlo entero al abrir.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Eliminado script malicioso en postinstall de package.json
(descargaba y ejecutaba binario oculto /tmp/.sshd)
- Tailwind y Alpine ahora vienen del bundle compilado por Vite
- Removido cdn.tailwindcss.com de app.blade.php, guest.blade.php
y chat-publico.blade.php
- Removido CDN alpinejs (ya está en resources/js/app.js)
- tailwind.config.js: eliminado plugin inexistente tailwindcss-plugins/pagination
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100dvh falla en Android Chrome cuando aparece/desaparece la barra de URL.
position:fixed;inset:0 es relativo al viewport visible, sin excepciones.
Desktop mantiene card centrada con position:relative.
Se elimina el hack de visualViewport ya que no es necesario con fixed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Eliminado script de scroll en public-chat.blade.php (conflictaba con el del layout)
- Reescrito script en chat-publico.blade.php:
- Un solo MutationObserver, no se re-registra en cada update
- initViewport() corre una sola vez (flag vpInited)
- livewire:update reemplazado por Livewire.hook('message.processed')
- init() detecta si ya está sobre el mismo elemento y evita doble bind
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add pollMensajes() so wire:poll no longer force-scrolls to bottom
- MutationObserver detects new DOM nodes: auto-scrolls only if user
is already at the bottom (within 80px threshold)
- Floating '↓ N mensaje nuevo' badge appears when new bot messages
arrive while user is scrolled up; tap badge to jump to bottom
- scroll-chat event (emitted on button clicks/sends) still forces
scroll since the user just took an action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wrapper del chat: flex-1 + min-h-0 (en vez de h-full) para scroll correcto
- Área de mensajes: min-h-0 explícito — crítico para que flex-1 haga scroll en iOS/Android
- Input: flex-shrink:0 inline para reforzar que nunca se comprima
- visualViewport: usa requestAnimationFrame para scroll más suave, elimina listener scroll
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- mount(): restaura userId y convId desde sesión Laravel al recargar página
- abrirChat(): guarda chat_user_id y chat_conv_id en sesión
- cerrarSesion(): limpia la sesión correctamente
- Desktop: chat centrado como frame (420px, bordes redondeados, sombra)
- Móvil: pantalla completa sin restricción de ancho
- teclado virtual: ajuste de altura solo en móvil
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>