fix timeline
This commit is contained in:
parent
6b8f27ad19
commit
f0346d82ad
@ -23,7 +23,6 @@ class SimpleAudioPlayer {
|
|||||||
this.isSeeking = false;
|
this.isSeeking = false;
|
||||||
this.rafId = null;
|
this.rafId = null;
|
||||||
this.abortCtrl = null;
|
this.abortCtrl = null;
|
||||||
this._posInterval = null;
|
|
||||||
|
|
||||||
// Pre-compute icons once
|
// Pre-compute icons once
|
||||||
const fill = getComputedStyle(document.documentElement)
|
const fill = getComputedStyle(document.documentElement)
|
||||||
@ -53,6 +52,32 @@ class SimpleAudioPlayer {
|
|||||||
this._initMediaSession();
|
this._initMediaSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push the current position to MediaSession so lockscreen / BT UIs stay in sync.
|
||||||
|
* Keeps values strict but avoids over-clamping that can confuse some platforms.
|
||||||
|
*/
|
||||||
|
_pushPositionState(force = false) {
|
||||||
|
if (!navigator.mediaSession?.setPositionState) return;
|
||||||
|
|
||||||
|
const duration = this.audio.duration;
|
||||||
|
const position = this.audio.currentTime;
|
||||||
|
if (!Number.isFinite(duration) || duration <= 0) return;
|
||||||
|
if (!Number.isFinite(position) || position < 0) return;
|
||||||
|
|
||||||
|
const playbackRate = this.audio.paused
|
||||||
|
? 0
|
||||||
|
: (Number.isFinite(this.audio.playbackRate) ? this.audio.playbackRate : 1);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ('playbackState' in navigator.mediaSession) {
|
||||||
|
navigator.mediaSession.playbackState = this.audio.paused ? 'paused' : 'playing';
|
||||||
|
}
|
||||||
|
navigator.mediaSession.setPositionState({ duration, playbackRate, position });
|
||||||
|
} catch (err) {
|
||||||
|
if (force) console.warn('setPositionState failed:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Minimal SVG helper
|
// Minimal SVG helper
|
||||||
svg(pathD, fill) {
|
svg(pathD, fill) {
|
||||||
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="${fill}">
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="${fill}">
|
||||||
@ -71,36 +96,40 @@ class SimpleAudioPlayer {
|
|||||||
this.timeline.max = this.audio.duration;
|
this.timeline.max = this.audio.duration;
|
||||||
this.timeline.value = 0;
|
this.timeline.value = 0;
|
||||||
this.timeline.style.backgroundSize = '0% 100%';
|
this.timeline.style.backgroundSize = '0% 100%';
|
||||||
|
this._pushPositionState(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.audio.addEventListener('play', () => this._updatePlayState());
|
this.audio.addEventListener('play', () => {
|
||||||
this.audio.addEventListener('pause', () => this._updatePlayState());
|
this._updatePlayState();
|
||||||
this.audio.addEventListener('ended', () => this.playBtn.innerHTML = this.icons.play);
|
this._pushPositionState(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.audio.addEventListener('playing', () => this._pushPositionState(true));
|
||||||
|
|
||||||
|
this.audio.addEventListener('pause', () => {
|
||||||
|
this._updatePlayState();
|
||||||
|
this._pushPositionState(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.audio.addEventListener('ratechange', () => this._pushPositionState(true));
|
||||||
|
this.audio.addEventListener('ended', () => {
|
||||||
|
this.playBtn.innerHTML = this.icons.play;
|
||||||
|
this._pushPositionState(true);
|
||||||
|
if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';
|
||||||
|
});
|
||||||
|
|
||||||
// Native timeupdate => update timeline
|
// Native timeupdate => update timeline
|
||||||
this.audio.addEventListener('timeupdate', () => this.updateTimeline());
|
this.audio.addEventListener('timeupdate', () => this.updateTimeline());
|
||||||
|
|
||||||
// Fallback interval for throttled mobile
|
// Keep position in sync when page visibility changes
|
||||||
this._interval = setInterval(() => {
|
document.addEventListener('visibilitychange', () => this._pushPositionState(true));
|
||||||
if (!this.audio.paused && !this.isSeeking) {
|
|
||||||
this.updateTimeline();
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Unified seek input
|
// Unified seek input
|
||||||
this.timeline.addEventListener('input', () => {
|
this.timeline.addEventListener('input', () => {
|
||||||
this.isSeeking = true;
|
this.isSeeking = true;
|
||||||
this.audio.currentTime = this.timeline.value;
|
this.audio.currentTime = this.timeline.value;
|
||||||
|
|
||||||
// immediate Android sync
|
this._pushPositionState(true); // immediate Android sync
|
||||||
if (navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
|
|
||||||
navigator.mediaSession.setPositionState({
|
|
||||||
duration: this.audio.duration,
|
|
||||||
playbackRate: this.audio.playbackRate,
|
|
||||||
position: this.audio.currentTime
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateTimeline();
|
this.updateTimeline();
|
||||||
this.isSeeking = false;
|
this.isSeeking = false;
|
||||||
});
|
});
|
||||||
@ -112,9 +141,7 @@ class SimpleAudioPlayer {
|
|||||||
|
|
||||||
_updatePlayState() {
|
_updatePlayState() {
|
||||||
this.playBtn.innerHTML = this.audio.paused ? this.icons.play : this.icons.pause;
|
this.playBtn.innerHTML = this.audio.paused ? this.icons.play : this.icons.pause;
|
||||||
if ('mediaSession' in navigator) {
|
this._pushPositionState(true); // lock‑screen refresh on play/pause toggle
|
||||||
navigator.mediaSession.playbackState = this.audio.paused ? 'paused' : 'playing';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_formatTime(sec) {
|
_formatTime(sec) {
|
||||||
@ -134,13 +161,7 @@ class SimpleAudioPlayer {
|
|||||||
this.timeInfo.textContent =
|
this.timeInfo.textContent =
|
||||||
`${this._formatTime(this.audio.currentTime)} / ${this._formatTime(this.audio.duration)}`;
|
`${this._formatTime(this.audio.currentTime)} / ${this._formatTime(this.audio.duration)}`;
|
||||||
// 4) Push to Android widget
|
// 4) Push to Android widget
|
||||||
if (navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
|
this._pushPositionState();
|
||||||
navigator.mediaSession.setPositionState({
|
|
||||||
duration: this.audio.duration,
|
|
||||||
playbackRate: this.audio.playbackRate,
|
|
||||||
position: this.audio.currentTime
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleCollapse() {
|
toggleCollapse() {
|
||||||
@ -267,16 +288,6 @@ class SimpleAudioPlayer {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Heartbeat for widget
|
|
||||||
this._posInterval = setInterval(() => {
|
|
||||||
if (!this.audio.paused && navigator.mediaSession?.setPositionState && Number.isFinite(this.audio.duration)) {
|
|
||||||
navigator.mediaSession.setPositionState({
|
|
||||||
duration: this.audio.duration,
|
|
||||||
playbackRate: this.audio.playbackRate,
|
|
||||||
position: this.audio.currentTime
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user