From 1bfb10259a9337499a1595259a4db4d811f5922f Mon Sep 17 00:00:00 2001 From: Reynaldi Chernando Date: Tue, 3 Dec 2024 02:37:00 +0700 Subject: [PATCH] Optimize search render --- components/AddVideoDialog.tsx | 266 ++++++++++++++++++---------------- 1 file changed, 141 insertions(+), 125 deletions(-) diff --git a/components/AddVideoDialog.tsx b/components/AddVideoDialog.tsx index 6a55747..7831f27 100644 --- a/components/AddVideoDialog.tsx +++ b/components/AddVideoDialog.tsx @@ -9,7 +9,7 @@ import { } from "@/lib/utils"; import { fetchVideoInfo } from "@/lib/youtube"; import { Search } from "lucide-react"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; import { SearchResultItem } from "@/lib/model/SearchResultItem"; @@ -32,6 +32,107 @@ import { } from "./ui/dialog"; import { searchVideos } from "@/lib/flexSearch"; +function LocalSearchResults({ + videos, + onSelectVideo +}: { + videos: Video[]; + onSelectVideo: (video: Video) => void; +}) { + if (videos.length === 0) return null; + + return ( +
+

+ From Your Library +

+
+ {videos.map((video) => ( +
onSelectVideo(video)} + > +
+ {video.title} +
+

{video.title}

+

{video.author}

+
+
+
+ ))} +
+
+ ); +} + +function YouTubeSearchResults({ + videos, + searchQuery, + isLoading, + onAddVideo, + onSearch, + onClear +}: { + videos: Video[]; + searchQuery: string; + isLoading: boolean; + onAddVideo: (video: Video) => void; + onSearch: () => void; + onClear: () => void; +}) { + return ( +
+
+

+ From YouTube +

+
+ {videos.length > 0 && ( + + )} + +
+
+ {videos.length > 0 ? ( +
+ {videos.map((video) => ( + onAddVideo(video)} + /> + ))} +
+ ) : ( +
+ {searchQuery.length >= 2 + ? 'Click "Search YouTube" to find videos' + : "Type to search YouTube videos"} +
+ )} +
+ ); +} + export default function AddVideoDialog({ onAddVideo, onSelectVideo, @@ -59,25 +160,20 @@ export default function AddVideoDialog({ return () => clearTimeout(debounceTimeout); }, [searchQuery]); - const handleSearch = async () => { - if (!searchQuery) { - return; - } + const handleSearch = useCallback(async () => { + if (!searchQuery) return; + setSearchLoading(true); - try { if (isYoutubeUrl(searchQuery)) { const videoId = extractVideoId(searchQuery); const videoInfo = await fetchVideoInfo(videoId || ""); - - setRemoteVideos([ - { - id: videoId, - title: videoInfo.title, - thumbnail: generateThumbnailUrl(videoId), - author: videoInfo.uploader, - } as Video, - ]); + setRemoteVideos([{ + id: videoId, + title: videoInfo.title, + thumbnail: generateThumbnailUrl(videoId), + author: videoInfo.uploader, + } as Video]); } else { const res = await search({ query: `${searchQuery} site:youtube.com` }); setRemoteVideos( @@ -97,107 +193,45 @@ export default function AddVideoDialog({ } finally { setSearchLoading(false); } - }; + }, [searchQuery]); - const handleOpen = () => { + const handleOpen = useCallback(() => { setSearchQuery(""); setRemoteVideos([]); setLocalVideos([]); setOpen(true); - }; + }, []); - const handleSearchResultClick = (video: Video) => { - onSelectVideo(video); - setSearchQuery(""); - setOpen(false); - }; + const handleClearResults = useCallback(() => { + setRemoteVideos([]); + }, []); - const SearchResults = () => ( - <> + const searchContent = ( +
{ e.preventDefault(); handleSearch(); }} className="space-y-4"> + setSearchQuery(e.target.value)} + /> {searchQuery.length >= 2 && (
- {localVideos.length > 0 && ( -
-

- From Your Library -

-
- {localVideos.map((video) => ( -
handleSearchResultClick(video)} - > -
- {video.title} -
-

- {video.title} -

-

- {video.author} -

-
-
-
- ))} -
-
- )} -
-
-

- From YouTube -

-
- {remoteVideos.length > 0 && ( - - )} - -
-
- {remoteVideos.length > 0 ? ( -
- {remoteVideos.map((video) => ( - onAddVideo(video)} - /> - ))} -
- ) : ( -
- {searchQuery.length >= 2 - ? 'Click "Search YouTube" to find videos' - : "Type to search YouTube videos"} -
- )} -
+ +
)} - +
); if (isDesktop) { @@ -217,16 +251,7 @@ export default function AddVideoDialog({ Search Video -
- setSearchQuery(e.target.value)} - /> - - + {searchContent} ); @@ -248,16 +273,7 @@ export default function AddVideoDialog({ Search Video -
- setSearchQuery(e.target.value)} - /> - - + {searchContent} );