Restored to '44d6f571a5a2b8bce0fd4e8a9eae76204284885b'

Replit-Restored-To: 44d6f571a5
This commit is contained in:
sebastjanartic
2025-08-28 17:43:16 +00:00
parent 8fe4a6f7f6
commit 42883d8409
12 changed files with 85 additions and 469 deletions
+24 -65
View File
@@ -5,8 +5,7 @@ import { type Video } from "@shared/schema";
import go4LogoPath from "@assets/go4_1756394900352.png";
// Helper functions
const formatViews = (views: number | undefined): string => {
if (!views) return '0';
const formatViews = (views: number): string => {
if (views >= 1000000) return `${(views / 1000000).toFixed(1)}M`;
if (views >= 1000) return `${(views / 1000).toFixed(1)}K`;
return views.toString();
@@ -32,9 +31,7 @@ const formatDate = (date: Date | string): string => {
});
};
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Share2, X, Edit3, Search } from "lucide-react";
import Hls from "hls.js";
import { Share2, X, Edit3 } from "lucide-react";
import { apiRequest } from "@/lib/queryClient";
import {
FacebookShareButton,
@@ -55,7 +52,6 @@ export default function VideoPage() {
const [, params] = useRoute("/video/:id");
const videoId = params?.id;
const [showShareMenu, setShowShareMenu] = useState(false);
const [sidebarSearchQuery, setSidebarSearchQuery] = useState("");
// Fetch current video
const { data: currentVideo, isLoading: videoLoading } = useQuery<Video>({
@@ -64,26 +60,14 @@ export default function VideoPage() {
enabled: !!videoId,
});
// Fetch recommended videos using the same search endpoint as main page
// Fetch recommended videos (excluding current video)
const { data: recommendedResponse } = useQuery<VideosResponse>({
queryKey: ["/api/videos", sidebarSearchQuery],
queryFn: () => {
const url = sidebarSearchQuery && sidebarSearchQuery.length >= 2
? `/api/videos?limit=50&offset=0&search=${encodeURIComponent(sidebarSearchQuery)}`
: "/api/videos?limit=50&offset=0";
return fetch(url).then(res => res.json());
},
queryKey: ["/api/videos"],
queryFn: () => fetch("/api/videos?limit=20&offset=0").then(res => res.json()),
enabled: !!videoId,
});
// Simply exclude current video - search filtering is now done server-side
const filteredRecommendedVideos = (recommendedResponse?.videos || [])
.filter(v => v.id !== videoId);
// Debug logging for troubleshooting
if (sidebarSearchQuery.length >= 2) {
console.log(`Video page search "${sidebarSearchQuery}": Got ${recommendedResponse?.videos?.length || 0} videos from server, showing ${filteredRecommendedVideos.length} after filtering current video`);
}
const recommendedVideos = recommendedResponse?.videos?.filter(v => v.id !== videoId) || [];
@@ -255,18 +239,23 @@ export default function VideoPage() {
<div className="flex flex-col lg:flex-row gap-6 relative z-10">
{/* Main video section */}
<div className="flex-1">
{/* Bunny.net iframe player */}
{/* Video player */}
<div className="relative w-full h-0 pb-[56.25%] bg-black rounded-lg overflow-hidden mb-4">
<iframe
src={`https://iframe.mediadelivery.net/embed/${process.env.BUNNY_LIBRARY_ID || "384105"}/${currentVideo.id}?preroll=false&postroll=false&ads=false`}
className="absolute inset-0 w-full h-full"
frameBorder="0"
allowFullScreen
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
onLoad={handleVideoPlay}
title={currentVideo.title}
referrerPolicy="origin"
/>
{currentVideo.videoUrlIframe ? (
<iframe
src={currentVideo.videoUrlIframe}
className="absolute inset-0 w-full h-full"
frameBorder="0"
allowFullScreen
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
onLoad={handleVideoPlay}
title={currentVideo.title}
/>
) : (
<div className="absolute inset-0 flex items-center justify-center text-white">
<p>Video not available</p>
</div>
)}
</div>
{/* Video info */}
@@ -340,40 +329,10 @@ export default function VideoPage() {
{/* Recommended videos sidebar */}
<div className="lg:w-96">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-semibold text-bunny-light">Recommended Videos</h2>
</div>
{/* Search input for recommended videos */}
<div className="relative mb-4">
<Input
type="search"
placeholder="Search videos..."
value={sidebarSearchQuery}
onChange={(e) => setSidebarSearchQuery(e.target.value)}
className="bg-bunny-gray/50 border-bunny-gray/70 text-white placeholder-gray-400 pr-10 focus:border-bunny-blue transition-colors"
data-testid="input-sidebar-search"
/>
<Search className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
</div>
<h2 className="text-lg font-semibold text-bunny-light mb-4">Recommended Videos</h2>
<div className="space-y-3">
{/* Show search results info */}
{sidebarSearchQuery.length >= 2 && (
<div className="mb-2 text-xs text-bunny-muted">
{filteredRecommendedVideos.length === 0 ? (
<div className="text-center py-4">
<Search className="w-8 h-8 mx-auto mb-1 opacity-50" />
<p>No videos found for "{sidebarSearchQuery}"</p>
</div>
) : (
<p>Found {filteredRecommendedVideos.length} videos for "{sidebarSearchQuery}"</p>
)}
</div>
)}
{filteredRecommendedVideos.slice(0, 10).map((video) => (
{recommendedVideos.slice(0, 10).map((video) => (
<div
key={video.id}
onClick={() => window.location.href = `/video/${video.id}`}