mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-11 17:30:00 +02:00
Security: - Replace unsalted SHA-256 password hashing with bcrypt (lazy rehash on login) - Add authenticated /api/xtream-api gateway: Xtream credentials are injected server-side and never sent to the frontend; /api/playlists no longer returns passwords - Redact credentials from all logs (login body, proxy/FFmpeg/scheduler URLs) - Add auth to recordings, EPG, season-passes and streaming routes (HttpOnly session cookie for hls.js; loopback bypass for local FFmpeg) - Lock player postMessage to same-origin in both directions - Vendor and pin hls.js 1.6.7 / mpegts.js 1.7.3 (drop CDN @latest) - Fix rate limiter (client IP was never resolved), add login rate limit, restrict CORS, add CSP Report-Only, block private-IP SSRF targets, fix path traversal in recording log retrieval, chmod 777 -> 770 - Remove dead HiveService (seeded admin/admin into IndexedDB with SHA-256) - Fix authMiddleware not populating 'user' context (getPlaylist ignored the logged-in user; admin purge always returned 403) Streaming: - New FfmpegSessionManager: process registry, idle reaper (4 min live / 15 min VOD), orphan cleanup at startup, clean SIGTERM shutdown, fast-fail with stderr instead of 30 s timeout - Quality selection (source/high/medium/low) for live and VOD; source mode streams with -c:v copy (zero transcoding); selector wired into the player - Concurrent recordings (MAX_CONCURRENT_RECORDINGS, default 2); conflicts retry on the next tick instead of silently failing - Lower live latency (HLS window 20 -> 10 segments, liveSync 10 -> 3) - Fix recording log lookup (.mp4 vs .mkv mismatch) Design: - Replace hardcoded colors with AppColors tokens (12 files) - web/theme.css syncs HTML players with the Flutter palette - DPAD/keyboard navigation (arrow-key focus, player shortcuts) - Tooltips on player icon buttons, Semantics on content cards - Remove 7 dead widgets broken since the Stitch merge Quality: - bin/test/: 21 unit tests (bcrypt, redaction, traversal, SSRF, recording conflicts) plus a quality-selector widget test - GitHub Actions CI (analyze + test + build web) - Archive stale status docs into docs/archive/ Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
258 lines
15 KiB
HTML
258 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html class="dark" lang="en"><head>
|
|
<meta charset="utf-8"/>
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
|
<title>Live TV Categories - AuraStream</title>
|
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet"/>
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
|
<script id="tailwind-config">
|
|
tailwind.config = {
|
|
darkMode: "class",
|
|
theme: {
|
|
extend: {
|
|
"colors": {
|
|
"tertiary-fixed": "#e2e2e2",
|
|
"inverse-surface": "#e3e2e7",
|
|
"on-secondary-fixed-variant": "#46464e",
|
|
"on-secondary": "#2f3037",
|
|
"inverse-on-surface": "#2f3035",
|
|
"primary": "#adc6ff",
|
|
"on-primary": "#002e69",
|
|
"primary-fixed-dim": "#adc6ff",
|
|
"on-primary-fixed-variant": "#004493",
|
|
"on-error-container": "#ffdad6",
|
|
"tertiary": "#c6c6c7",
|
|
"on-background": "#e3e2e7",
|
|
"on-surface": "#e3e2e7",
|
|
"surface": "#121317",
|
|
"outline-variant": "#414755",
|
|
"on-primary-container": "#00285c",
|
|
"error": "#ffb4ab",
|
|
"surface-container-low": "#1a1b20",
|
|
"outline": "#8b90a0",
|
|
"on-tertiary-container": "#282a2a",
|
|
"surface-tint": "#adc6ff",
|
|
"on-primary-fixed": "#001a41",
|
|
"on-tertiary-fixed": "#1a1c1c",
|
|
"inverse-primary": "#005bc1",
|
|
"background": "#121317",
|
|
"surface-bright": "#38393d",
|
|
"error-container": "#93000a",
|
|
"surface-dim": "#121317",
|
|
"surface-container-highest": "#343439",
|
|
"tertiary-fixed-dim": "#c6c6c7",
|
|
"secondary-container": "#4a4b53",
|
|
"primary-fixed": "#d8e2ff",
|
|
"on-surface-variant": "#c1c6d7",
|
|
"surface-container": "#1f1f24",
|
|
"secondary-fixed": "#e3e1eb",
|
|
"tertiary-container": "#909191",
|
|
"secondary-fixed-dim": "#c6c5cf",
|
|
"secondary": "#c6c5cf",
|
|
"surface-variant": "#343439",
|
|
"on-secondary-container": "#bcbbc4",
|
|
"on-tertiary": "#2f3131",
|
|
"on-error": "#690005",
|
|
"primary-container": "#4b8eff",
|
|
"on-tertiary-fixed-variant": "#454747",
|
|
"surface-container-lowest": "#0d0e12",
|
|
"on-secondary-fixed": "#1a1b22",
|
|
"surface-container-high": "#292a2e"
|
|
},
|
|
"borderRadius": {
|
|
"DEFAULT": "0.25rem",
|
|
"lg": "0.5rem",
|
|
"xl": "0.75rem",
|
|
"full": "9999px"
|
|
},
|
|
"spacing": {
|
|
"md": "24px",
|
|
"sm": "12px",
|
|
"margin": "32px",
|
|
"gutter": "24px",
|
|
"base": "8px",
|
|
"xs": "4px",
|
|
"lg": "48px",
|
|
"xl": "80px"
|
|
},
|
|
"fontFamily": {
|
|
"body-md": ["Inter"],
|
|
"label-sm": ["Inter"],
|
|
"body-lg": ["Inter"],
|
|
"label-lg": ["Inter"],
|
|
"headline-xl": ["Space Grotesk"],
|
|
"headline-md": ["Space Grotesk"],
|
|
"headline-lg": ["Space Grotesk"]
|
|
},
|
|
"fontSize": {
|
|
"body-md": ["16px", { "lineHeight": "1.5", "fontWeight": "400" }],
|
|
"label-sm": ["12px", { "lineHeight": "1.2", "letterSpacing": "0.02em", "fontWeight": "500" }],
|
|
"body-lg": ["18px", { "lineHeight": "1.6", "fontWeight": "400" }],
|
|
"label-lg": ["14px", { "lineHeight": "1.2", "letterSpacing": "0.05em", "fontWeight": "600" }],
|
|
"headline-xl": ["48px", { "lineHeight": "1.1", "letterSpacing": "-0.02em", "fontWeight": "700" }],
|
|
"headline-md": ["24px", { "lineHeight": "1.3", "fontWeight": "500" }],
|
|
"headline-lg": ["32px", { "lineHeight": "1.2", "letterSpacing": "-0.01em", "fontWeight": "600" }]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
.glass-card {
|
|
background: rgba(31, 31, 36, 0.4);
|
|
backdrop-filter: blur(20px);
|
|
-webkit-backdrop-filter: blur(20px);
|
|
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
transition: all 0.3s ease;
|
|
}
|
|
.glass-card:hover {
|
|
border-color: rgba(75, 142, 255, 0.4);
|
|
background: rgba(41, 42, 46, 0.6);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 10px 30px -10px rgba(75, 142, 255, 0.15);
|
|
}
|
|
.glow-icon {
|
|
text-shadow: 0 0 15px rgba(75, 142, 255, 0.5);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="bg-background text-on-background font-body-md min-h-screen flex overflow-x-hidden">
|
|
<!-- SideNavBar -->
|
|
<nav class="hidden md:flex flex-col h-screen fixed left-0 top-0 w-64 border-r border-white/10 bg-[#0F1014]/80 backdrop-blur-2xl shadow-[10px_0_30px_-15px_rgba(0,122,255,0.2)] py-8 z-50">
|
|
<div class="px-6 mb-8 flex items-center gap-3">
|
|
<span class="material-symbols-outlined text-primary text-3xl glow-icon" style="font-variation-settings: 'FILL' 1;">dataset</span>
|
|
<div>
|
|
<h1 class="font-headline-md text-headline-md text-on-surface">AuraStream</h1>
|
|
<p class="font-label-sm text-label-sm text-outline">Premium Tier</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex-1 flex flex-col gap-2 mt-4">
|
|
<a class="bg-blue-500/10 text-blue-400 border-l-4 border-blue-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium" href="#">
|
|
<span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">live_tv</span>
|
|
Live TV
|
|
</a>
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">movie</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Movies</span>
|
|
</a>
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">theaters</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Series</span>
|
|
</a>
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">fiber_manual_record</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Recordings</span>
|
|
</a>
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">settings</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Settings</span>
|
|
</a>
|
|
</div>
|
|
<div class="mt-auto flex flex-col gap-2">
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">help</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Support</span>
|
|
</a>
|
|
<a class="text-slate-500 flex items-center gap-4 px-6 py-4 font-['Space_Grotesk'] text-sm font-medium hover:bg-white/5 hover:text-white transition-colors group" href="#">
|
|
<span class="material-symbols-outlined group-hover:translate-x-1 transition-transform duration-200" style="font-variation-settings: 'FILL' 0;">logout</span>
|
|
<span class="group-hover:translate-x-1 transition-transform duration-200">Logout</span>
|
|
</a>
|
|
</div>
|
|
</nav>
|
|
<!-- Main Content Canvas -->
|
|
<main class="flex-1 md:ml-64 p-margin min-h-screen flex flex-col relative">
|
|
<!-- Ambient background glow -->
|
|
<div class="absolute top-0 left-1/4 w-1/2 h-1/2 bg-primary/5 blur-[120px] rounded-full pointer-events-none"></div>
|
|
<!-- Header -->
|
|
<header class="flex justify-between items-end mb-10 pb-6 border-b border-white/5 relative z-10">
|
|
<div>
|
|
<h2 class="font-headline-lg text-headline-lg text-on-surface mb-2">Live TV Categories</h2>
|
|
<p class="font-body-md text-body-md text-outline">Select a category to browse channels</p>
|
|
</div>
|
|
<div class="flex gap-4">
|
|
<div class="relative">
|
|
<span class="material-symbols-outlined absolute left-4 top-1/2 -translate-y-1/2 text-outline">search</span>
|
|
<input class="bg-surface-container border border-outline-variant rounded-full py-2 pl-12 pr-4 font-body-md text-body-md text-on-surface focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary w-64 transition-all placeholder:text-outline/50" placeholder="Search categories..." type="text"/>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<!-- Bento Grid -->
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 relative z-10">
|
|
<!-- Category Card 1 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">FRANCE HEVC</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">142 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 2 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">FRANCE SPORTS</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">45 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 3 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">CINEMA</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">89 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 4 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">DOCUMENTARY</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">34 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 5 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">KIDS</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">28 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 6 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group" href="#">
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">folder</span>
|
|
</div>
|
|
<div class="mt-2">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">NEWS INT</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">62 Channels</p>
|
|
</div>
|
|
</a>
|
|
<!-- Category Card 7 -->
|
|
<a class="glass-card rounded-xl p-6 flex flex-col gap-4 group col-span-1 sm:col-span-2 lg:col-span-2 relative overflow-hidden" href="#">
|
|
<!-- Decorative element for wide card -->
|
|
<div class="absolute right-0 bottom-0 w-32 h-32 bg-primary/10 rounded-tl-full blur-2xl"></div>
|
|
<div class="w-12 h-12 rounded-lg bg-surface-container-high flex items-center justify-center border border-white/5 group-hover:bg-primary/10 transition-colors relative z-10">
|
|
<span class="material-symbols-outlined text-outline group-hover:text-primary transition-colors" style="font-variation-settings: 'FILL' 0;">star</span>
|
|
</div>
|
|
<div class="mt-2 relative z-10">
|
|
<h3 class="font-headline-md text-headline-md text-on-surface group-hover:text-primary-fixed transition-colors">FAVORITES</h3>
|
|
<p class="font-label-sm text-label-sm text-outline mt-1 uppercase tracking-wider">Your curated collection</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
</main>
|
|
</body></html> |