podfather / index.html
send2cloud's picture
Let’s build a podcast commenting page where a podcast plays on the top and users can comment. What do you think about it and it shows up as little tags or dots on the play bar make a prototype - Initial Deployment
af0033d verified
Raw
History Blame Contribute Delete
22.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Podcast with Interactive Comments</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.comment-marker {
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
transform: translateX(-50%);
cursor: pointer;
transition: all 0.2s ease;
}
.comment-marker:hover {
transform: translateX(-50%) scale(1.5);
}
.progress-bar-container {
position: relative;
height: 6px;
}
.progress-bar {
height: 100%;
background-color: #e5e7eb;
border-radius: 3px;
position: relative;
overflow: hidden;
}
.progress {
height: 100%;
background-color: #3b82f6;
width: 0%;
border-radius: 3px;
}
.comment-tooltip {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background-color: white;
padding: 8px 12px;
border-radius: 6px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
z-index: 10;
min-width: 200px;
display: none;
}
.comment-tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border-width: 8px;
border-style: solid;
border-color: white transparent transparent transparent;
}
.timestamp-btn {
background-color: #f3f4f6;
border-radius: 4px;
padding: 2px 6px;
font-size: 0.75rem;
cursor: pointer;
}
.comment-input {
transition: all 0.3s ease;
}
.comment-input:focus-within {
box-shadow: 0 0 0 2px #3b82f6;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Podcast Header -->
<div class="flex items-center mb-6">
<div class="w-24 h-24 rounded-lg overflow-hidden shadow-md mr-4">
<img src="https://images.unsplash.com/photo-1478737270239-2f02b77fc618?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" alt="Podcast Cover" class="w-full h-full object-cover">
</div>
<div>
<h1 class="text-2xl font-bold text-gray-800">The Future of AI in Everyday Life</h1>
<p class="text-gray-600">Tech Talk Podcast • Episode 42</p>
<div class="flex items-center mt-1">
<span class="text-sm text-gray-500 mr-3"><i class="fas fa-calendar-alt mr-1"></i> June 15, 2023</span>
<span class="text-sm text-gray-500"><i class="fas fa-clock mr-1"></i> 45 min</span>
</div>
</div>
</div>
<!-- Audio Player -->
<div class="bg-white rounded-xl shadow-md p-6 mb-8">
<div class="progress-bar-container mb-2">
<div class="progress-bar">
<div class="progress" id="progress"></div>
<!-- Comment markers will be added here dynamically -->
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<button id="playBtn" class="w-10 h-10 bg-blue-500 text-white rounded-full flex items-center justify-center mr-4 hover:bg-blue-600 transition">
<i class="fas fa-play"></i>
</button>
<span id="currentTime" class="text-gray-600">0:00</span>
</div>
<div class="flex items-center space-x-4">
<button class="text-gray-500 hover:text-blue-500 transition">
<i class="fas fa-step-backward"></i>
</button>
<button class="text-gray-500 hover:text-blue-500 transition">
<i class="fas fa-step-forward"></i>
</button>
<button class="text-gray-500 hover:text-blue-500 transition">
<i class="fas fa-volume-up"></i>
</button>
<div class="w-24">
<input type="range" min="0" max="100" value="80" class="w-full">
</div>
</div>
</div>
<audio id="audioPlayer" src="https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"></audio>
</div>
<!-- Comment Input -->
<div class="bg-white rounded-xl shadow-md p-6 mb-8 comment-input">
<h3 class="text-lg font-semibold text-gray-800 mb-4">Add your comment</h3>
<div class="flex items-start space-x-3">
<div class="w-10 h-10 rounded-full overflow-hidden bg-gray-200">
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="User" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<textarea id="commentText" class="w-full border border-gray-300 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent" rows="3" placeholder="What are your thoughts on this part of the podcast?"></textarea>
<div class="flex justify-between items-center mt-3">
<button id="addTimestampBtn" class="flex items-center text-sm text-blue-500 hover:text-blue-700">
<i class="fas fa-clock mr-1"></i> Add at current time
</button>
<button id="submitCommentBtn" class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 transition">Post Comment</button>
</div>
</div>
</div>
</div>
<!-- Comments Section -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex justify-between items-center mb-6">
<h3 class="text-lg font-semibold text-gray-800">Comments</h3>
<div class="flex items-center">
<span class="text-sm text-gray-500 mr-2">Sort by:</span>
<select class="border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500">
<option>Newest</option>
<option>Oldest</option>
<option>Timeline</option>
</select>
</div>
</div>
<div id="commentsContainer">
<!-- Sample comments -->
<div class="comment mb-6 pb-6 border-b border-gray-100" data-timestamp="45">
<div class="flex items-start space-x-3">
<div class="w-10 h-10 rounded-full overflow-hidden bg-gray-200">
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="User" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<div class="flex items-center justify-between mb-1">
<span class="font-semibold text-gray-800">Michael Johnson</span>
<button class="timestamp-btn flex items-center text-xs text-gray-500 hover:text-blue-500">
<i class="fas fa-clock mr-1"></i> 0:45
</button>
</div>
<p class="text-gray-700 mb-2">This point about AI in healthcare is fascinating. I work in the field and we're already seeing some of these applications in diagnostic imaging.</p>
<div class="flex items-center text-sm text-gray-500 space-x-4">
<button class="hover:text-blue-500"><i class="far fa-thumbs-up mr-1"></i> 12</button>
<button class="hover:text-blue-500"><i class="far fa-thumbs-down mr-1"></i> 2</button>
<button class="hover:text-blue-500"><i class="far fa-comment mr-1"></i> Reply</button>
<span>2 hours ago</span>
</div>
</div>
</div>
</div>
<div class="comment mb-6 pb-6 border-b border-gray-100" data-timestamp="210">
<div class="flex items-start space-x-3">
<div class="w-10 h-10 rounded-full overflow-hidden bg-gray-200">
<img src="https://randomuser.me/api/portraits/women/65.jpg" alt="User" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<div class="flex items-center justify-between mb-1">
<span class="font-semibold text-gray-800">Sarah Williams</span>
<button class="timestamp-btn flex items-center text-xs text-gray-500 hover:text-blue-500">
<i class="fas fa-clock mr-1"></i> 3:30
</button>
</div>
<p class="text-gray-700 mb-2">I disagree with the host's perspective on AI taking creative jobs. Tools are just tools - they enhance human creativity rather than replace it.</p>
<div class="flex items-center text-sm text-gray-500 space-x-4">
<button class="hover:text-blue-500"><i class="far fa-thumbs-up mr-1"></i> 8</button>
<button class="hover:text-blue-500"><i class="far fa-thumbs-down mr-1"></i> 0</button>
<button class="hover:text-blue-500"><i class="far fa-comment mr-1"></i> Reply</button>
<span>5 hours ago</span>
</div>
</div>
</div>
</div>
<div class="comment mb-6" data-timestamp="540">
<div class="flex items-start space-x-3">
<div class="w-10 h-10 rounded-full overflow-hidden bg-gray-200">
<img src="https://randomuser.me/api/portraits/men/75.jpg" alt="User" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<div class="flex items-center justify-between mb-1">
<span class="font-semibold text-gray-800">David Chen</span>
<button class="timestamp-btn flex items-center text-xs text-gray-500 hover:text-blue-500">
<i class="fas fa-clock mr-1"></i> 9:00
</button>
</div>
<p class="text-gray-700 mb-2">The ethical considerations mentioned here are crucial. We need more public discourse on how AI systems make decisions that affect people's lives.</p>
<div class="flex items-center text-sm text-gray-500 space-x-4">
<button class="hover:text-blue-500"><i class="far fa-thumbs-up mr-1"></i> 15</button>
<button class="hover:text-blue-500"><i class="far fa-thumbs-down mr-1"></i> 1</button>
<button class="hover:text-blue-500"><i class="far fa-comment mr-1"></i> Reply</button>
<span>1 day ago</span>
</div>
</div>
</div>
</div>
</div>
<button class="w-full py-3 text-center text-blue-500 font-medium hover:bg-gray-50 rounded-lg mt-4">
Load more comments
</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const audioPlayer = document.getElementById('audioPlayer');
const playBtn = document.getElementById('playBtn');
const progress = document.getElementById('progress');
const currentTime = document.getElementById('currentTime');
const commentText = document.getElementById('commentText');
const addTimestampBtn = document.getElementById('addTimestampBtn');
const submitCommentBtn = document.getElementById('submitCommentBtn');
const commentsContainer = document.getElementById('commentsContainer');
const progressBar = document.querySelector('.progress-bar');
let isPlaying = false;
let currentTimestamp = 0;
let comments = [];
// Initialize with sample comments
document.querySelectorAll('.comment').forEach(comment => {
const timestamp = parseInt(comment.dataset.timestamp);
comments.push({timestamp});
addCommentMarker(timestamp);
});
// Play/Pause functionality
playBtn.addEventListener('click', function() {
if (isPlaying) {
audioPlayer.pause();
playBtn.innerHTML = '<i class="fas fa-play"></i>';
} else {
audioPlayer.play();
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
}
isPlaying = !isPlaying;
});
// Update progress bar
audioPlayer.addEventListener('timeupdate', function() {
const duration = audioPlayer.duration;
const currentTimeValue = audioPlayer.currentTime;
const progressPercent = (currentTimeValue / duration) * 100;
progress.style.width = `${progressPercent}%`;
// Update current time display
currentTimestamp = Math.floor(currentTimeValue);
currentTime.textContent = formatTime(currentTimeValue);
});
// Click on progress bar to seek
progressBar.addEventListener('click', function(e) {
const width = this.clientWidth;
const clickX = e.offsetX;
const duration = audioPlayer.duration;
audioPlayer.currentTime = (clickX / width) * duration;
});
// Add timestamp button
addTimestampBtn.addEventListener('click', function() {
if (audioPlayer.duration) {
const timestamp = Math.floor(audioPlayer.currentTime);
commentText.value = `${commentText.value} [${formatTime(timestamp)}]`;
}
});
// Submit comment
submitCommentBtn.addEventListener('click', function() {
if (commentText.value.trim() === '') return;
const comment = {
text: commentText.value,
timestamp: currentTimestamp,
user: {
name: "You",
avatar: "https://randomuser.me/api/portraits/women/44.jpg"
},
likes: 0,
dislikes: 0,
timeAgo: "Just now"
};
addComment(comment);
commentText.value = '';
});
// Format time from seconds to MM:SS
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
}
// Add comment to the DOM
function addComment(comment) {
comments.push({timestamp: comment.timestamp});
addCommentMarker(comment.timestamp);
const commentElement = document.createElement('div');
commentElement.className = 'comment mb-6 pb-6 border-b border-gray-100';
commentElement.dataset.timestamp = comment.timestamp;
commentElement.innerHTML = `
<div class="flex items-start space-x-3">
<div class="w-10 h-10 rounded-full overflow-hidden bg-gray-200">
<img src="${comment.user.avatar}" alt="User" class="w-full h-full object-cover">
</div>
<div class="flex-1">
<div class="flex items-center justify-between mb-1">
<span class="font-semibold text-gray-800">${comment.user.name}</span>
<button class="timestamp-btn flex items-center text-xs text-gray-500 hover:text-blue-500">
<i class="fas fa-clock mr-1"></i> ${formatTime(comment.timestamp)}
</button>
</div>
<p class="text-gray-700 mb-2">${comment.text}</p>
<div class="flex items-center text-sm text-gray-500 space-x-4">
<button class="hover:text-blue-500"><i class="far fa-thumbs-up mr-1"></i> ${comment.likes}</button>
<button class="hover:text-blue-500"><i class="far fa-thumbs-down mr-1"></i> ${comment.dislikes}</button>
<button class="hover:text-blue-500"><i class="far fa-comment mr-1"></i> Reply</button>
<span>${comment.timeAgo}</span>
</div>
</div>
</div>
`;
commentsContainer.prepend(commentElement);
// Add click handler to timestamp button
const timestampBtn = commentElement.querySelector('.timestamp-btn');
timestampBtn.addEventListener('click', function() {
audioPlayer.currentTime = comment.timestamp;
if (!isPlaying) {
audioPlayer.play();
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
isPlaying = true;
}
});
}
// Add comment marker to progress bar
function addCommentMarker(timestamp) {
const marker = document.createElement('div');
marker.className = 'comment-marker bg-blue-500';
marker.dataset.timestamp = timestamp;
// Position marker based on timestamp
const duration = audioPlayer.duration || 540; // Fallback to 9 minutes if duration not loaded
const positionPercent = (timestamp / duration) * 100;
marker.style.left = `${positionPercent}%`;
// Add tooltip
const tooltip = document.createElement('div');
tooltip.className = 'comment-tooltip';
tooltip.textContent = `${formatTime(timestamp)} - ${comments.filter(c => c.timestamp === timestamp).length} comment(s)`;
marker.appendChild(tooltip);
// Show tooltip on hover
marker.addEventListener('mouseenter', function() {
tooltip.style.display = 'block';
});
marker.addEventListener('mouseleave', function() {
tooltip.style.display = 'none';
});
// Seek to timestamp when clicked
marker.addEventListener('click', function() {
audioPlayer.currentTime = timestamp;
if (!isPlaying) {
audioPlayer.play();
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
isPlaying = true;
}
});
progressBar.appendChild(marker);
}
// Add click handlers to existing timestamp buttons
document.querySelectorAll('.timestamp-btn').forEach(btn => {
btn.addEventListener('click', function() {
const comment = this.closest('.comment');
const timestamp = parseInt(comment.dataset.timestamp);
audioPlayer.currentTime = timestamp;
if (!isPlaying) {
audioPlayer.play();
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
isPlaying = true;
}
});
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=send2cloud/podfather" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>