class SelfTalkRecorder extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
Record Your Self-Talk
Speak freely for 1 minute about your thoughts, feelings, or affirmations.
Video preview will appear here
01:00
`;
this.mediaRecorder = null;
this.recordedChunks = [];
this.countdownInterval = null;
this.timeLeft = 60;
this.setupEventListeners();
feather.replace();
}
setupEventListeners() {
const recordBtn = this.shadowRoot.getElementById('recordBtn');
const stopBtn = this.shadowRoot.getElementById('stopBtn');
const videoPreview = this.shadowRoot.getElementById('videoPreview');
const videoPlaceholder = this.shadowRoot.getElementById('videoPlaceholder');
const timer = this.shadowRoot.getElementById('timer');
recordBtn.addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
videoPreview.srcObject = stream;
videoPlaceholder.style.display = 'none';
videoPreview.style.display = 'block';
this.mediaRecorder = new MediaRecorder(stream);
this.recordedChunks = [];
this.mediaRecorder.ondataavailable = event => {
if (event.data.size > 0) {
this.recordedChunks.push(event.data);
}
};
this.mediaRecorder.onstop = () => {
const blob = new Blob(this.recordedChunks, { type: 'video/webm' });
this.saveRecording(blob);
};
this.mediaRecorder.start(100);
recordBtn.classList.add('recording');
recordBtn.disabled = true;
stopBtn.disabled = false;
// Start countdown
this.timeLeft = 60;
this.countdownInterval = setInterval(() => {
this.timeLeft--;
const minutes = Math.floor(this.timeLeft / 60);
const seconds = this.timeLeft % 60;
timer.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
if (this.timeLeft <= 0) {
this.stopRecording();
}
}, 1000);
} catch (error) {
console.error('Error accessing media devices:', error);
alert('Could not access camera/microphone. Please check permissions.');
}
});
stopBtn.addEventListener('click', () => this.stopRecording());
}
stopRecording() {
if (this.countdownInterval) {
clearInterval(this.countdownInterval);
this.countdownInterval = null;
}
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
this.mediaRecorder.stop();
const videoPreview = this.shadowRoot.getElementById('videoPreview');
const stream = videoPreview.srcObject;
stream.getTracks().forEach(track => track.stop());
this.shadowRoot.getElementById('recordBtn').classList.remove('recording');
this.shadowRoot.getElementById('recordBtn').disabled = false;
this.shadowRoot.getElementById('stopBtn').disabled = true;
this.shadowRoot.getElementById('timer').textContent = '01:00';
}
}
async saveRecording(blob) {
// In a real app, this would upload to S3/CDN via your backend
console.log('Recording saved:', blob);
alert('Recording saved successfully! It will appear in your journal entries.');
// Simulate adding to entries list
const entriesContainer = document.getElementById('entriesContainer');
if (entriesContainer) {
const newEntry = {
id: Date.now().toString(),
date: new Date().toISOString().split('T')[0],
duration: '1:00',
thumbnail: 'http://static.photos/people/320x240/' + Math.floor(Math.random() * 10),
mood: 'New'
};
entriesContainer.insertAdjacentHTML('afterbegin', `
${newEntry.date}
${newEntry.mood}
`);
feather.replace();
}
}
}
customElements.define('self-talk-recorder', SelfTalkRecorder);