diff --git a/src/app/results/Playlist.tsx b/src/app/results/Playlist.tsx index b06d4d1..8c27ba4 100644 --- a/src/app/results/Playlist.tsx +++ b/src/app/results/Playlist.tsx @@ -6,8 +6,10 @@ import NextLink from "next/link"; import { Card, CardBody } from "@nextui-org/card"; import { Image } from "@nextui-org/image"; import { Link } from "@nextui-org/link"; +import { Listbox, ListboxItem } from "@nextui-org/listbox"; import { PlaylistItem } from "@/client/typings/item"; +import { videoUrl } from "@/utils/urls"; import { videoSize } from "@/utils/videoSize"; import { Component } from "@/typings/component"; @@ -16,14 +18,16 @@ export const Playlist: Component<{ data: PlaylistItem }> = ({ data }) => { const url = `/playlist/${data.id}`; const channelUrl = `/channel/${data.author.id}`; - const [width, height] = videoSize([16, 9], 30); + const [width, height] = videoSize(30); + + const [playlistItemWidth, playlistItemHeight] = videoSize(5); return ( - - - -
-
+ + +
+
+ = ({ data }) => { as={NextImage} unoptimized /> -

- {data.numberOfVideos} videos -

-
- -
-
-

{data.title}

+ +

+ {data.numberOfVideos} videos +

+
- -

- {data.author.name} -

- -
+
+
+ +

+ {data.title} +

+ - {data.videos && ( -
- {data.videos.map((video) => ( -

{video.title}

- ))} -
- )} + +

{data.author.name}

+
+ + {data.videos && ( + + {data.videos.map((video) => ( + + } + key={video.id} + href={videoUrl(video.id)} + > + {video.title} + + ))} + + )}
- - - +
+
+
); }; diff --git a/src/app/results/Search.tsx b/src/app/results/Search.tsx index 8202b73..eba280c 100644 --- a/src/app/results/Search.tsx +++ b/src/app/results/Search.tsx @@ -45,13 +45,14 @@ export const Search: Component = () => { return new Error(`The provided filter \`${filter}\` is invalid`); }, [filter]); + const canSearch = !(!!invalidQuery || !!invalidFilter); + const { data, error: fetchError, fetchNextPage, - // hasNextPage, refetch, - isFetching, + isPending, isFetchingNextPage } = useInfiniteQuery({ queryKey: ["search", query, filter], @@ -61,12 +62,12 @@ export const Search: Component = () => { type: filter }); }, - enabled: !!invalidQuery || !!invalidFilter, + enabled: canSearch, initialPageParam: "", getNextPageParam: (lastPage) => lastPage.nextCursor }); - const error = invalidQuery ?? invalidFilter ?? fetchError ?? undefined; + const error = invalidFilter ?? fetchError ?? undefined; const searchFor = useSearch(); @@ -84,6 +85,13 @@ export const Search: Component = () => { [isFetchingNextPage, fetchNextPage] ); + const hasLoadedData = + canSearch && data?.pages.flat().length + ? data?.pages.flat().length !== 0 + : false; + + const isLoadingInitialData = canSearch && !isFetchingNextPage && isPending; + return ( <> @@ -91,12 +99,13 @@ export const Search: Component = () => {
-
- -
+ {canSearch && ( +
+ +
+ )}
- - {isFetching && !error && } + {isLoadingInitialData && } {error && (
@@ -111,32 +120,34 @@ export const Search: Component = () => {
)} -
- {!error && - data?.pages.map((page, i) => { - return ( - - {page.items.map((result) => { - switch (result.type) { - case "channel": - return ; - - case "video": - return - ); - })} - - -
+ {hasLoadedData && ( + <> +
+ {data?.pages.map((page, i) => { + return ( + + {page.items.map((result) => { + switch (result.type) { + case "channel": + return ; + + case "video": + return + ); + })} +
+ + + )} ); diff --git a/src/app/results/Video.tsx b/src/app/results/Video.tsx index 4009310..f11c1c6 100644 --- a/src/app/results/Video.tsx +++ b/src/app/results/Video.tsx @@ -20,14 +20,14 @@ export const Video: Component<{ data: VideoItem }> = ({ data }) => { const url = `/watch?v=${data.id}`; const channelUrl = `/channel/${data.author.id}`; - const [width, height] = videoSize([16, 9], 30); + const [width, height] = videoSize(30); return ( - - - -
-
+ + +
+
+ = ({ data }) => { as={NextImage} unoptimized /> -

- {formatDuration(data.duration)} + + +

+ {formatDuration(data.duration)} +

+ {data.live && ( +

+ LIVE

- {data.live && ( -

- LIVE -

- )} -
+ )} +
-
-

{data.title}

-
-

{formatBigNumber(data.views)} views

- {data.uploaded &&

{formatUploadedTime(data.uploaded)}

} -
- - {data.author.avatar && ( - - )} -

{data.author.name}

- -

{data.description}

+
+ +

{data.title}

+ +
+

{formatBigNumber(data.views)} views

+ {data.uploaded &&

{formatUploadedTime(data.uploaded)}

}
+ + {data.author.avatar && ( + + )} +

{data.author.name}

+ +

{data.description}

- - - +
+
+
); }; diff --git a/src/app/trending/Trending.tsx b/src/app/trending/Trending.tsx index cb4764b..34805fa 100644 --- a/src/app/trending/Trending.tsx +++ b/src/app/trending/Trending.tsx @@ -70,11 +70,11 @@ export const Trending: Component = ({}) => { return ( <> -
+
-

Trending

+ {isLoading && !data && } {error && (
diff --git a/src/app/trending/page.tsx b/src/app/trending/page.tsx index 99a4fd4..18c4678 100644 --- a/src/app/trending/page.tsx +++ b/src/app/trending/page.tsx @@ -1,6 +1,7 @@ import { NextPage } from "next"; import { Suspense } from "react"; +import { Container } from "@/components/Container"; import { LoadingPage } from "@/components/LoadingPage"; import { Trending } from "./Trending"; @@ -8,7 +9,13 @@ import { Trending } from "./Trending"; const Page: NextPage = () => { return ( <> - }> + + + + } + > diff --git a/src/app/watch/Description.tsx b/src/app/watch/Description.tsx index 1d7192a..cd81a7b 100644 --- a/src/app/watch/Description.tsx +++ b/src/app/watch/Description.tsx @@ -14,6 +14,8 @@ import { highlight, ItemType } from "@/utils/highlight"; import { Component } from "@/typings/component"; +const shortenedDescriptionLength = 200; + export const Description: Component<{ data: string }> = ({ data }) => { const [expandedDescription, setExpandedDescription] = useState(false); @@ -32,7 +34,7 @@ export const Description: Component<{ data: string }> = ({ data }) => { () => expandedDescription ? sanitizedDescription - : sanitizedDescription?.substring(0, 200) + "...", + : sanitizedDescription.substring(0, shortenedDescriptionLength) + "...", [sanitizedDescription, expandedDescription] ); diff --git a/src/components/Nav/index.tsx b/src/components/Nav/index.tsx index 22bbf19..45023a3 100644 --- a/src/components/Nav/index.tsx +++ b/src/components/Nav/index.tsx @@ -10,8 +10,6 @@ import { NavbarItem } from "@nextui-org/navbar"; -// import { Search } from "./Search"; - export const navHeight = 64; export const Nav: FC<{ pathname: string }> = ({ pathname }) => { @@ -20,6 +18,10 @@ export const Nav: FC<{ pathname: string }> = ({ pathname }) => { title: "Trending", link: "/trending" }, + { + title: "Search", + link: "/results" + }, { title: "Subscriptions", link: "/subscriptions" diff --git a/src/components/Search.tsx b/src/components/Search.tsx index eade196..c696f46 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -3,7 +3,7 @@ import { useDebounce } from "use-debounce"; import { useQuery } from "@tanstack/react-query"; -import { useMemo, useState } from "react"; +import { FC, useMemo, useState } from "react"; import { FiSearch as SearchIcon } from "react-icons/fi"; import { Autocomplete, AutocompleteItem } from "@nextui-org/autocomplete"; @@ -11,9 +11,7 @@ import { Autocomplete, AutocompleteItem } from "@nextui-org/autocomplete"; import { useClient } from "@/hooks/useClient"; import { useSearch } from "@/hooks/useSearch"; -import { Component } from "@/typings/component"; - -export const Search: Component<{ +export const Search: FC<{ initialQueryValue?: string; }> = ({ initialQueryValue }) => { const client = useClient(); @@ -73,7 +71,7 @@ export const Search: Component<{ required type="text" label="Search" - variant="flat" + variant="bordered" placeholder="Search for videos" > {(suggestion) => ( diff --git a/src/components/Video.tsx b/src/components/Video.tsx index 91687b1..384a7d8 100644 --- a/src/components/Video.tsx +++ b/src/components/Video.tsx @@ -25,7 +25,7 @@ export const Video: Component<{ data: VideoProps; size?: number }> = ({ }) => { const url = videoUrl(data.id); - const [width, height] = videoSize([16, 9], size); + const [width, height] = videoSize(size); const menuItems = useMemo(() => { const items: ContextMenuItem[] = [ diff --git a/src/utils/highlight.ts b/src/utils/highlight.ts index 3d091a3..ad4597f 100644 --- a/src/utils/highlight.ts +++ b/src/utils/highlight.ts @@ -19,8 +19,6 @@ const itemPatterns: ItemPattern[] = [ regex: /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g, convert: (match): Link => { - console.log(match); - return { type: ItemType.Link, href: match[0], diff --git a/src/utils/videoSize.ts b/src/utils/videoSize.ts index 7cece18..ecc0998 100644 --- a/src/utils/videoSize.ts +++ b/src/utils/videoSize.ts @@ -1,6 +1,6 @@ export const videoSize = ( - aspectRatio: [number, number], - size: number + size: number, + aspectRatio: [number, number] = [16, 9] ): [number, number] => { return [aspectRatio[0] * size, aspectRatio[1] * size]; };