9.3 KiB
CONTINUE — RTL del Slider y del media-player (+ la cola del hilo de audio)
Kickoff: "Lee
docs/process/CONTINUE-player-rtl.mdy empieza por §2." Fecha: 2026-08-01 · actualizado 2026-08-02 · Ramaalpha-0.1-dir-prefs(sale dealpha-0.1-sec-dom). §1 está CERRADO — no lo rehagas. Lo abierto empieza en §2. El hilo de audio propiamente dicho sigue enCONTINUE-sound-engine.md; este documento recoge lo que la mirada del usuario abrió el 2026-08-01 y quedó SIN cerrar.
Lo que se cerró el 2026-08-01 (7 commits, verificados)
| Commit | Qué |
|---|---|
df86a4e50 |
El anillo del commit dejaba de enmarcar contenedores (slider + media-player) · saltar al final ya no anuncia compleción falsa |
e096f65e3 |
MediaSession verificada por el usuario (carátula + título + artista en el hub de Chrome) |
905012507 |
Waveform: el buffered vuelve a banda recta con acento lavado |
58acb778e |
Waveform F6 firmada — iniciativa COMPLETA |
77f8a4e46 |
La demo del waveform carga solo la pista real; sample deja de fingir que es una prop |
4356020e3 |
La carátula de card sale a token (--audio-player-artwork-size-card) |
3ceda5b59 |
El botón de velocidad ya dice su velocidad (emit: 'value') · el player reenvía dir a sus dos sliders |
1. PRIORIDAD — el Slider está roto en RTL · CERRADO 2026-08-02
Cerrado en 013ceac57 + 5469e05df (rama alpha-0.1-dir-prefs). La
hipótesis de este documento acertó las dos piezas visibles — el Slider sí
estampaba dir y slider.css sí mezclaba lógicas con físicas — pero eran
síntomas, no la causa. Lo que resultó ser, medido:
| Del slider | slider.css emparejaba inset-inline-start: 50% (lógico) con translateX(-50%) (FÍSICO, no se voltea) en las tres reglas verticales. Medido en Chrome: raíz/pulgar/ticks en x=961, raíl y relleno en x=955. El Tick se libraba porque ya usaba margin-inline-start — ése era el idioma correcto del propio fichero. Mismo defecto en accordion.css (text-align: left), el único físico que quedaba en todo eidos. |
| La causa raíz, que no estaba en las hipótesis | makeDimension().get() (arts/prefs) leía engine.snapshot() esquivando la celda $state, así que soma.prefs.getDir() era una lectura sin tracking y los ~64 componentes que resuelven su dirección desde prefs la congelaban al montarse. La proyección DOM se salvaba porque usa onChange: misma dimensión, dos caminos de lectura, uno solo reactivo. |
| Y el estampado | 33 de 37 componentes escribían dir con un valor SIEMPRE concreto → una app que ponga <html dir="rtl"> sin registrar la preferencia se encontraba 33 islas del revés. Ahora el atributo se omite cuando nadie afirmó nada (modelo de Zag, aplicado uniforme). |
No hizo falta elegir «un solo dueño de la inversión»: el JS sigue calculando físico y el CSS sigue siendo lógico. No había doble volteo — había un transform físico donde tocaba uno lógico.
✅ La contradicción del pulgar del volumen queda explicada: con getDir()
congelado, el mismo slider daba lecturas distintas según cuándo se midiera
respecto al montaje. No era una sonda mintiendo.
Guards que nacieron en rojo y ahora pasan:
arts/prefs/test/active-prefs-reactivity.svelte.test.ts (intent · derivación ·
granularidad por clave) y uix/active-uix/test/prefs-view.svelte.test.ts.
De regalo: elegir árabe voltea la dirección por derivación desde el idioma —
la cadena que active-architecture.md:407 documenta y que en esta app era
código muerto, porque la shell fijaba intent desde el primer frame y no había
ningún idioma RTL en el catálogo.
⚠️ Sigue abierto de este eje: html lang no sigue al idioma (el dir sí), y
perm:check sin ejecutar — el topbar ya lleva data-perm-step, lo que hace que
toda ruta tenga paso y la pasada sea mucho más larga.
2. La disposición de los botones del player en RTL — APARTE y abierto
El usuario insiste en que no es lo mismo que §1: aun con el Slider
arreglado, la disposición que él ve sigue mal. Las sondas de la sesión decían
que el orden mirroriza (orden exactamente invertido en vídeo y en audio/card, y
el transporte interno ⏪ ▶ ⏩ → ⏩ ▶ ⏪), pero esas sondas se equivocaron
varias veces ese día — dos de ellas midieron vídeo creyendo que medían audio.
Tratar sus números como NO fiables y volver a mirar con la página delante.
3. Iconos de seek en RTL — decisión tomada, sin aplicar
Medido: las posiciones mirrorizan pero los iconos no se voltean
(transform: none en ambas direcciones). Recomendación dada al usuario y
aceptada implícitamente al pedir «arregla el rtl/ltr»: voltearlos. El icono
no dice «derecha», dice «adelante en el tiempo», y el eje temporal en RTL corre
hacia la izquierda — igual que la barra de progreso, que ancla en right. Si el
slider avanza a la izquierda y la flecha de avanzar apunta a la derecha, se
contradicen dentro del mismo control. Es lo que hacen YouTube y Spotify en árabe.
Decidir al aplicarlo: ¿volteo del icono en el propio botón, o regla RTL transversal de eidos? (afecta a cualquier icono direccional del catálogo).
4. Medición del escenario mixto — NO concluyente, repetir bien
Lo que SÍ quedó establecido: la media no abre ningún AudioContext (con
audio sonando de verdad, cero contextos creados) — el transporte va por la
tubería nativa, no por Web Audio, porque attach() es opt-in y nadie lo activa.
Esa es la mitad importante de la invariante.
Lo que NO: la mitad del earcon. Se instrumentó AudioContext después del
arranque, así que un contexto ya existente no se ve; el 0 creados sólo prueba
que no se creó uno NUEVO. soundOn: true está en prefs.
Para cerrarlo: instrumentar antes del boot y llegar a la página con una navegación client-side (sin recargar, o el parche se pierde).
5. Iniciativas dormidas (cada una con su gate)
Captions— parte declarada en el morfo desde el principio y nunca implementada. Diagnóstico completo y medido: el player pone las pistas enmode='showing', así que Chrome pinta su caja de cues enbottom: 0del<video>— la MISMA franja de 49px que la barra de controles — y como el vídeo computaz-index: autofrente alz-index: 4de la barra al 82% de opacidad, llega el 18% del texto («apenas imperceptible»).::cueNO puede arreglarlo: la especificación no admite propiedades de posición. Arreglo real:mode='hidden'+ pintaractiveCuesen la parte declarada. Defecto latente adicional:captionsOnes un espejo de una sola dirección (nunca releetrack.mode), así que si Chrome activa subtítulos por preferencia del SO salen cues mientras el botón dice que están apagados.- Waveform como scrubber del player — cero cables hoy entre ambos, y es
deliberado (D-AP2.4 +
PLAN-waveform.md§0 lo aplazan a la v2 del player). El nudo NO es cambiar el componente: es de dónde salen los picos. El contrato del waveform (D-WF.2) dice que los provee la app, y un player streamea, así que no puede decodificar su fuente sin bajársela entera. Verificado además quefetchdemedia.w3.orgysoundhelix.comfalla por CORS mientras el<audio>las reproduce sin problema. Empezar por la varianteinline(nota de voz): ahí el audio SÍ es local y corto.
Lecciones de método del 2026-08-01 — leer antes de repetirlas
- Medir el contrato NO es verificar la experiencia. Se afirmó tres veces
que algo estaba verificado midiendo JS: la MediaSession (metadata poblada
≠ overlay del SO visible), el botón de velocidad (cambiaba
playbackRateperfectamente… y no lo mostraba) y el RTL (se comprobó LTR y se dio RTL por bueno). Las tres las cazó el usuario. - El panel del navegador embebido NO SIRVE para nada visual:
innerWidth: 0,visibility: hidden, el stage mide 2px. Ese día inventó tres «overflow» inexistentes y un hueco de carátula que estaba bien. Screenshot falla con «not compositing frames». Para cualquier juicio visual, usar el Chrome real del usuario (mcp__claude-in-chrome__*). - Comprobar que el control se pulsó de verdad. Dos medidas de esa sesión
midieron el modo vídeo creyendo que era audio porque el chip no cambió y
nadie lo verificó. Leer siempre
data-media/data-variantdespués de clicar. - La distancia RGB engaña: avaló un gris que el ojo del usuario rechazó al instante. Está dominada por la luminosidad y es ciega al croma.
- La forma manda sobre el color: el buffered del waveform se rechazó dos veces; la segunda porque una copia de la onda es la onda y se camufla por construcción, por muy distinto que sea su color.