Update templates/index.html
Browse files- templates/index.html +40 -42
templates/index.html
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
-
|
|
|
|
|
2 |
<html lang="en">
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
@@ -29,7 +31,7 @@
|
|
29 |
<input type="text" id="youtubeUrl"
|
30 |
placeholder="Paste YouTube URL here"
|
31 |
class="w-full pl-12 pr-4 py-4 bg-gray-50 dark:bg-gray-900/50 border-0 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-all duration-300 text-gray-700 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500">
|
32 |
-
<div class="absolute inset-y-0 left-4
|
33 |
<i class="fas fa-link text-gray-400 group-focus-within:text-blue-500 transition-colors"></i>
|
34 |
</div>
|
35 |
</div>
|
@@ -52,23 +54,23 @@
|
|
52 |
|
53 |
<!-- Video Details -->
|
54 |
<div class="p-6 space-y-4">
|
55 |
-
<h2 id="
|
56 |
|
57 |
<div class="space-y-2">
|
58 |
-
<div id="
|
59 |
-
<
|
60 |
<span></span>
|
61 |
</div>
|
62 |
-
<div id="
|
63 |
-
<
|
64 |
<span></span>
|
65 |
</div>
|
66 |
</div>
|
67 |
|
68 |
<!-- Play Audio Button -->
|
69 |
<button onclick="playAudio()"
|
70 |
-
class="w-full bg-green-500 hover:bg-green-600 active:bg-green-700 text-white py-4 px-6 rounded-xl transition-all duration-300 flex items-center justify-center space-x-2 font-medium focus:outline-none focus:ring-2 focus:ring-green-500/50 focus:
|
71 |
-
<
|
72 |
<span>Start Listening</span>
|
73 |
</button>
|
74 |
</div>
|
@@ -82,7 +84,7 @@
|
|
82 |
position: 'top-end',
|
83 |
showConfirmButton: false,
|
84 |
timer: 3000,
|
85 |
-
|
86 |
didOpen: (toast) => {
|
87 |
toast.addEventListener('mouseenter', Swal.stopTimer)
|
88 |
toast.addEventListener('mouseleave', Swal.resumeTimer)
|
@@ -93,7 +95,7 @@
|
|
93 |
return Swal.fire({
|
94 |
html: `
|
95 |
<div class="space-y-3">
|
96 |
-
<
|
97 |
<div class="text-gray-600 text-sm">${message}</div>
|
98 |
</div>
|
99 |
`,
|
@@ -115,7 +117,7 @@
|
|
115 |
});
|
116 |
}
|
117 |
|
118 |
-
|
119 |
Toast.fire({
|
120 |
icon: 'error',
|
121 |
title: message,
|
@@ -124,14 +126,14 @@
|
|
124 |
});
|
125 |
}
|
126 |
|
127 |
-
function
|
128 |
const minutes = Math.floor(seconds / 60);
|
129 |
-
const
|
130 |
-
return`${minutes}:${
|
131 |
}
|
132 |
|
133 |
function getVideoInfo() {
|
134 |
-
const
|
135 |
if (!url) {
|
136 |
showError('Please enter a YouTube URL');
|
137 |
return;
|
@@ -164,8 +166,6 @@
|
|
164 |
});
|
165 |
}
|
166 |
|
167 |
-
let currentAudioPlayer = null;
|
168 |
-
|
169 |
function playAudio() {
|
170 |
const url = $('#youtubeUrl').val().trim();
|
171 |
if (!url) {
|
@@ -178,7 +178,7 @@
|
|
178 |
$.ajax({
|
179 |
url: '/download',
|
180 |
type: 'POST',
|
181 |
-
contentType: '
|
182 |
data: JSON.stringify({ url: url }),
|
183 |
xhrFields: {
|
184 |
responseType: 'blob'
|
@@ -187,28 +187,26 @@
|
|
187 |
const blob = new Blob([response], { type: 'audio/mp3' });
|
188 |
const audioUrl = URL.createObjectURL(blob);
|
189 |
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
currentAudioPlayer = audioPlayer;
|
211 |
-
}
|
212 |
|
213 |
Swal.close();
|
214 |
showSuccess('Audio is ready to play');
|
@@ -224,7 +222,7 @@
|
|
224 |
document.addEventListener('DOMContentLoaded', () => {
|
225 |
requestAnimationFrame(() => {
|
226 |
document.body.style.opacity = '0';
|
227 |
-
|
228 |
document.body.style.transition = 'opacity 0.5s ease-in';
|
229 |
document.body.style.opacity = '1';
|
230 |
});
|
|
|
1 |
+
}
|
2 |
+
|
3 |
+
<!DOCTYPE html>
|
4 |
<html lang="en">
|
5 |
<head>
|
6 |
<meta charset="UTF-8">
|
|
|
31 |
<input type="text" id="youtubeUrl"
|
32 |
placeholder="Paste YouTube URL here"
|
33 |
class="w-full pl-12 pr-4 py-4 bg-gray-50 dark:bg-gray-900/50 border-0 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500/50 transition-all duration-300 text-gray-700 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500">
|
34 |
+
<div class="absolute inset-y-0 left-4 flex items-center pointer-events-none transition-transform group-focus-within:scale-110">
|
35 |
<i class="fas fa-link text-gray-400 group-focus-within:text-blue-500 transition-colors"></i>
|
36 |
</div>
|
37 |
</div>
|
|
|
54 |
|
55 |
<!-- Video Details -->
|
56 |
<div class="p-6 space-y-4">
|
57 |
+
<h2 id="videoTitle" class="text-xl font-semibold text-gray-800 dark:text-white line-clamp-2"></h2>
|
58 |
|
59 |
<div class="space-y-2">
|
60 |
+
<div id="channelName" class="flex items-center text-sm text-gray-500 dark:text-gray-400">
|
61 |
+
<i class="fas fa-user-circle mr-2 text-blue-500"></i>
|
62 |
<span></span>
|
63 |
</div>
|
64 |
+
<div id="duration" class="flex items-center text-sm text-gray-500 dark:text-gray-400">
|
65 |
+
<i class="fas fa-clock mr-2 text-blue-500"></i>
|
66 |
<span></span>
|
67 |
</div>
|
68 |
</div>
|
69 |
|
70 |
<!-- Play Audio Button -->
|
71 |
<button onclick="playAudio()"
|
72 |
+
class="w-full bg-green-500 hover:bg-green-600 active:bg-green-700 text-white py-4 px-6 rounded-xl transition-all duration-300 flex items-center justify-center space-x-2 font-medium focus:outline-none focus:ring-2 focus:ring-green-500/50 focus:ring-offset-2 dark:ring-offset-gray-800 mt-4">
|
73 |
+
<i class="fas fa-play text-sm"></i>
|
74 |
<span>Start Listening</span>
|
75 |
</button>
|
76 |
</div>
|
|
|
84 |
position: 'top-end',
|
85 |
showConfirmButton: false,
|
86 |
timer: 3000,
|
87 |
+
timerProgressBar: true,
|
88 |
didOpen: (toast) => {
|
89 |
toast.addEventListener('mouseenter', Swal.stopTimer)
|
90 |
toast.addEventListener('mouseleave', Swal.resumeTimer)
|
|
|
95 |
return Swal.fire({
|
96 |
html: `
|
97 |
<div class="space-y-3">
|
98 |
+
<div class="w-16 h-16 mx-auto border-4 border-gray-200 border-t-blue-500 rounded-full animate-spin"></div>
|
99 |
<div class="text-gray-600 text-sm">${message}</div>
|
100 |
</div>
|
101 |
`,
|
|
|
117 |
});
|
118 |
}
|
119 |
|
120 |
+
function showError(message) {
|
121 |
Toast.fire({
|
122 |
icon: 'error',
|
123 |
title: message,
|
|
|
126 |
});
|
127 |
}
|
128 |
|
129 |
+
function formatDuration(seconds) {
|
130 |
const minutes = Math.floor(seconds / 60);
|
131 |
+
const remainingSeconds = seconds % 60;
|
132 |
+
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
|
133 |
}
|
134 |
|
135 |
function getVideoInfo() {
|
136 |
+
const url = $('#youtubeUrl').val().trim();
|
137 |
if (!url) {
|
138 |
showError('Please enter a YouTube URL');
|
139 |
return;
|
|
|
166 |
});
|
167 |
}
|
168 |
|
|
|
|
|
169 |
function playAudio() {
|
170 |
const url = $('#youtubeUrl').val().trim();
|
171 |
if (!url) {
|
|
|
178 |
$.ajax({
|
179 |
url: '/download',
|
180 |
type: 'POST',
|
181 |
+
contentType: 'application/json',
|
182 |
data: JSON.stringify({ url: url }),
|
183 |
xhrFields: {
|
184 |
responseType: 'blob'
|
|
|
187 |
const blob = new Blob([response], { type: 'audio/mp3' });
|
188 |
const audioUrl = URL.createObjectURL(blob);
|
189 |
|
190 |
+
const videoInfoContainer = document.querySelector('#videoInfo .p-6');
|
191 |
+
// Remove any existing audio players
|
192 |
+
const existingAudioPlayers = videoInfoContainer.querySelectorAll('audio');
|
193 |
+
existingAudioPlayers.forEach(player => player.remove());
|
194 |
+
|
195 |
+
const audioPlayer = document.createElement('audio');
|
196 |
+
audioPlayer.src = audioUrl;
|
197 |
+
audioPlayer.controls = true;
|
198 |
+
audioPlayer.style.width = '100%';
|
199 |
+
audioPlayer.style.marginTop = '1rem';
|
200 |
+
audioPlayer.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
|
201 |
+
audioPlayer.style.borderRadius = '8px';
|
202 |
+
audioPlayer.style.padding = '1rem';
|
203 |
+
audioPlayer.style.color = 'white';
|
204 |
+
audioPlayer.style.border = '1px solid rgba(255, 255, 255, 0.2)';
|
205 |
+
|
206 |
+
// Autoplay
|
207 |
+
audioPlayer.autoplay = true;
|
208 |
+
|
209 |
+
videoInfoContainer.appendChild(audioPlayer);
|
|
|
|
|
210 |
|
211 |
Swal.close();
|
212 |
showSuccess('Audio is ready to play');
|
|
|
222 |
document.addEventListener('DOMContentLoaded', () => {
|
223 |
requestAnimationFrame(() => {
|
224 |
document.body.style.opacity = '0';
|
225 |
+
requestAnimationFrame(() => {
|
226 |
document.body.style.transition = 'opacity 0.5s ease-in';
|
227 |
document.body.style.opacity = '1';
|
228 |
});
|