Memora — Feedback iteración (uso real iPhone 14)
Recopilación íntegra del feedback de Gonzalo tras varios días de uso real en iPhone 14 (Safari + Chrome). Cada item incluye prioridad y nota técnica para no perder detalles entre sesiones de trabajo.
Leyenda prioridad: P0 = bloqueante / pérdida de datos · P1 = UX clave · P2 = mejora · P3 = nice‑to‑have. Estado: ✅ hecho · 🟡 parcial · ⏳ pendiente.
⚠️ Deploy
Siempre desde storefronts/memora/:
cd storefronts/memora
npm run deploy
Cloudflare Pages tiene memora marcado como "Bindings managed through wrangler.toml".
Si se ejecuta wrangler pages deploy desde la raíz del monorepo, no localiza
el wrangler.toml y falla con Binding name 'GOOGLE_CLIENT_ID' already in use
(falso positivo: hereda bindings de otros projects hermanos).
El script deploy de package.json ya está corregido para no salir del cwd —
NO restaurar el viejo cd ../...
Resumen de esta tanda
| Item | Estado | Notas |
|---|---|---|
| D1 Export libro Safari | ✅ | Navegación directa con ?t=token (mismo patrón que /api/memora/assets/[id]). En iOS abre en misma pestaña; en desktop, nueva. |
| D2 Imágenes en export | ✅ | book.js carga memora_asset kind=photo por entry y embebe <img> con CSS .photos (grid). |
| A1 Suggestions: crear/asignar capítulo | ✅ | Bloque nuevo en SuggestionsPanel con chips a capítulos existentes + input “Crear capítulo”. |
| B1 Today: navegar días anteriores | ✅ | TodayEntries con flechas ‹/›, etiqueta dinámica (Hoy/Ayer/Antes de ayer/día), paginación auto. |
| G1 Popups cerrar al clic fuera | ✅ | Script global en app.astro: cierra <details> al click fuera + Escape + “solo uno abierto”. |
| A4 Editar lugar de una entry | ✅ | EntryCard añade input “Lugar” en modo edición → PUT locationText. |
| F1 Audio sigue en background | 🟡 | Wake Lock añadido en useVoiceRecorder (acquire al start, release al stop, re-acquire on visibility). Falta buffer IndexedDB para resiliencia total. |
| E1 Onboarding Safari iOS | 🟡 | Robustecido (try/catch localStorage, expone window.__memoraOnboarding). Si sigue sin aparecer, abrir Web Inspector iOS y mirar esa variable + errores JS. |
| A2 Asignar capítulo desde "Hoy" | ⏳ | EntryCard ya tiene "Añadir a capítulo" (cambia tab). Mejora futura: modal in‑place sin cambiar de tab. |
| A3 Modal publicar unificado | ⏳ | Diseño grande; mejor en una iteración dedicada. |
| A5 Hashtags cross-libros | ⏳ | Requiere migración: tabla memora_tag + memora_entry_tag. |
| C1 Clic en mensaje abre detalle | ⏳ | Por ahora EntryCard se expande inline (truncated 600). Modal detallado pendiente. |
| C2 Filtros en Línea | ⏳ | Hoy soporta personId y q. Añadir capítulo, etiqueta, lugar, rango fecha. |
| C3 Fragmentos truncados | ⏳ | Mejora visual de la vista de capítulo. |
A. Captura y composición ("Hoy" / Composer)
A1. Crear capítulo desde la sugerencia (P1)
- Hoy, después de añadir una entrada en "Cuenta tu día", el panel de Sugerencias propone capítulos / hashtags. Pero no se puede crear un capítulo nuevo ni añadir directamente la entrada a un capítulo existente desde la sugerencia.
- Toca ir a Línea → buscar el mensaje → asignar a capítulo, lo que rompe el flujo.
- Acción: botones inline en cada
Suggestion→- "➕ Crear capítulo «X»"
- "↳ Añadir a capítulo…" (autocomplete entre capítulos del libro activo)
- "🏷️ Aplicar hashtags propuestos"
- Archivos clave:
SuggestionsPanel.tsx,ChaptersPanel.tsx, endpoints/api/memora/chapters/*.
A2. Asignar a capítulo desde "Hoy" (P1)
- Mismo problema: en la tarjeta de un mensaje recién creado debería poder asignarse a capítulo sin salir de "Hoy".
- Acción: menú contextual en
EntryCardcon opción "Mover a capítulo…" (modal con búsqueda).
A3. Flujo de publicar — modal unificado (P1)
- Revisar flujo de publicar entero. Propuesta: un modal único al
publicar que reúna en un solo paso:
- Texto del mensaje (editable).
- Capítulo: existente o crear nuevo (input rápido).
- Personas mencionadas (como ahora).
- Hashtags sugeridos por IA + manuales.
- Lugar: ver A4.
- Nivel de intimidad.
- Hoy estos pasos están dispersos por varios paneles → fricción alta.
A4. Lugares: IA debe usar ubicación real (P1)
- Caso real: dije "Vilallonga" pensando en la de Valencia (la del lado),
pero la IA asignó otra Vilallonga. No puedo cambiarlo a posteriori.
- Cuando hablé desde Belfast preguntó "esto viene de Belfast, ¿lo confirmas?" → ese flujo SÍ funcionó bien.
- Acciones:
- Pasar
geolocation(lat/lng aproximada con consentimiento) al prompt de extracción de entidades para desambiguar topónimos. - Cuando haya dudas geográficas (varios candidatos a < 50km) → preguntar al usuario antes de asignar.
- Permitir editar el lugar de un mensaje ya publicado
(
EntryCard→ menú → "Cambiar lugar").
- Pasar
A5. Hashtags y etiquetas (P1)
- Falta gestión real de etiquetas:
- Vista global "Mis etiquetas" con conteos.
- Buscar por etiqueta entre libros.
- Renombrar / fusionar etiquetas.
- Sugerencias de hashtags coherentes (re‑usar los existentes antes de inventar nuevos).
B. Vista "Hoy" / Histórico
B1. Recuperar días anteriores (P1)
- A las 00:00 cambia de día y "Hoy" se vacía. No se puede volver a ayer / antes de ayer sin ir a Línea.
- Acción: flechas «‹ Ayer · Hoy · Mañana ›» en cabecera de
TodayEntries- posibilidad de ver vista "Esta semana" colapsada por día.
- Implementación: parámetro
?date=YYYY-MM-DDen la página, query D1 por rango.
B2. Hoy → asignar a capítulo (duplicado de A2, dejarlo aquí también
por trazabilidad).
C. Línea / Timeline / Vista de libro
C1. Clic en mensaje abre detalle (P1)
- En la vista de libro / capítulo se ven los mensajes y se pueden reordenar (subir/bajar). Bien. Pero clic ≠ abrir.
- Para ver el mensaje completo / editar hay que ir a Línea y buscarlo.
- Acción: clic en
EntryCarddentro de capítulo abre modal de detalle con texto íntegro, audio, imágenes, lugar, intimidad, acciones (editar, mover, borrar).
C2. Filtros en Línea (P1)
- Línea necesita filtros: por etiqueta, por persona, por capítulo, por rango de fechas, por lugar, por libro, por tipo (audio/texto/foto).
- Búsqueda full‑text con debounce.
C3. Fragmentos truncados (P2)
- En vista de capítulo solo se ve un trocito del texto. Aumentar a 3 líneas con "ver más" o tarjeta expandible inline.
D. Exportar libro
D1. Exportar libro NO funciona en Safari iOS (P0)
- Pulsar "Exportar" en Safari iPhone → no pasa nada.
- Posibles causas:
window.openbloqueado,<a download>ignorado en iOS, blob > limit, faltan headersContent-Disposition. - Acción: detectar Safari iOS y caer a:
- Abrir el blob en nueva pestaña (
location.href = blobURL) tras user gesture directo. - Alternativa: generar el PDF en backend (function) y devolver URL firmada de descarga en R2.
- Abrir el blob en nueva pestaña (
D2. Imágenes de mensajes no aparecen en export (P0)
- Cuando un mensaje tiene imágenes, en el libro exportado no salen.
- Acción: en el generador (jspdf / pdf‑lib / html→pdf) asegurar:
- Resolver URLs absolutas (R2 público o presigned).
awaitcarga de imagen antes de embed.- Soportar formatos: JPEG/PNG/WebP. Convertir HEIC a JPEG si llega.
- Test E2E: libro con 1 entrada + 1 imagen → PDF contiene la imagen.
E. Onboarding
E1. No aparece en Safari iOS (P0)
- En iPhone Safari no aparece la explicación. En iPhone Chrome sí.
- Hipótesis: condición CSS / detección de viewport /
localStorage/navigator.userAgento el<dialog>no se abre en Safari. - Acción: revisar
OnboardingTour.tsx/OnboardingBanner.tsx/UserOnboarding.tsx:- No usar
<dialog showModal()>sin polyfill (Safari < 15.4 lo soporta, pero hay quirks con iOS). - Reemplazar por overlay propio con
position: fixed; inset: 0. - Probar con DevTools → Safari iOS Simulator.
- No usar
F. Audio / Grabación
F1. Pantalla bloqueada corta el audio (P0)
- En iPhone, si la pantalla se bloquea durante la grabación, sigue grabando aparentemente pero al recuperar se corta o se pierde.
- Acción:
- Usar
MediaRecordercontimeslice(chunks cada 1‑5s) y persistir cada chunk en IndexedDB → ensamblar al final. Así si se corta no perdemos todo. - Pedir
wake lock(navigator.wakeLock.request('screen')) durante grabación activa. - Mostrar aviso visible: "Mantén la app en primer plano".
- Indicador de "audio guardado hasta HH:MM:SS" en vivo.
- Usar
G. UX / Componentes
G1. Pop‑ups no se cierran con clic fuera (P1)
- Algunos menús contextuales se quedan abiertos: clic en otro elemento abre otro popup encima sin cerrar el primero. Solo cierran clicando el mismo botón que los abrió.
- Acción: patrón único de menú con:
- Backdrop transparente que captura clic fuera → cerrar.
Escapecierra.- Solo un menú abierto a la vez (singleton / context).
- Usar
<Popover>oRadix Dropdowny unificar.
Prioridades sugeridas para esta tanda
- P0 bug fixes: D1, D2, E1, F1.
- P1 flujo de publicar: A1, A2, A3, A4, A5.
- P1 navegación: B1, C1, C2.
- P1 UX: G1.
- P2/P3: C3 + pulido.
Notas para no olvidar
- Probar SIEMPRE en Safari iOS real (no solo Chrome desktop).
- Mantener IndexedDB como buffer offline para audio + entradas no publicadas.
- Cualquier cambio en flujo de publicar → re‑grabar onboarding/tour.
- Documentar nuevo modal de publicar en
MEMORA_OVERVIEW.md.