import React, { useState, KeyboardEvent } from 'react';
import { FaSearch, FaSpinner, FaTimes } from 'react-icons/fa';
import { getInvidiousSearchURL, INVIDIOUS_BASE_URL } from '../config';
interface InvidiousVideoThumbnail {
quality: string;
url: string;
width: number;
height: number;
}
interface InvidiousResult {
type: string;
title: string;
videoId: string;
author: string;
videoThumbnails?: InvidiousVideoThumbnail[];
}
interface InvidiousSearchModalProps {
isOpen: boolean;
onClose: () => void;
onSelectVideo: (url: string) => void;
}
const ResultCell: React.FC<{ result: InvidiousResult, onClick: () => void }> = ({ result, onClick, ...props }) => {
const thumbnailUrl = (result: InvidiousResult) => {
if (!result.videoThumbnails) return '/assets/placeholder.jpg';
const thumbnail = result.videoThumbnails.find(t => t.quality === 'medium');
return thumbnail ? `${INVIDIOUS_BASE_URL}${thumbnail.url}` : '/assets/placeholder.jpg';
};
return (
{result.title}
{result.author}
);
};
const InvidiousSearchModal: React.FC = ({ isOpen, onClose, onSelectVideo }) => {
const [searchQuery, setSearchQuery] = useState('');
const [results, setResults] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const handleSearch = async () => {
if (!searchQuery.trim()) return;
setIsLoading(true);
try {
const response = await fetch(getInvidiousSearchURL(searchQuery));
const data = await response.json();
const videoResults = data.filter((item: InvidiousResult) => {
return item.type === 'video' || item.type === 'playlist'
});
setResults(videoResults);
} catch (error) {
console.error('Failed to search:', error);
} finally {
setIsLoading(false);
}
};
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Enter') {
handleSearch();
}
};
const _onSelectVideo = (url: string) => {
setSearchQuery('');
setResults([]);
onSelectVideo(url);
};
if (!isOpen) return null;
return (
Search YouTube (Invidious)
setSearchQuery(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Search videos..."
className="p-2 rounded-lg border-2 border-violet-500 flex-grow bg-black/20 text-white"
/>
{isLoading ? (
Searching...
) : (
{results.map((result) => (
_onSelectVideo(`https://www.youtube.com/watch?v=${result.videoId}`)}
/>
))}
)}
);
};
export default InvidiousSearchModal;