aboutsummaryrefslogtreecommitdiffstats
path: root/pages
diff options
context:
space:
mode:
Diffstat (limited to 'pages')
-rw-r--r--pages/404.tsx21
-rw-r--r--pages/_app.tsx10
-rw-r--r--pages/index.tsx185
3 files changed, 216 insertions, 0 deletions
diff --git a/pages/404.tsx b/pages/404.tsx
new file mode 100644
index 0000000..93eabab
--- /dev/null
+++ b/pages/404.tsx
@@ -0,0 +1,21 @@
+import React from "react";
+import Head from "next/head";
+import PageBase from "../modules/PageBase";
+
+const NotFoundPage = () => {
+ return (
+ <PageBase>
+ <Head>
+ <title>404 - Ragtag Archive</title>
+ </Head>
+ <div>
+ <div className="px-4">
+ <h1 className="text-3xl mt-16 text-center">404</h1>
+ <p className="text-lg text-center mb-16">Page not found</p>
+ </div>
+ </div>
+ </PageBase>
+ );
+};
+
+export default NotFoundPage;
diff --git a/pages/_app.tsx b/pages/_app.tsx
new file mode 100644
index 0000000..27c48fc
--- /dev/null
+++ b/pages/_app.tsx
@@ -0,0 +1,10 @@
+import "../styles/tailwind.css";
+import "../styles/player.css";
+
+function MyApp({ Component, pageProps }) {
+ return (
+ <Component {...pageProps} />
+ );
+}
+
+export default MyApp;
diff --git a/pages/index.tsx b/pages/index.tsx
new file mode 100644
index 0000000..316e16a
--- /dev/null
+++ b/pages/index.tsx
@@ -0,0 +1,185 @@
+import React from "react";
+import Head from "next/head";
+import ChatReplayPanel from "../modules/ChatReplay/ChatReplayPanel";
+import { useWindowSize } from "../modules/hooks/useWindowSize";
+import PageBase from "../modules/PageBase";
+import VideoPlayer2 from "../modules/VideoPlayer/VideoPlayer2";
+import { buttonStyle } from "../modules/VideoActionButtons";
+import { IconCheck } from "../modules/icons";
+
+const CustomPlayerPage = () => {
+ const [isChatVisible, setIsChatVisible] = React.useState(false);
+ const { innerWidth, innerHeight } = useWindowSize();
+ const [playbackProgress, setPlaybackProgress] = React.useState(0);
+ const [urlVideo, setUrlVideo] = React.useState("");
+ const [urlChat, setUrlChat] = React.useState("");
+ const [urlYtt, setUrlYtt] = React.useState("");
+ const [showPlayer, setShowPlayer] = React.useState(false);
+
+ const handleFile = (
+ e: React.ChangeEvent<HTMLInputElement>,
+ setter: (newValue: string) => any
+ ) => {
+ const file = e.target.files?.[0];
+ if (!file) {
+ console.error("No file selected");
+ return false;
+ }
+ const url = URL.createObjectURL(file).toString();
+ console.log(url);
+ setter(url);
+ };
+
+ return (
+ <PageBase>
+ <Head>
+ <title>Custom Player - Ragtag Archive</title>
+ </Head>
+ {showPlayer ? (
+ <div>
+ <div
+ className={["flex lg:flex-row flex-col lg:h-auto"].join(" ")}
+ style={{
+ height: isChatVisible && innerWidth < 640 ? innerHeight : "auto",
+ }}
+ >
+ <div className="w-full lg:w-3/4">
+ <div
+ className="relative bg-gray-400 w-full h-0"
+ style={{ paddingBottom: "56.25%" }}
+ >
+ <div className="absolute inset-0 w-full h-full">
+ <VideoPlayer2
+ key={urlVideo}
+ videoId="custom"
+ srcVideo={urlVideo}
+ srcAudio={urlVideo}
+ captions={
+ urlYtt
+ ? [
+ {
+ lang: "en",
+ src: urlYtt,
+ },
+ ]
+ : undefined
+ }
+ onPlaybackProgress={setPlaybackProgress}
+ />
+ </div>
+ </div>
+ </div>
+ <div
+ className={[
+ "w-full lg:w-1/4 lg:pl-4",
+ isChatVisible ? "flex-1" : "",
+ ].join(" ")}
+ >
+ {!urlChat ? (
+ <div className="border border-gray-800 rounded p-4 text-center">
+ <p>Chat replay unavailable</p>
+ </div>
+ ) : (
+ <ChatReplayPanel
+ src={urlChat}
+ currentTimeSeconds={playbackProgress}
+ onChatToggle={setIsChatVisible}
+ />
+ )}
+ </div>
+ </div>
+ <button
+ type="button"
+ className={[buttonStyle, "mt-4"].join(" ")}
+ onClick={() => setShowPlayer(false)}
+ >
+ Go back
+ </button>
+ </div>
+ ) : (
+ <div>
+ <div className="px-4 pb-8">
+ <h1 className="text-3xl mt-16 text-center">Custom Video Player</h1>
+ <p className="text-lg text-center">
+ You can play locally-saved video files and chat replay JSON
+ </p>
+ <p className="text-center">
+ Chat replay compatible with output from{" "}
+ <a
+ className="underline"
+ href="https://github.com/yt-dlp/yt-dlp"
+ target="_blank"
+ rel="noreferrer noopener nofollow"
+ >
+ yt-dlp
+ </a>
+ {" and "}
+ <a
+ className="underline"
+ href="https://pypi.org/project/chat-downloader/"
+ target="_blank"
+ rel="noreferrer noopener nofollow"
+ >
+ chat-downloader
+ </a>
+ .
+ </p>
+ </div>
+ <div className="mx-auto max-w-md">
+ <form>
+ <label
+ className={[buttonStyle, "relative cursor-pointer"].join(" ")}
+ >
+ <span>Select video</span>
+ <span className="ml-auto">
+ {urlVideo ? <IconCheck width="1em" height="1em" /> : null}
+ </span>
+ <input
+ type="file"
+ className="hidden"
+ onChange={(e) => handleFile(e, setUrlVideo)}
+ />
+ </label>
+ <label
+ className={[buttonStyle, "relative cursor-pointer"].join(" ")}
+ >
+ <span>Select chat json</span>
+ <span className="ml-auto">
+ {urlChat ? <IconCheck width="1em" height="1em" /> : null}
+ </span>
+ <input
+ type="file"
+ className="hidden"
+ onChange={(e) => handleFile(e, setUrlChat)}
+ />
+ </label>
+ <label
+ className={[buttonStyle, "relative cursor-pointer"].join(" ")}
+ >
+ <span>Select captions (srv3)</span>
+ <span className="ml-auto">
+ {urlYtt ? <IconCheck width="1em" height="1em" /> : null}
+ </span>
+ <input
+ type="file"
+ className="hidden"
+ onChange={(e) => handleFile(e, setUrlYtt)}
+ />
+ </label>
+
+ <button
+ type="button"
+ className={[buttonStyle, "mt-8 ml-auto"].join(" ")}
+ onClick={() => setShowPlayer(true)}
+ >
+ Launch player
+ </button>
+ </form>
+ </div>
+ </div>
+ )}
+ </PageBase>
+ );
+};
+
+export default CustomPlayerPage;
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage