class PlaybackControls extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.isPlaying = false;
}
connectedCallback() {
this.render();
this.setupEventListeners();
}
static get observedAttributes() {
return ['duration', 'current-tick'];
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.render();
}
}
render() {
const duration = parseInt(this.getAttribute('duration') || '0');
const currentTick = parseInt(this.getAttribute('current-tick') || '0');
const progress = duration > 0 ? (currentTick / duration) * 100 : 0;
this.shadowRoot.innerHTML = `
${this.formatTime(currentTick)} / ${this.formatTime(duration)}
`;
// Feather icons need to be replaced after rendering
if (window.feather) {
window.feather.replace();
}
}
setupEventListeners() {
this.shadowRoot.querySelector('.play-pause').addEventListener('click', () => {
this.togglePlayback();
});
this.shadowRoot.querySelector('.progress-bar').addEventListener('click', (e) => {
const rect = e.target.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
const duration = parseInt(this.getAttribute('duration') || '0');
const seekTick = Math.floor(percent * duration);
this.setAttribute('current-tick', seekTick.toString());
window.playbackControls.seek(seekTick);
});
this.shadowRoot.querySelector('.speed-control').addEventListener('click', () => {
// Speed control logic would go here
});
}
togglePlayback() {
this.isPlaying = !this.isPlaying;
this.render();
if (this.isPlaying) {
window.playbackControls.play();
} else {
window.playbackControls.pause();
}
}
formatTime(ticks) {
if (!ticks) return '0:00';
const seconds = Math.floor(ticks / 30); // Assuming 30 ticks per second
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
}
}
customElements.define('custom-playback-controls', PlaybackControls);