You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
8.6 KiB
140 lines
8.6 KiB
|
2 months ago
|
# CONTINUE — RTL del Slider y del media-player (+ la cola del hilo de audio)
|
||
|
|
|
||
|
|
> **Kickoff**: _"Lee `docs/process/CONTINUE-player-rtl.md` y empieza por §1."_
|
||
|
|
> **Fecha**: 2026-08-01 · Rama `alpha-0.1-sec-dom`.
|
||
|
|
> El hilo de audio propiamente dicho sigue en
|
||
|
|
> [`CONTINUE-sound-engine.md`](./CONTINUE-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
|
||
|
|
|
||
|
|
**Confirmado por el usuario con el componente SUELTO** (`/uix/components/slider`),
|
||
|
|
sin player de por medio. No es un fallo del media-player: es del componente
|
||
|
|
canónico del que cuelgan **waveform · media-player · color-picker · time-picker ·
|
||
|
|
time-range-picker**. Arreglarlo mal los rompe los cinco a la vez.
|
||
|
|
|
||
|
|
Lo que YA se descartó leyendo el código — las dos piezas centrales están bien
|
||
|
|
en aislamiento:
|
||
|
|
|
||
|
|
- `slider-provider.svelte.ts:160-180` — `getValueFromPointer` invierte el
|
||
|
|
porcentaje en RTL (`if (isRtl) percent = 1 - percent`). Correcto.
|
||
|
|
- `slider-provider.svelte.ts:~422-438` — `rangeStyle` usa `right` en vez de
|
||
|
|
`left` cuando `isRtl`. Correcto.
|
||
|
|
|
||
|
|
**HIPÓTESIS a probar primero (dos minutos, decide el arreglo entero):** el
|
||
|
|
Slider **estampa `dir` como atributo HTML** en su propio elemento
|
||
|
|
(`slider-provider.svelte.ts:385`, `dir: this.opts.dir.current`). Eso hace que el
|
||
|
|
navegador le aplique además `direction: rtl` en CSS. Y `slider.css` mezcla
|
||
|
|
propiedades **lógicas** (`inset-inline`, `inset-inline-start` en el track y los
|
||
|
|
casos verticales) con los estilos **físicos en línea** (`left` / `right`) que
|
||
|
|
calcula el provider. Ahí es donde salen los **doble-volteos**: el JS ya
|
||
|
|
invirtió y el CSS lógico vuelve a invertir.
|
||
|
|
|
||
|
|
Comprobación: abrir el Slider suelto en RTL y mirar si `[data-slider]::before`
|
||
|
|
(lógico) y el thumb (físico en línea) están usando ejes distintos.
|
||
|
|
|
||
|
|
Si se confirma, el arreglo es elegir **UN solo dueño de la inversión**:
|
||
|
|
|
||
|
|
- o el JS calcula físico y el CSS deja de ser lógico en esos ejes,
|
||
|
|
- o el CSS es lógico y el JS deja de invertir.
|
||
|
|
|
||
|
|
No los dos. Y el guard tiene que nacer en rojo (quitar el cableado y ver el
|
||
|
|
fallo) antes de darlo por bueno.
|
||
|
|
|
||
|
|
⚠️ **Contradicción sin resolver**, y probablemente el dato falso sea el de la
|
||
|
|
sesión: una sonda midió el pulgar del volumen en el borde DERECHO (correcto para
|
||
|
|
valor 0 en RTL) mientras la captura del usuario lo mostraba en el IZQUIERDO.
|
||
|
|
Resolverla con el componente suelto antes de tocar nada.
|
||
|
|
|
||
|
|
## 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 en
|
||
|
|
`mode='showing'`, así que Chrome pinta su caja de cues en `bottom: 0` del
|
||
|
|
`<video>` — la MISMA franja de 49px que la barra de controles — y como el
|
||
|
|
vídeo computa `z-index: auto` frente al `z-index: 4` de la barra al 82% de
|
||
|
|
opacidad, llega el **18%** del texto («apenas imperceptible»). `::cue` NO
|
||
|
|
puede arreglarlo: la especificación no admite propiedades de posición.
|
||
|
|
Arreglo real: `mode='hidden'` + pintar `activeCues` en la parte declarada.
|
||
|
|
Defecto latente adicional: `captionsOn` es un espejo de una sola dirección
|
||
|
|
(nunca relee `track.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 que `fetch` de `media.w3.org` y `soundhelix.com` **falla
|
||
|
|
por CORS** mientras el `<audio>` las reproduce sin problema. Empezar por la
|
||
|
|
variante **`inline`** (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 `playbackRate`
|
||
|
|
perfectamente… 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-variant` despué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.
|