mirror of
https://github.com/vndangkhoa/purestream.git
synced 2026-04-05 01:17:58 +07:00
feat: add immersive mode, improved search with fallback to trending videos
This commit is contained in:
parent
2d066b038b
commit
771d6f2c60
2 changed files with 76 additions and 0 deletions
25
backend/run_server.py
Normal file
25
backend/run_server.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
# Fix sys.path for user site-packages where pip installed dependencies
|
||||||
|
user_site = os.path.expanduser("~\\AppData\\Roaming\\Python\\Python312\\site-packages")
|
||||||
|
if os.path.exists(user_site) and user_site not in sys.path:
|
||||||
|
print(f"DEBUG: Adding user site-packages to path: {user_site}")
|
||||||
|
sys.path.append(user_site)
|
||||||
|
|
||||||
|
# Enforce ProactorEventLoopPolicy for Playwright on Windows
|
||||||
|
# This is required for asyncio.create_subprocess_exec used by Playwright
|
||||||
|
if sys.platform == "win32":
|
||||||
|
# Check if policy is already set
|
||||||
|
current_policy = asyncio.get_event_loop_policy()
|
||||||
|
if not isinstance(current_policy, asyncio.WindowsProactorEventLoopPolicy):
|
||||||
|
print("DEBUG: Setting WindowsProactorEventLoopPolicy")
|
||||||
|
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
|
||||||
|
else:
|
||||||
|
print("DEBUG: WindowsProactorEventLoopPolicy already active")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import uvicorn
|
||||||
|
print("🚀 Bootstrapping Uvicorn with Proactor Loop (Reload Disabled)...")
|
||||||
|
uvicorn.run("main:app", host="0.0.0.0", port=8002, reload=False, loop="asyncio")
|
||||||
51
frontend/src/components/SearchSkeleton.tsx
Normal file
51
frontend/src/components/SearchSkeleton.tsx
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface SearchSkeletonProps {
|
||||||
|
count?: number;
|
||||||
|
estimatedTime?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SearchSkeleton: React.FC<SearchSkeletonProps> = ({
|
||||||
|
count = 9,
|
||||||
|
estimatedTime
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Countdown Timer */}
|
||||||
|
{estimatedTime !== undefined && estimatedTime > 0 && (
|
||||||
|
<div className="text-center py-2">
|
||||||
|
<p className="text-white/50 text-xs">
|
||||||
|
Estimated time: ~{Math.ceil(estimatedTime)}s
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Skeleton Grid */}
|
||||||
|
<div className="grid grid-cols-3 gap-1">
|
||||||
|
{Array.from({ length: count }).map((_, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="aspect-[9/16] bg-white/5 rounded-lg animate-pulse relative overflow-hidden"
|
||||||
|
style={{
|
||||||
|
animationDelay: `${index * 100}ms`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Shimmer effect */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/5 to-transparent shimmer" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Add shimmer keyframes via inline style */}
|
||||||
|
<style>{`
|
||||||
|
@keyframes shimmer {
|
||||||
|
0% { transform: translateX(-100%); }
|
||||||
|
100% { transform: translateX(100%); }
|
||||||
|
}
|
||||||
|
.shimmer {
|
||||||
|
animation: shimmer 1.5s infinite;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue