mirror of
https://github.com/tubearchivist/tubearchivist-frontend.git
synced 2024-12-22 09:50:15 +00:00
chore: more code cleanup and use better env vars
This commit is contained in:
parent
526c98ca8a
commit
df30173ba3
@ -3,15 +3,17 @@ import NextImage from "next/image";
|
||||
import { useState } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import IconPlay from "../../images/icon-play.svg";
|
||||
import { TA_BASE_URL } from "../../lib/constants";
|
||||
import { getTAUrl } from "../../lib/constants";
|
||||
import { getVideos } from "../../lib/getVideos";
|
||||
import type { Datum } from "../../types/video";
|
||||
import type { Data } from "../../types/video";
|
||||
import VideoPlayer from "../VideoPlayer";
|
||||
|
||||
type ViewStyle = "grid" | "list";
|
||||
|
||||
const TA_BASE_URL = getTAUrl();
|
||||
|
||||
const VideoList = () => {
|
||||
const [selectedVideoUrl, setSelectedVideoUrl] = useState<Datum>();
|
||||
const [selectedVideoUrl, setSelectedVideoUrl] = useState<Data>();
|
||||
const [viewStyle, setViewStyle] = useState<ViewStyle>("grid");
|
||||
const { data: session } = useSession();
|
||||
const { data, error, isLoading } = useQuery(
|
||||
@ -22,7 +24,7 @@ const VideoList = () => {
|
||||
}
|
||||
);
|
||||
|
||||
const handleSelectedVideo = (video: Datum) => {
|
||||
const handleSelectedVideo = (video: Data) => {
|
||||
setSelectedVideoUrl(video);
|
||||
};
|
||||
|
||||
@ -51,7 +53,7 @@ const VideoList = () => {
|
||||
<>
|
||||
<VideoPlayer
|
||||
handleRemoveVideoPlayer={handleRemoveVideoPlayer}
|
||||
selectedVideoUrl={selectedVideoUrl}
|
||||
selectedVideo={selectedVideoUrl}
|
||||
/>
|
||||
|
||||
<div className="boxed-content">
|
||||
@ -135,10 +137,10 @@ const VideoList = () => {
|
||||
<div className="video-thumb-wrap list">
|
||||
<div className="video-thumb">
|
||||
<NextImage
|
||||
src={`${TA_BASE_URL}/cache/${video.vid_thumb_url}`}
|
||||
src={`${TA_BASE_URL.client}/cache/${video.vid_thumb_url}`}
|
||||
alt="video-thumb"
|
||||
width={325}
|
||||
height={190}
|
||||
width={640}
|
||||
height={360}
|
||||
blurDataURL={video.vid_thumb_base64}
|
||||
placeholder="blur"
|
||||
/>
|
||||
|
@ -1,14 +1,28 @@
|
||||
import NextImage from "next/image";
|
||||
import NextLink from "next/link";
|
||||
import ReactPlayer from "react-player";
|
||||
import IconClose from "../../images/icon-close.svg";
|
||||
import { TA_BASE_URL } from "../../lib/constants";
|
||||
import { formatNumbers } from "../../lib/utils";
|
||||
import IconClose from "../../images/icon-close.svg";
|
||||
import { Data } from "../../types/video";
|
||||
|
||||
const VideoPlayer = ({ selectedVideoUrl, handleRemoveVideoPlayer }) => {
|
||||
if (!selectedVideoUrl) return;
|
||||
type VideoPlayerProps = {
|
||||
selectedVideo: Data;
|
||||
handleRemoveVideoPlayer?: () => void;
|
||||
isHome?: boolean;
|
||||
showStats?: boolean;
|
||||
};
|
||||
|
||||
const VideoPlayer = ({
|
||||
selectedVideo,
|
||||
handleRemoveVideoPlayer,
|
||||
isHome = true,
|
||||
showStats = true,
|
||||
}: VideoPlayerProps) => {
|
||||
if (!selectedVideo) return;
|
||||
return (
|
||||
<>
|
||||
{selectedVideoUrl && (
|
||||
{selectedVideo && (
|
||||
<div className="player-wrapper">
|
||||
<div className="video-player">
|
||||
<ReactPlayer
|
||||
@ -18,44 +32,50 @@ const VideoPlayer = ({ selectedVideoUrl, handleRemoveVideoPlayer }) => {
|
||||
light={false}
|
||||
playing // TODO: Not currently working
|
||||
playsinline
|
||||
url={`${TA_BASE_URL}/media/${selectedVideoUrl?.media_url}`}
|
||||
url={
|
||||
isHome
|
||||
? `${TA_BASE_URL}/media/${selectedVideo?.media_url}`
|
||||
: `${TA_BASE_URL}/${selectedVideo?.media_url}`
|
||||
}
|
||||
/>
|
||||
<div className="player-title boxed-content">
|
||||
<NextImage
|
||||
className="close-button"
|
||||
src={IconClose}
|
||||
width={30}
|
||||
height={30}
|
||||
alt="close-icon"
|
||||
onClick={handleRemoveVideoPlayer}
|
||||
title="Close player"
|
||||
/>
|
||||
{/* ${watchStatusIndicator}
|
||||
${castButton}
|
||||
*/}
|
||||
<div className="thumb-icon player-stats">
|
||||
<img src="/img/icon-eye.svg" alt="views icon" />
|
||||
<span>
|
||||
{formatNumbers(selectedVideoUrl.stats.view_count.toString())}
|
||||
</span>
|
||||
<span>|</span>
|
||||
<img src="/img/icon-thumb.svg" alt="thumbs-up" />
|
||||
<span>
|
||||
{formatNumbers(selectedVideoUrl.stats.like_count.toString())}
|
||||
</span>
|
||||
</div>
|
||||
<div className="player-channel-playlist">
|
||||
<h3>
|
||||
<a href="/channel/${channelId}/">
|
||||
{selectedVideoUrl.channel.channel_name}
|
||||
<SponsorBlock />
|
||||
{showStats ? (
|
||||
<div className="player-title boxed-content">
|
||||
<NextImage
|
||||
className="close-button"
|
||||
src={IconClose}
|
||||
width={30}
|
||||
height={30}
|
||||
alt="close-icon"
|
||||
onClick={handleRemoveVideoPlayer}
|
||||
title="Close player"
|
||||
/>
|
||||
<div className="thumb-icon player-stats">
|
||||
<img src="/img/icon-eye.svg" alt="views icon" />
|
||||
<span>
|
||||
{formatNumbers(selectedVideo.stats.view_count.toString())}
|
||||
</span>
|
||||
<span>|</span>
|
||||
<img src="/img/icon-thumb.svg" alt="thumbs-up" />
|
||||
<span>
|
||||
{formatNumbers(selectedVideo.stats.like_count.toString())}
|
||||
</span>
|
||||
</div>
|
||||
<div className="player-channel-playlist">
|
||||
<h3>
|
||||
<a href="/channel/${channelId}/">
|
||||
{selectedVideo.channel.channel_name}
|
||||
</a>
|
||||
</h3>
|
||||
{/* ${playlist} */}
|
||||
</div>
|
||||
<NextLink href={`/video/${selectedVideo.youtube_id}/`}>
|
||||
<a>
|
||||
<h2 id="video-title">{selectedVideo.title}</h2>
|
||||
</a>
|
||||
</h3>
|
||||
{/* ${playlist} */}
|
||||
</NextLink>
|
||||
</div>
|
||||
<a href="/video/${videoId}/">
|
||||
<h2 id="video-title">{selectedVideoUrl.title}</h2>
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@ -64,3 +84,45 @@ const VideoPlayer = ({ selectedVideoUrl, handleRemoveVideoPlayer }) => {
|
||||
};
|
||||
|
||||
export default VideoPlayer;
|
||||
|
||||
function SponsorBlock() {
|
||||
return (
|
||||
<>
|
||||
{/* <div className="notifications" id="notifications"></div> */}
|
||||
<div className="sponsorblock" id="sponsorblock">
|
||||
{/* {% if video.sponsorblock.is_enabled %} */}
|
||||
{/* {% if video.sponsorblock.segments|length == 0 %} */}
|
||||
<h4>
|
||||
This video doesn't have any sponsor segments added. To add a
|
||||
segment go to{" "}
|
||||
<u>
|
||||
<a href="https://www.youtube.com/watch?v={{ video.youtube_id }}">
|
||||
this video on YouTube
|
||||
</a>
|
||||
</u>{" "}
|
||||
and add a segment using the{" "}
|
||||
<u>
|
||||
<a href="https://sponsor.ajay.app/">SponsorBlock</a>
|
||||
</u>{" "}
|
||||
extension.
|
||||
</h4>
|
||||
{/* {% elif video.sponsorblock.has_unlocked %} */}
|
||||
<h4>
|
||||
This video has unlocked sponsor segments. Go to{" "}
|
||||
<u>
|
||||
<a href="https://www.youtube.com/watch?v={{ video.youtube_id }}">
|
||||
this video on YouTube
|
||||
</a>
|
||||
</u>{" "}
|
||||
and vote on the segments using the{" "}
|
||||
<u>
|
||||
<a href="https://sponsor.ajay.app/">SponsorBlock</a>
|
||||
</u>{" "}
|
||||
extension.
|
||||
</h4>
|
||||
{/* {% endif %} */}
|
||||
{/* {% endif %} */}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1 +1,12 @@
|
||||
export const TA_BASE_URL = process.env.NEXT_PUBLIC_TUBEARCHIVIST_URL;
|
||||
export const getTAUrl = () => {
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
return {
|
||||
client: process.env.NEXT_PUBLIC_TUBEARCHIVIST_URL,
|
||||
server: process.env.NEXT_PUBLIC_TUBEARCHIVIST_URL,
|
||||
};
|
||||
}
|
||||
return {
|
||||
client: process.env.NEXT_PUBLIC_TUBEARCHIVIST_URL,
|
||||
server: process.env.TUBEARCHIVIST_URL,
|
||||
};
|
||||
};
|
||||
|
@ -1,8 +1,14 @@
|
||||
import { Channel } from "../types/channel";
|
||||
import { TA_BASE_URL } from "./constants";
|
||||
import { getTAUrl } from "./constants";
|
||||
|
||||
const TA_BASE_URL = getTAUrl();
|
||||
|
||||
export const getChannels = async (token: string): Promise<Channel> => {
|
||||
const response = await fetch(`${TA_BASE_URL}/api/channel/`, {
|
||||
if (!token) {
|
||||
throw new Error(`Unable to fetch channels, no token provided`);
|
||||
}
|
||||
|
||||
const response = await fetch(`${TA_BASE_URL.server}/api/channel/`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { Playlist } from "../types/playlist";
|
||||
import { Playlists } from "../types/playlists";
|
||||
import { TA_BASE_URL } from "./constants";
|
||||
|
||||
export const getPlaylists = async (token: string): Promise<Playlist> => {
|
||||
export const getPlaylists = async (token: string): Promise<Playlists> => {
|
||||
if (!token) {
|
||||
throw new Error(`No token provided when fetching a playlists`);
|
||||
}
|
||||
|
||||
const response = await fetch(`${TA_BASE_URL}/api/playlist/`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
@ -11,7 +16,35 @@ export const getPlaylists = async (token: string): Promise<Playlist> => {
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Error getting channel information");
|
||||
throw new Error(
|
||||
`Error getting playlists information: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const getPlaylist = async (
|
||||
token: string,
|
||||
playlistId: string
|
||||
): Promise<Playlist> => {
|
||||
if (!token) {
|
||||
throw new Error(
|
||||
`No token provided when fetching a playlist: ${playlistId}`
|
||||
);
|
||||
}
|
||||
|
||||
const response = await fetch(`${TA_BASE_URL}/api/playlist/${playlistId}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${token}`,
|
||||
mode: "no-cors",
|
||||
},
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Error getting playlists information: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
return response.json();
|
||||
};
|
||||
|
@ -1,11 +1,37 @@
|
||||
import { Videos } from "../types/video";
|
||||
import { TA_BASE_URL } from "./constants";
|
||||
import { Video } from "../types/video";
|
||||
import { Videos } from "../types/videos";
|
||||
import { getTAUrl } from "./constants";
|
||||
|
||||
const TA_BASE_URL = getTAUrl();
|
||||
|
||||
export const getVideos = async (token: string): Promise<Videos> => {
|
||||
if (!token) {
|
||||
throw new Error("Missing API token in request to get videos");
|
||||
}
|
||||
const response = await fetch(`${TA_BASE_URL}/api/video/`, {
|
||||
const response = await fetch(`${TA_BASE_URL.server}/api/video/`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${token}`,
|
||||
mode: "no-cors",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch videos");
|
||||
}
|
||||
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const getVideo = async (
|
||||
token: string,
|
||||
videoId: string
|
||||
): Promise<Video> => {
|
||||
if (!token) {
|
||||
throw new Error("Missing API token in request to get video");
|
||||
}
|
||||
const response = await fetch(`${TA_BASE_URL.server}/api/video/${videoId}`, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
|
@ -1,6 +1,8 @@
|
||||
import NextAuth from "next-auth";
|
||||
import CredentialsProvider from "next-auth/providers/credentials";
|
||||
import { TA_BASE_URL } from "../../../lib/constants";
|
||||
import { getTAUrl } from "../../../lib/constants";
|
||||
|
||||
const TA_BASE_URL = getTAUrl();
|
||||
|
||||
type TA_Token = {
|
||||
token: string;
|
||||
@ -30,7 +32,7 @@ export default NextAuth({
|
||||
password: credentials.password,
|
||||
};
|
||||
|
||||
const res = await fetch(`${TA_BASE_URL}/api/login/`, {
|
||||
const res = await fetch(`${TA_BASE_URL.server}/api/login/`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
headers: {
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { CustomHead } from "../../components/CustomHead";
|
||||
import { Layout } from "../../components/Layout";
|
||||
import NextImage from "next/image";
|
||||
import Logo from "../../images/logo-tube-archivist-dark.png";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import { NextPageContext } from "next";
|
||||
import { getCsrfToken } from "next-auth/react";
|
||||
import NextImage from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { CustomHead } from "../../components/CustomHead";
|
||||
import Logo from "../../images/logo-tube-archivist-dark.png";
|
||||
|
||||
export async function getServerSideProps(context: NextPageContext) {
|
||||
return {
|
||||
|
@ -4,9 +4,11 @@ import { useState } from "react";
|
||||
import { dehydrate, QueryClient, useQuery } from "react-query";
|
||||
import { CustomHead } from "../components/CustomHead";
|
||||
import { Layout } from "../components/Layout";
|
||||
import { TA_BASE_URL } from "../lib/constants";
|
||||
import { getTAUrl } from "../lib/constants";
|
||||
import { getChannels } from "../lib/getChannels";
|
||||
|
||||
const TA_BASE_URL = getTAUrl();
|
||||
|
||||
type ViewStyle = "grid" | "list";
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
@ -54,6 +56,23 @@ const Channel: NextPage = () => {
|
||||
setViewStyle(selectedViewStyle);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Loading...</h1>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Layout>
|
||||
<h1>Error</h1>
|
||||
<pre>{JSON.stringify(error, null, 2)}</pre>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<CustomHead title="Channels" />
|
||||
@ -128,7 +147,7 @@ const Channel: NextPage = () => {
|
||||
<div className={`channel-banner ${viewStyle}`}>
|
||||
<a href="{% url 'channel_id' channel.source.channel_id %}">
|
||||
<img
|
||||
src={`${TA_BASE_URL}${channel?.channel_banner_url}`}
|
||||
src={`${TA_BASE_URL.client}${channel?.channel_banner_url}`}
|
||||
alt="{{ channel.source.channel_id }}-banner"
|
||||
/>
|
||||
</a>
|
||||
@ -138,7 +157,7 @@ const Channel: NextPage = () => {
|
||||
<div className="round-img">
|
||||
<a href="{% url 'channel_id' channel.source.channel_id %}">
|
||||
<img
|
||||
src={`${TA_BASE_URL}${channel?.channel_thumb_url}`}
|
||||
src={`${TA_BASE_URL.client}${channel?.channel_thumb_url}`}
|
||||
alt="channel-thumb"
|
||||
/>
|
||||
</a>
|
||||
|
Loading…
Reference in New Issue
Block a user