158 lines
5.7 KiB
HTML
158 lines
5.7 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>KV Download</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<meta name="theme-color" content="#000000">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css">
|
|
<link rel="stylesheet" href="/static/css/style.css">
|
|
</head>
|
|
<body>
|
|
<div class="app-container">
|
|
<div class="hero-content">
|
|
<h1 class="app-title">
|
|
<i class="bi bi-cloud-arrow-down"></i>
|
|
KV Download
|
|
</h1>
|
|
<p class="app-subtitle">Download videos from social media platforms</p>
|
|
|
|
<form action="/fetch" method="GET" class="url-form" id="downloadForm">
|
|
<div class="glass-card">
|
|
<div class="glass-input">
|
|
<div class="input-icon">
|
|
<i class="bi bi-link-45deg"></i>
|
|
</div>
|
|
<input name="url" type="url" class="url-input"
|
|
placeholder="Paste video URL here..." required
|
|
value="{{.url}}" autofocus id="urlInput">
|
|
<button class="btn-download" type="submit" id="submitBtn">
|
|
<i class="bi bi-download"></i>
|
|
<span class="btn-text">Download</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="platforms-wrapper">
|
|
<span class="platform-badge"><i class="bi bi-youtube"></i> YouTube</span>
|
|
<span class="platform-badge"><i class="bi bi-tiktok"></i> TikTok</span>
|
|
<span class="platform-badge"><i class="bi bi-instagram"></i> Instagram</span>
|
|
<span class="platform-badge"><i class="bi bi-twitter-x"></i> Twitter/X</span>
|
|
<span class="platform-badge"><i class="bi bi-vimeo"></i> Vimeo</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="loading-overlay d-none" id="loadingOverlay">
|
|
<div class="loading-card">
|
|
<div class="loading-icon"></div>
|
|
<h3 class="loading-title"><i class="bi bi-cloud-arrow-down"></i> Downloading</h3>
|
|
<p class="loading-text">Please wait while we fetch your video</p>
|
|
<div class="loading-timer">
|
|
<i class="bi bi-clock"></i>
|
|
<span id="timer">0:00</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{ if .media }}
|
|
<div class="results-section">
|
|
<div class="section-header">
|
|
<i class="bi bi-check-circle-fill"></i>
|
|
<h2>Download Complete</h2>
|
|
</div>
|
|
<div class="media-grid">
|
|
{{range .media}}
|
|
<div class="media-card">
|
|
<div class="media-preview">
|
|
<video controls loop class="media-video">
|
|
<source src="/download?id={{.Id}}" type="video/mp4">
|
|
</video>
|
|
</div>
|
|
<div class="media-info">
|
|
<h5 class="media-name"><i class="bi bi-film"></i> {{.Name}}</h5>
|
|
<div class="media-meta">
|
|
<span class="media-size"><i class="bi bi-hdd"></i> {{.HumanSize}}</span>
|
|
<a href="/download?id={{.Id}}" class="btn-save">
|
|
<i class="bi bi-download"></i> Save
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
|
|
{{ if .error }}
|
|
<div class="error-container">
|
|
<div class="error-card">
|
|
<i class="bi bi-exclamation-triangle-fill"></i>
|
|
<h4>Download Failed</h4>
|
|
<pre>{{ .error }}</pre>
|
|
</div>
|
|
</div>
|
|
{{ end }}
|
|
|
|
<footer class="app-footer">
|
|
<p>Powered by <a href="https://github.com/yt-dlp/yt-dlp" target="_blank">yt-dlp</a> {{ $.ytDlpVersion }}</p>
|
|
</footer>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
(function() {
|
|
var timerInterval = null;
|
|
var startTime = null;
|
|
|
|
function formatTime(seconds) {
|
|
var mins = Math.floor(seconds / 60);
|
|
var secs = seconds % 60;
|
|
return mins + ':' + (secs < 10 ? '0' : '') + secs;
|
|
}
|
|
|
|
function startTimer() {
|
|
startTime = Date.now();
|
|
var timerEl = document.getElementById('timer');
|
|
if (timerEl) {
|
|
timerEl.textContent = '0:00';
|
|
}
|
|
timerInterval = setInterval(function() {
|
|
var elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
if (timerEl) {
|
|
timerEl.textContent = formatTime(elapsed);
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
function stopTimer() {
|
|
if (timerInterval) {
|
|
clearInterval(timerInterval);
|
|
timerInterval = null;
|
|
}
|
|
}
|
|
|
|
var form = document.getElementById('downloadForm');
|
|
if (form) {
|
|
form.addEventListener('submit', function() {
|
|
var btn = document.getElementById('submitBtn');
|
|
var btnText = btn ? btn.querySelector('.btn-text') : null;
|
|
var overlay = document.getElementById('loadingOverlay');
|
|
|
|
if (btn) btn.disabled = true;
|
|
if (btnText) btnText.textContent = 'Downloading...';
|
|
if (overlay) overlay.classList.remove('d-none');
|
|
|
|
startTimer();
|
|
});
|
|
}
|
|
|
|
window.addEventListener('beforeunload', function() {
|
|
stopTimer();
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|