mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-15 00:33:44 +08:00
feat: Add GitHub link to navbar and implement direct video playback links for secret page.
This commit is contained in:
@@ -49,6 +49,7 @@ function SecretHomePage() {
|
||||
results={results}
|
||||
availableSources={availableSources}
|
||||
loading={loading}
|
||||
openDirectLinks={true}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -11,9 +11,10 @@ interface SearchResultsProps {
|
||||
results: Video[];
|
||||
availableSources: SourceBadge[];
|
||||
loading: boolean;
|
||||
openDirectLinks?: boolean;
|
||||
}
|
||||
|
||||
export function SearchResults({ results, availableSources, loading }: SearchResultsProps) {
|
||||
export function SearchResults({ results, availableSources, loading, openDirectLinks = false }: SearchResultsProps) {
|
||||
// Source badges hook - filters by video source
|
||||
const {
|
||||
selectedSources,
|
||||
@@ -61,7 +62,7 @@ export function SearchResults({ results, availableSources, loading }: SearchResu
|
||||
)}
|
||||
|
||||
{/* Display filtered videos (both source and type filters applied) */}
|
||||
<VideoGrid videos={finalFilteredVideos} />
|
||||
<VideoGrid videos={finalFilteredVideos} openDirectLinks={openDirectLinks} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { ThemeSwitcher } from '@/components/ThemeSwitcher';
|
||||
import { Icons } from '@/components/ui/Icon';
|
||||
|
||||
interface NavbarProps {
|
||||
onReset: () => void;
|
||||
@@ -38,6 +39,15 @@ export function Navbar({ onReset }: NavbarProps) {
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<a
|
||||
href="https://github.com/KuekHaoYang/KVideo"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-10 h-10 flex items-center justify-center rounded-[var(--radius-full)] bg-[var(--glass-bg)] border border-[var(--glass-border)] text-[var(--text-color)] hover:bg-[color-mix(in_srgb,var(--accent-color)_10%,transparent)] transition-all duration-200 cursor-pointer"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<Icons.Github size={20} />
|
||||
</a>
|
||||
<Link
|
||||
href="/settings"
|
||||
className="w-10 h-10 flex items-center justify-center rounded-[var(--radius-full)] bg-[var(--glass-bg)] border border-[var(--glass-border)] text-[var(--text-color)] hover:bg-[color-mix(in_srgb,var(--accent-color)_10%,transparent)] transition-all duration-200 cursor-pointer"
|
||||
|
||||
@@ -15,7 +15,7 @@ interface VideoCardProps {
|
||||
videoUrl: string;
|
||||
cardId: string;
|
||||
isActive: boolean;
|
||||
onCardClick: (e: React.MouseEvent, cardId: string, videoUrl: string) => void;
|
||||
onCardClick: (e: React.MouseEvent, cardId: string, videoUrl: string, video: Video) => void;
|
||||
}
|
||||
|
||||
export const VideoCard = memo<VideoCardProps>(({
|
||||
@@ -35,7 +35,7 @@ export const VideoCard = memo<VideoCardProps>(({
|
||||
<Link
|
||||
key={cardId}
|
||||
href={videoUrl}
|
||||
onClick={(e) => onCardClick(e, cardId, videoUrl)}
|
||||
onClick={(e) => onCardClick(e, cardId, videoUrl, video)}
|
||||
role="listitem"
|
||||
aria-label={`${video.vod_name}${video.vod_remarks ? ` - ${video.vod_remarks}` : ''}`}
|
||||
prefetch={false}
|
||||
|
||||
@@ -8,9 +8,10 @@ import { Video } from '@/lib/types';
|
||||
interface VideoGridProps {
|
||||
videos: Video[];
|
||||
className?: string;
|
||||
openDirectLinks?: boolean;
|
||||
}
|
||||
|
||||
export const VideoGrid = memo(function VideoGrid({ videos, className = '' }: VideoGridProps) {
|
||||
export const VideoGrid = memo(function VideoGrid({ videos, className = '', openDirectLinks = false }: VideoGridProps) {
|
||||
const [activeCardId, setActiveCardId] = useState<string | null>(null);
|
||||
const [visibleCount, setVisibleCount] = useState(24);
|
||||
const gridRef = useRef<HTMLDivElement>(null);
|
||||
@@ -36,7 +37,25 @@ export const VideoGrid = memo(function VideoGrid({ videos, className = '' }: Vid
|
||||
}, []);
|
||||
|
||||
// Memoize the click handler to prevent re-renders
|
||||
const handleCardClick = useCallback((e: React.MouseEvent, videoId: string, videoUrl: string) => {
|
||||
const handleCardClick = useCallback((e: React.MouseEvent, videoId: string, videoUrl: string, video?: Video) => {
|
||||
if (openDirectLinks && video?.vod_play_url) {
|
||||
// For secret page: extract first video URL and open directly
|
||||
e.preventDefault();
|
||||
const playUrls = video.vod_play_url.split('$$$');
|
||||
if (playUrls.length > 0) {
|
||||
const firstPlaylist = playUrls[0];
|
||||
const segments = firstPlaylist.split('#');
|
||||
if (segments.length > 0) {
|
||||
const urls = segments[0].split('$');
|
||||
if (urls.length > 1) {
|
||||
window.open(urls[1], '_blank');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a mobile device
|
||||
const isMobile = window.innerWidth < 1024; // lg breakpoint
|
||||
|
||||
@@ -52,7 +71,7 @@ export const VideoGrid = memo(function VideoGrid({ videos, className = '' }: Vid
|
||||
}
|
||||
}
|
||||
// On desktop, let the Link work normally
|
||||
}, [activeCardId]);
|
||||
}, [activeCardId, openDirectLinks]);
|
||||
|
||||
// Memoize video items to prevent unnecessary re-computations
|
||||
const videoItems = useMemo(() => {
|
||||
|
||||
@@ -121,4 +121,10 @@ export const UtilityIcons = {
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
|
||||
</svg>
|
||||
),
|
||||
|
||||
Github: ({ className = "", size = 24 }: IconProps) => (
|
||||
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
|
||||
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22" />
|
||||
</svg>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface VideoItem {
|
||||
vod_actor?: string;
|
||||
vod_director?: string;
|
||||
vod_content?: string;
|
||||
vod_play_url?: string;
|
||||
source: string;
|
||||
latency?: number; // Response time in milliseconds
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user