Files
KVideo/app/page.tsx
T

138 lines
4.0 KiB
TypeScript

'use client';
import { useState, useRef, useEffect, Suspense } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { SearchForm } from '@/components/search/SearchForm';
import { NoResults } from '@/components/search/NoResults';
import { PopularFeatures } from '@/components/home/PopularFeatures';
import { WatchHistorySidebar } from '@/components/history/WatchHistorySidebar';
import { useSearchCache } from '@/lib/hooks/useSearchCache';
import { useParallelSearch } from '@/lib/hooks/useParallelSearch';
import { settingsStore } from '@/lib/store/settings-store';
import { Navbar } from '@/components/layout/Navbar';
import { SearchResults } from '@/components/home/SearchResults';
function HomePage() {
const router = useRouter();
const searchParams = useSearchParams();
const { loadFromCache, saveToCache } = useSearchCache();
const hasLoadedCache = useRef(false);
const [query, setQuery] = useState('');
const [hasSearched, setHasSearched] = useState(false);
const [currentSortBy, setCurrentSortBy] = useState('default');
// Search stream hook
const {
loading,
results,
availableSources,
completedSources,
totalSources,
performSearch,
resetSearch,
loadCachedResults,
} = useParallelSearch(
saveToCache,
(q: string) => router.replace(`/?q=${encodeURIComponent(q)}`, { scroll: false })
);
// Load sort preference on mount
useEffect(() => {
const settings = settingsStore.getSettings();
setCurrentSortBy(settings.sortBy);
}, []);
// Load cached results on mount
useEffect(() => {
if (hasLoadedCache.current) return;
hasLoadedCache.current = true;
const urlQuery = searchParams.get('q');
const cached = loadFromCache();
if (urlQuery) {
setQuery(urlQuery);
if (cached && cached.query === urlQuery && cached.results.length > 0) {
setHasSearched(true);
loadCachedResults(cached.results, cached.availableSources);
} else {
setTimeout(() => handleSearch(urlQuery), 100);
}
}
}, [searchParams, loadFromCache, loadCachedResults]);
const handleSearch = (searchQuery: string) => {
setQuery(searchQuery);
setHasSearched(true);
performSearch(searchQuery, currentSortBy as any);
};
const handleReset = () => {
setHasSearched(false);
setQuery('');
resetSearch();
router.replace('/', { scroll: false });
};
return (
<div className="min-h-screen">
{/* Glass Navbar */}
<Navbar onReset={handleReset} />
{/* Search Form - Separate from navbar */}
<div className="max-w-7xl mx-auto px-4 mt-6 mb-8 relative" style={{
transform: 'translate3d(0, 0, 0)',
zIndex: 1000
}}>
<SearchForm
onSearch={handleSearch}
onClear={handleReset}
isLoading={loading}
initialQuery={query}
currentSource=""
checkedSources={completedSources}
totalSources={totalSources}
/>
</div>
{/* Main Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-20">
{/* Results Section */}
{(results.length >= 1 || (!loading && results.length > 0)) && (
<SearchResults
results={results}
availableSources={availableSources}
loading={loading}
/>
)}
{/* Popular Features - Homepage */}
{!loading && !hasSearched && <PopularFeatures onSearch={handleSearch} />}
{/* No Results */}
{!loading && hasSearched && results.length === 0 && (
<NoResults onReset={handleReset} />
)}
</main>
{/* Watch History Sidebar */}
<WatchHistorySidebar />
</div>
);
}
export default function Home() {
return (
<Suspense fallback={
<div className="min-h-screen flex items-center justify-center">
<div className="animate-spin rounded-full h-16 w-16 border-4 border-[var(--accent-color)] border-t-transparent"></div>
</div>
}>
<HomePage />
</Suspense>
);
}