aimbot-forensic-analyzer / components /playback-controls.js
LestradeMoran's picture
TypeError: Cannot read properties of undefined (reading 'accuracy')
af233fa verified
Raw
History Blame Contribute Delete
5.41 kB
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 = `
<style>
:host {
display: block;
}
.controls {
display: flex;
align-items: center;
gap: 1rem;
}
.play-pause {
background-color: #3b82f6;
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.2s;
}
.play-pause:hover {
background-color: #2563eb;
}
.progress-container {
flex-grow: 1;
display: flex;
align-items: center;
gap: 0.5rem;
}
.progress-bar {
flex-grow: 1;
height: 6px;
background-color: #374151;
border-radius: 3px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.progress-fill {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: #3b82f6;
width: ${progress}%;
}
.time {
font-size: 0.875rem;
color: #9ca3af;
min-width: 80px;
text-align: center;
}
.speed-control {
background-color: #374151;
color: white;
border: none;
border-radius: 4px;
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
cursor: pointer;
}
</style>
<div class="controls">
<button class="play-pause">
<i data-feather="${this.isPlaying ? 'pause' : 'play'}"></i>
</button>
<div class="progress-container">
<div class="time">
${this.formatTime(currentTick)} / ${this.formatTime(duration)}
</div>
<div class="progress-bar">
<div class="progress-fill"></div>
</div>
</div>
<button class="speed-control">1x</button>
</div>
`;
// 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);