From 9a04f4f2eccc6cc9a1bfa28747bc60b38fd24891 Mon Sep 17 00:00:00 2001 From: Artemy Date: Thu, 10 Aug 2023 14:14:51 +0300 Subject: [PATCH] feat: search --- package-lock.json | 8 ++-- package.json | 2 +- src/App.tsx | 3 ++ src/components/item.tsx | 6 +-- src/components/navbar.tsx | 14 +++++- src/pages/channel.tsx | 4 +- src/pages/search.tsx | 98 +++++++++++++++++++++++++++++++++++++++ src/pages/trending.tsx | 15 +++--- 8 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 src/pages/search.tsx diff --git a/package-lock.json b/package-lock.json index 934b403..d0014ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@heroicons/react": "^2.0.18", "@nextui-org/react": "^2.0.7", "framer-motion": "^10.15.1", - "piped-api": "^1.2.2", + "piped-api": "^1.2.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.2" @@ -4439,9 +4439,9 @@ } }, "node_modules/piped-api": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/piped-api/-/piped-api-1.2.2.tgz", - "integrity": "sha512-eSzyanTMRGq3c9xCsSSlDXQ7jmd9auLvRIP5RNwv7yIkYBQjBxbQI5CR1vLcmKnD1tw4XdBF15aLIh0Jru3iIw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/piped-api/-/piped-api-1.2.3.tgz", + "integrity": "sha512-RL3C659rMC2Dwilcp0ejNQV0iiNd+DthmFDWYmGZNAcDN/bMJY3+J3p4dRFNzbplKh1jSA8j5tGkXRpIDMizKA==", "dependencies": { "axios": "^1.4.0" } diff --git a/package.json b/package.json index dabddf4..a341944 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@heroicons/react": "^2.0.18", "@nextui-org/react": "^2.0.7", "framer-motion": "^10.15.1", - "piped-api": "^1.2.2", + "piped-api": "^1.2.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.14.2" diff --git a/src/App.tsx b/src/App.tsx index b24318a..25b6182 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import TrendingPage from "./pages/trending"; import { NavbarComponent } from "./components/navbar"; import ChannelPage from "./pages/channel"; import { useState } from "react"; +import SearchPage from "./pages/search"; declare global { interface Window { @@ -26,6 +27,8 @@ function App() { } /> } /> } /> + } /> + } /> ); diff --git a/src/components/item.tsx b/src/components/item.tsx index db1f096..914d6db 100644 --- a/src/components/item.tsx +++ b/src/components/item.tsx @@ -6,11 +6,11 @@ import { ChannelComponent } from "./channel"; export function ItemComponent({ item, channel }: ItemComponentProps) { if (item.type === "stream") { item = item as Video; - return ; + return ; } else if (item.type === "playlist") { item = item as Playlist; return ( - + ); } else if (item.type === "channel") { item = item as Channel; @@ -23,6 +23,6 @@ export function ItemComponent({ item, channel }: ItemComponentProps) { } type ItemComponentProps = { - channel: Channel; + channel?: Channel; item: Video | Playlist | Channel; }; diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index 133b46b..37453ab 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -9,9 +9,14 @@ import { NavbarMenuItem, Input, } from "@nextui-org/react"; -import { Link } from "react-router-dom"; +import { useState } from "react"; +import { Link, useNavigate, useSearchParams } from "react-router-dom"; export function NavbarComponent() { + const [search, setSearch] = useState(""); + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + return ( @@ -30,6 +35,13 @@ export function NavbarComponent() { radius="lg" placeholder="Type to search..." startContent={} + onChange={(e) => setSearch(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") { + navigate(`/search?q=${search}`); + } + }} + defaultValue={searchParams.get("q") || ""} /> diff --git a/src/pages/channel.tsx b/src/pages/channel.tsx index d61caae..d143420 100644 --- a/src/pages/channel.tsx +++ b/src/pages/channel.tsx @@ -78,11 +78,11 @@ class ChannelPageŠ”omponent extends React.Component< if (!channel) { return ( -
+ {[...Array(20).keys()].map((num) => ( ))} -
+ ); } else { return ( diff --git a/src/pages/search.tsx b/src/pages/search.tsx new file mode 100644 index 0000000..7bd6a22 --- /dev/null +++ b/src/pages/search.tsx @@ -0,0 +1,98 @@ +import { Item } from "piped-api/dist/types"; +import { SkeletonVideoComponent, VideoContainer } from "../components/video"; +import React from "react"; +import { useSearchParams } from "react-router-dom"; +import { ItemComponent } from "../components/item"; +import { Button } from "@nextui-org/react"; + +export default function SearchPage() { + const [searchParams, setSearchParams] = useSearchParams(); + + return ( + + ); +} + +class SearchPageComponent extends React.Component< + { search: string; setSearchParams }, + { + items: Item[]; + corrected: boolean; + suggestion: string | null; + nextpage: string; + search: string; + } +> { + async componentDidMount() { + const { items, corrected, suggestion, nextpage } = + await window.piped_api.search(this.props.search); + + this.setState({ + items, + corrected, + suggestion, + nextpage, + search: this.props.search, + }); + } + + async componentDidUpdate() { + if (this.props.search !== this.state.search) { + const { items, corrected, suggestion, nextpage } = + await window.piped_api.search(this.props.search); + + this.setState({ + items, + corrected, + suggestion, + nextpage, + search: this.props.search, + }); + } + } + + render() { + if (!this.state) { + return null; + } + + const { items } = this.state; + + if (items.length === 0) { + return ( + + {[...Array(20).keys()].map((num) => ( + + ))} + + ); + } + + return ( + <> + {this.state.suggestion && ( +
+ Did you mean + + ? +
+ )} + + {items.map((video) => ( + + ))} + + + ); + } +} diff --git a/src/pages/trending.tsx b/src/pages/trending.tsx index be8ac8d..4c2423d 100644 --- a/src/pages/trending.tsx +++ b/src/pages/trending.tsx @@ -1,5 +1,9 @@ import { Video } from "piped-api/dist/types"; -import { SkeletonVideoComponent, VideoComponent } from "../components/video"; +import { + SkeletonVideoComponent, + VideoComponent, + VideoContainer, +} from "../components/video"; import React from "react"; export default class TrendingPage extends React.Component { @@ -8,7 +12,6 @@ export default class TrendingPage extends React.Component { }; async componentDidMount() { - console.log("trending"); const trending = await window.piped_api.trending( localStorage.getItem("region") || "US" ); @@ -20,20 +23,20 @@ export default class TrendingPage extends React.Component { if (trending.length === 0) { return ( -
+ {[...Array(20).keys()].map((num) => ( ))} -
+ ); } return ( -
+ {trending.map((video) => ( ))} -
+ ); } }