refactor: class components

This commit is contained in:
Artemy 2023-08-10 11:50:17 +03:00
parent b7a10179ad
commit bafd943814
3 changed files with 161 additions and 128 deletions

View file

@ -1,10 +1,3 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@layer base {
body {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' width='32' height='32' fill='none' stroke='%23f1f5f9'%3e%3cpath d='M0 .5H31.5V32'/%3e%3c/svg%3e");
@apply bg-gray-200;
}
}

View file

@ -1,5 +1,4 @@
import { Channel, Tab, Video } from "piped-api/dist/types"; import { Channel, Tab, Video } from "piped-api/dist/types";
import { useEffect, useState } from "react";
import { import {
SkeletonVideoComponent, SkeletonVideoComponent,
VideoComponent, VideoComponent,
@ -8,118 +7,156 @@ import {
import { useParams, useSearchParams } from "react-router-dom"; import { useParams, useSearchParams } from "react-router-dom";
import { Button, Card, CardFooter } from "@nextui-org/react"; import { Button, Card, CardFooter } from "@nextui-org/react";
import { capitalize } from "../components/utils"; import { capitalize } from "../components/utils";
import React from "react";
export default function ChannelPage() { export default function ChannelPage() {
const [channel, setChannel] = useState<Channel>();
const [tab, setTab] = useState<Tab>();
const { id } = useParams(); const { id } = useParams();
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const tabId = searchParams.get("tabId") || "videos"; const tabId = searchParams.get("tabId") || "videos";
useEffect(() => { return (
async function getChannel() { <ChannelPageСomponent
const channel = (await window.piped_api.channel(id || "")) as Channel; id={id}
setChannel(channel); setSearchParams={setSearchParams}
tabId={tabId}
/>
);
}
class ChannelPageСomponent extends React.Component<
{ id; setSearchParams; tabId },
{ channel: Channel; tab: Tab | undefined }
> {
async componentDidMount() {
const channel = (await window.piped_api.channel(
this.props.id || ""
)) as Channel;
if (this.props.tabId === "videos") {
return this.setState({ channel });
} }
async function getTab(name: string) { if (!this.state?.tab) {
const tab = await window.piped_api.channelTabs(channel?.tabs[name].data); const tab = await window.piped_api.channelTabs(
setTab(tab); channel.tabs[this.props.tabId].data
);
this.setState({ channel, tab });
} }
}
async updateTab() {
if (this.props.tabId === "videos") {
return;
}
const { channel } = this.state;
const tab = await window.piped_api.channelTabs(
channel.tabs[this.props.tabId].data
);
this.setState({ channel, tab });
}
componentDidUpdate() {
if (!this.state.tab) {
this.updateTab();
}
}
render() {
if (!this.state) {
return null;
}
const { channel, tab } = this.state;
const { setSearchParams, tabId } = this.props;
if (!channel) { if (!channel) {
getChannel(); return (
} <div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4">
{[...Array(20).keys()].map((num) => (
if (!tab && tabId !== "videos") { <SkeletonVideoComponent key={num} />
getTab(tabId); ))}
}
});
if (!channel) {
return (
<div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4">
{[...Array(20).keys()].map((num) => (
<SkeletonVideoComponent key={num} />
))}
</div>
);
} else {
return (
<div className="grid grid-rows p-4">
<Card radius="lg" shadow="none">
<div className="p-4">
<img className="w-full rounded-xl" src={channel.bannerUrl} />
</div>
<CardFooter className="p-4 justify-between ">
<div className="flex flex-col">
<div className="flex flex-row gap-2 text-xl font-bold pl-2">
{channel.name}
</div>
</div>
</CardFooter>
</Card>
<div className="flex flex-row flex-wrap gap-2 mt-4">
<Button
onClick={() => {
setSearchParams({ tabId: "videos" });
}}
key="videos"
className="text-xl font-bold mt-4"
>
Videos
</Button>
{channel.tabs.map((tab, index) => {
return (
<Button
onClick={() => {
setSearchParams({ tabId: String(index) });
setTab(undefined);
}}
key={tab.name}
className="text-xl font-bold mt-4"
>
{capitalize(tab.name)}
</Button>
);
})}
</div> </div>
);
} else {
return (
<div className="grid grid-rows p-4">
<Card radius="lg" shadow="none">
<div className="p-4">
<img className="w-full rounded-xl" src={channel.bannerUrl} />
</div>
<CardFooter className="p-4 justify-between ">
<div className="flex flex-col">
<div className="flex flex-row gap-2 text-xl font-bold pl-2">
{channel.name}
</div>
</div>
</CardFooter>
</Card>
{tabId !== "videos" ? ( <div className="flex flex-row flex-wrap gap-2 mt-4">
<VideoContainer> <Button
{tab?.content.map((video) => { onClick={() => {
if (video.type === "stream") { setSearchParams({ tabId: "videos" });
video = video as Video; }}
return ( key="videos"
<VideoComponent className="text-xl font-bold mt-4"
video={video} >
key={video.url} Videos
uploaderAvatar={channel.avatarUrl} </Button>
/> {channel.tabs.map((tab, index) => {
); return (
} else { <Button
return ( onClick={() => {
<div className="" key={Math.random()}> setSearchParams({ tabId: String(index) });
Soon...
</div> this.setState({
); ...this.state,
} tab: undefined,
});
}}
key={tab.name}
className="text-xl font-bold mt-4"
>
{capitalize(tab.name)}
</Button>
);
})} })}
</VideoContainer> </div>
) : (
<VideoContainer> {tabId !== "videos" ? (
{channel.relatedStreams.map((video) => ( <VideoContainer>
<VideoComponent {tab?.content.map((video) => {
video={video} if (video.type === "stream") {
key={video.url} video = video as Video;
uploaderAvatar={channel.avatarUrl} return (
/> <VideoComponent
))} video={video}
</VideoContainer> key={video.url}
)} uploaderAvatar={channel.avatarUrl}
</div> />
); );
} else {
return (
<div className="" key={Math.random()}>
Soon...
</div>
);
}
})}
</VideoContainer>
) : (
<VideoContainer>
{channel.relatedStreams.map((video) => (
<VideoComponent
video={video}
key={video.url}
uploaderAvatar={channel.avatarUrl}
/>
))}
</VideoContainer>
)}
</div>
);
}
} }
} }

View file

@ -1,36 +1,39 @@
import { Video } from "piped-api/dist/types"; import { Video } from "piped-api/dist/types";
import { useEffect, useState } from "react";
import { SkeletonVideoComponent, VideoComponent } from "../components/video"; import { SkeletonVideoComponent, VideoComponent } from "../components/video";
import React from "react";
export default function TrendingPage() { export default class TrendingPage extends React.Component {
const [trending, setTrending] = useState([] as Video[]); state: { trending: Video[] } = {
trending: [],
};
useEffect(() => { async componentDidMount() {
async function getTrending() { console.log("trending");
const trending = await window.piped_api.trending("US"); const trending = await window.piped_api.trending(
setTrending(trending); localStorage.getItem("region") || "US"
} );
this.setState({ trending });
}
render() {
const { trending } = this.state;
if (trending.length === 0) { if (trending.length === 0) {
getTrending(); return (
<div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4">
{[...Array(20).keys()].map((num) => (
<SkeletonVideoComponent key={num} />
))}
</div>
);
} }
});
if (trending.length === 0) {
return ( return (
<div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4"> <div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4">
{[...Array(20).keys()].map((num) => ( {trending.map((video) => (
<SkeletonVideoComponent key={num} /> <VideoComponent video={video} key={video.url} />
))} ))}
</div> </div>
); );
} }
return (
<div className="grid md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 gap-2 p-4">
{trending.map((video) => (
<VideoComponent video={video} key={video.url} />
))}
</div>
);
} }