Team Meeting Recorder & Transcriber

Team Meeting Recorder & Transcriber

Capture, transcribe, and archive your important team discussions.

Requesting microphone permissions...

Status: Idle

00:00:00

No meetings have been archived yet.

`; return; } meetingList.innerHTML = meetings.map(meeting => { const meetingDate = meeting.timestamp ? meeting.timestamp.toDate().toLocaleString() : 'N/A'; const duration = new Date(meeting.durationSeconds * 1000).toISOString().substr(11, 8); return `

${meeting.title}

By ${meeting.authorName} on ${meetingDate}

Duration: ${duration}

${meeting.transcript}

`; }).join(''); } // --- PROFILE & SETTINGS LOGIC --- async function loadUserProfile() { if (!userId) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-recorder-app'; const userProfileRef = doc(db, `/artifacts/${appId}/users/${userId}/profile/data`); try { const docSnap = await getDoc(userProfileRef); if (docSnap.exists()) userDisplayName = docSnap.data().displayName || 'Anonymous'; } catch (error) { console.error("Error loading profile:", error); } displayNameInput.value = userDisplayName; } async function saveUserProfile() { if (!userId) return; const newName = displayNameInput.value.trim(); if (newName === '') return; userDisplayName = newName; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-recorder-app'; const userProfileRef = doc(db, `/artifacts/${appId}/users/${userId}/profile/data`); try { await setDoc(userProfileRef, { displayName: newName }, { merge: true }); settingsFeedback.textContent = "Profile saved!"; setTimeout(() => settingsFeedback.textContent = "", 2000); } catch (error) { console.error("Error saving profile:", error); settingsFeedback.textContent = "Error saving profile."; } } // --- PDF GENERATION --- async function generatePdf(meetingId) { const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-recorder-app'; const meetingRef = doc(db, `/artifacts/${appId}/public/data/meetings`, meetingId); const meetingSnap = await getDoc(meetingRef); if (!meetingSnap.exists()) { console.error("Meeting not found for PDF generation"); return; } const meeting = meetingSnap.data(); const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'portrait', unit: 'pt', format: 'a4' }); doc.setFont("helvetica", "bold"); doc.setFontSize(20); doc.text(meeting.title, 40, 60); doc.setFontSize(10); doc.setTextColor(100); const meetingDate = meeting.timestamp ? meeting.timestamp.toDate().toLocaleString() : 'N/A'; doc.text(`Recorded by: ${meeting.authorName} on ${meetingDate}`, 40, 80); doc.setFont("helvetica", "normal"); doc.setFontSize(12); const splitTranscript = doc.splitTextToSize(meeting.transcript, 515); // 595 (width) - 40*2 (margins) doc.text(splitTranscript, 40, 120); doc.save(`Transcript-${meeting.title.replace(/\s+/g, '_')}.pdf`); } // --- TAB NAVIGATION LOGIC --- function switchTab(tabIndex) { currentTabIndex = tabIndex; tabsContainer.querySelectorAll('button').forEach((btn, index) => { btn.classList.toggle('tab-active', index === tabIndex); btn.classList.toggle('tab-inactive', index !== tabIndex); }); tabContents.forEach((content, index) => { content.classList.toggle('hidden', index !== tabIndex); }); updateButtonStates(); } function updateButtonStates() { prevBtn.disabled = currentTabIndex === 0; nextBtn.disabled = currentTabIndex === tabs.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); } // --- EVENT LISTENERS --- tabsContainer.querySelectorAll('button').forEach((btn, index) => { btn.addEventListener('click', () => switchTab(index)); }); prevBtn.addEventListener('click', () => { if (currentTabIndex > 0) switchTab(currentTabIndex - 1); }); nextBtn.addEventListener('click', () => { if (currentTabIndex < tabs.length - 1) switchTab(currentTabIndex + 1); }); recordBtn.addEventListener('click', toggleRecording); saveMeetingBtn.addEventListener('click', saveMeeting); saveSettingsBtn.addEventListener('click', saveUserProfile); meetingList.addEventListener('click', (e) => { if (e.target.classList.contains('download-transcript-btn')) { const meetingId = e.target.dataset.id; generatePdf(meetingId); } }); // --- RUN INITIALIZATION --- initializeFirebase(); setupMedia(); updateButtonStates(); });
Scroll to Top