fix(player): render the position the player reports, not its own
`seek-bar` renders `PlaybackPositionChanged` instead of counting: its setInterval survives only as interpolation *between* reports, stopped and restarted by every one of them, so its error is bounded by a second and is discarded rather than carried. Measured after: UI 00:34 / backend 34 across two keyboard seeks, against 00:44 / 73 before. The bar also stops lying about smaller things: the right-hand clock carries a minus sign and toggles to total duration on click, and the now-playing column starts at 320 px instead of 200, which is where "The Orchestra Of" came from. `now-playing.updated()` used to measure and rewrite its text geometry on every pass — six querySelectors and a read/write interleave — while the player store notifies at 1 Hz. It now runs only when its geometry key changes: the rendered title, the rendered artist, both scroll flags, or the ResizeObserver reporting a resize, with every read before every write. Over six seconds of playback: 52 forced layouts -> 2, and 3.2 ms -> 0.9 ms inside updated(). The scroll flags are in that key because `.will-scroll .scroll-content` carries `padding-right: 2em`, so applying the class changes the distance the marquee travels — -128 px before it, -158 px after. A guard on the text alone leaves every first hover scrolling short, and nothing in any test tier would have caught it. The resize's document listeners now attach on mousedown and detach on mouseup, rather than running on every pointer move in the app for the life of the process.
This commit is contained in:
@@ -1,13 +1,27 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import '@awesome.me/webawesome/dist/components/icon/icon.js';
|
||||
import './controls/player-controls';
|
||||
import './seekbar/seek-bar';
|
||||
import './volume-control/volume-control';
|
||||
import '../notifications/inline-notice';
|
||||
import { PlayerRegion } from '@store/player-store';
|
||||
import { designTokens } from '../../styles/tokens.css';
|
||||
|
||||
/**
|
||||
* The bottom bar. The transport lives here, and so does the one place
|
||||
* the player admits it could not do what it was told — an
|
||||
* `<inline-notice>` for the `player` region, floated above the bar
|
||||
* because `.bottom-bar` is a fixed 4em grid row with no room in it.
|
||||
*/
|
||||
@customElement('audio-player')
|
||||
export class AudioPlayer extends LitElement {
|
||||
static override styles = [designTokens, css`
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.audio-player-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -17,10 +31,16 @@ export class AudioPlayer extends LitElement {
|
||||
.player-main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
`];
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<inline-notice
|
||||
region=${PlayerRegion}
|
||||
testid="player-message"
|
||||
floating
|
||||
></inline-notice>
|
||||
<div class="audio-player-container">
|
||||
<div class="player-main">
|
||||
<player-controls></player-controls>
|
||||
|
||||
Reference in New Issue
Block a user