Taf2023's picture
Upload 8 files
c0a4ca6 verified
Raw History Blame Contribute Delete
13.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Professional media downloader with yt-dlp. Download from 1000+ platforms with advanced format selection and progress tracking.">
<title>Universal Media Downloader</title>
<link rel="stylesheet" href="style.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- PWA Meta Tags -->
<meta name="theme-color" content="#06B6D4">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="Media Downloader">
<!-- Service Worker -->
<link rel="manifest" href="/manifest.json">
</head>
<body>
<div class="app-container">
<!-- Header -->
<header class="app-header">
<div class="header-content">
<h1 class="app-title">Downloader</h1>
<div class="header-controls">
<button id="settings-btn" class="icon-btn" aria-label="Settings">
<svg viewBox="0 0 24 24" class="icon">
<path d="M12,8A4,4 0 0,0 8,12A4,4 0 0,0 12,16A4,4 0 0,0 16,12A4,4 0 0,0 12,8M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z"/>
</svg>
</button>
<button id="update-btn" class="icon-btn" aria-label="Check for updates" title="Update yt-dlp">
<svg viewBox="0 0 24 24" class="icon">
<path d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,6H13V11.59L17.59,16.59L16.17,18L11,12.83V6M12,4A1,1 0 0,1 13,5A1,1 0 0,1 12,6A1,1 0 0,1 11,5A1,1 0 0,1 12,4M7,12A1,1 0 0,1 8,11A1,1 0 0,1 7,10A1,1 0 0,1 6,11A1,1 0 0,1 7,12M17,12A1,1 0 0,1 16,11A1,1 0 0,1 17,10A1,1 0 0,1 18,11A1,1 0 0,1 17,12Z"/>
</svg>
</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="app-main">
<!-- URL Input Section -->
<section class="input-section">
<form id="download-form" class="url-form" aria-describedby="form-help">
<div class="input-group">
<label for="url-input" class="input-label">Media URL</label>
<div class="url-input-container">
<input
type="url"
id="url-input"
name="url"
placeholder="https://www.youtube.com/watch?v=..."
required
aria-describedby="form-help"
autocomplete="url"
inputmode="url"
class="url-input"
>
<button type="submit" id="analyze-btn" class="analyze-btn" aria-label="Analyze URL and show available formats">
<span class="btn-text">Analyze</span>
<span class="btn-loading" aria-hidden="true">
<svg class="spinner" viewBox="0 0 24 24">
<circle class="path" cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round"/>
</svg>
</span>
</button>
</div>
</div>
<p id="form-help" class="help-text">Enter a video, audio, or playlist URL from supported platforms</p>
</form>
</section>
<!-- Status and Progress -->
<section class="status-section" aria-labelledby="status-title">
<h2 id="status-title" class="section-title">Status</h2>
<div id="status-container" class="status-container" aria-live="assertive" role="status">
<div class="status-item">
<span class="status-icon">ℹ️</span>
<span class="status-text">Ready to analyze URLs. Enter a link to begin.</span>
</div>
</div>
<div id="progress-section" class="progress-section" style="display: none;">
<div class="progress-header">
<span id="progress-title" class="progress-title">Downloading...</span>
<span id="progress-speed" class="progress-speed"></span>
</div>
<div class="progress-bar-container">
<progress id="progress-bar" value="0" max="100" class="progress-bar"></progress>
<span id="progress-percentage" class="progress-percentage">0%</span>
</div>
</div>
</section>
<!-- Media Info Section -->
<section id="media-info-section" class="media-info-section" style="display: none;">
<h2 class="section-title">Media Information</h2>
<div id="media-info" class="media-info">
<div class="media-thumbnail">
<img id="media-thumb" alt="" style="display: none;">
<div id="thumb-placeholder" class="thumb-placeholder">
<svg class="placeholder-icon" viewBox="0 0 24 24">
<path d="M8.5,13.5L11,16.51L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z"/>
</svg>
</div>
</div>
<div class="media-details">
<h3 id="media-title" class="media-title"></h3>
<div class="media-meta">
<span id="media-uploader" class="media-uploader"></span>
<span id="media-platform" class="platform-badge"></span>
<span id="media-duration" class="duration"></span>
</div>
<div class="media-stats">
<span id="media-views" class="stat-item"></span>
<span id="media-likes" class="stat-item"></span>
</div>
</div>
</div>
</section>
<!-- Download Options -->
<section id="formats-section" class="formats-section" style="display: none;">
<div class="section-header">
<h2 class="section-title">Available Formats</h2>
<div class="format-filters">
<button class="filter-btn active" data-filter="all" aria-label="Show all formats">All</button>
<button class="filter-btn" data-filter="video" aria-label="Show video formats only">Video</button>
<button class="filter-btn" data-filter="audio" aria-label="Show audio formats only">Audio</button>
</div>
</div>
<div id="format-list" class="format-list" role="list" aria-label="Available download formats">
<!-- Format options will be populated here -->
</div>
</section>
<!-- Download Queue -->
<section class="queue-section">
<div class="section-header">
<h2 class="section-title">Download Queue</h2>
<button id="clear-queue-btn" class="secondary-btn" aria-label="Clear all queued downloads">Clear All</button>
</div>
<div id="queue-list" class="queue-list" role="list" aria-label="Active downloads">
<!-- Active downloads will appear here -->
</div>
</section>
<!-- Error Section -->
<section id="error-section" class="error-section" style="display: none;">
<h2 class="section-title">Error</h2>
<div id="error-messages" class="error-container" role="alert" aria-live="assertive">
<!-- Error messages -->
</div>
</section>
<!-- Success Section -->
<section id="success-section" class="success-section" style="display: none;">
<h2 class="section-title">Success</h2>
<div id="success-messages" class="success-container" role="status" aria-live="polite">
<!-- Success messages -->
</div>
</section>
</main>
<!-- Bottom Navigation (Mobile) -->
<nav class="bottom-nav" role="navigation" aria-label="Main navigation">
<button class="nav-item active" data-tab="download" aria-label="Download section">
<svg class="nav-icon" viewBox="0 0 24 24">
<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z"/>
</svg>
<span class="nav-label">Download</span>
</button>
<button class="nav-item" data-tab="history" aria-label="Download history">
<svg class="nav-icon" viewBox="0 0 24 24">
<path d="M13.5,8H12V13L16.28,15.54L17,14.33L13.5,12.25V8M13,3A9,9 0 0,0 4,12H1L4.96,16.03L9,12H6A7,7 0 0,1 13,5A7,7 0 0,1 20,12A7,7 0 0,1 13,19C11.07,19 9.32,18.21 8.06,16.94L6.64,18.36C8.27,20 10.5,21 13,21A9,9 0 0,0 22,12A9,9 0 0,0 13,3"/>
</svg>
<span class="nav-label">History</span>
</button>
<button class="nav-item" data-tab="settings" aria-label="Settings">
<svg class="nav-icon" viewBox="0 0 24 24">
<path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.68 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"/>
</svg>
<span class="nav-label">Settings</span>
</button>
</nav>
</div>
<!-- Settings Modal -->
<div id="settings-modal" class="modal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3>Settings</h3>
<button class="modal-close" aria-label="Close settings">&times;</button>
</div>
<div class="modal-body">
<div class="setting-group">
<label class="setting-label">Auto-update yt-dlp</label>
<label class="toggle">
<input type="checkbox" id="auto-update" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-group">
<label class="setting-label">Privacy mode</label>
<label class="toggle">
<input type="checkbox" id="privacy-mode">
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-group">
<label class="setting-label">Default download quality</label>
<select id="default-quality" class="setting-select">
<option value="best">Best available</option>
<option value="1080p">1080p</option>
<option value="720p">720p</option>
<option value="480p">480p</option>
<option value="360p">360p</option>
</select>
</div>
</div>
<div class="modal-footer">
<button class="primary-btn" id="save-settings">Save Settings</button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>