From 14172f9dd64ce91ba5cf51f82c53deb6a81d68a6 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Wed, 3 Jun 2026 17:22:48 -0700 Subject: create daily/unlimited mode, CDN audio file for daily mode --- src/components/Player/index.tsx | 137 ++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 48 deletions(-) (limited to 'src/components/Player/index.tsx') diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index fcfce72..e4dfd9e 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -1,101 +1,142 @@ import React from "react"; -import YouTube from "react-youtube"; import { IoPlay, IoPause } from "react-icons/io5"; import { playTimes } from "../../constants"; - -import * as Styled from "./index.styled"; +import * as Styled from "../YTPlayer/index.styled"; interface Props { - id: string; currentTry: number; } -export function Player({ id, currentTry }: Props) { - const opts = { - width: "0", - height: "0", - }; +const MAX_TIME = 16; - // react-youtube doesn't export types for this - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const playerRef = React.useRef(null); +export function Player({ currentTry }: Props) { + const audioRef = React.useRef(null); const currentPlayTime = playTimes[currentTry]; - const [play, setPlay] = React.useState(false); + const [play, setPlay] = React.useState(false); + const [currentTime, setCurrentTime] = React.useState(0); + const [isReady, setIsReady] = React.useState(false); - const [currentTime, setCurrentTime] = React.useState(0); + const CDN_URL = + import.meta.env.VITE_CDN_URL || "https://yena.pinapelz.com/kheardle"; - const [isReady, setIsReady] = React.useState(false); + const dateString = new Date().toISOString().split("T")[0]; - React.useEffect(() => { - setInterval(() => { - playerRef.current?.internalPlayer - .getCurrentTime() - .then((time: number) => { - setCurrentTime(time); - }); - }, 250); + const startPlayback = React.useCallback(() => { + const audio = audioRef.current; + if (!audio) return; + + audio.play(); + setPlay(true); + }, []); + + const stopPlayback = React.useCallback(() => { + const audio = audioRef.current; + if (!audio) return; + + audio.pause(); + audio.currentTime = 0; + setPlay(false); }, []); React.useEffect(() => { - if (play) { - if (currentTime * 1000 >= currentPlayTime) { - playerRef.current?.internalPlayer.pauseVideo(); - playerRef.current?.internalPlayer.seekTo(0); + const audio = new Audio(`${CDN_URL}/${dateString}.mp3`); + audioRef.current = audio; + + audio.addEventListener("loadeddata", () => { + setIsReady(true); + }); + + audio.addEventListener("timeupdate", () => { + setCurrentTime(audio.currentTime); + }); + + audio.addEventListener("ended", () => { + setPlay(false); + audio.currentTime = 0; + }); + + return () => { + audio.pause(); + audio.src = ""; + }; + }, [dateString]); + + React.useEffect(() => { + if (!play || !audioRef.current) return; + + const interval = setInterval(() => { + const a = audioRef.current!; + const t = a.currentTime * 1000; + + setCurrentTime(a.currentTime); + + if (t >= currentPlayTime || t >= MAX_TIME * 1000) { + a.pause(); + a.currentTime = 0; setPlay(false); } - } - }, [play, currentTime]); + }, 100); - // don't call play video each time currentTime changes - const startPlayback = React.useCallback(() => { - playerRef.current?.internalPlayer.playVideo(); - setPlay(true); - }, []); + return () => clearInterval(interval); + }, [play, currentPlayTime]); + + React.useEffect(() => { + if (!("mediaSession" in navigator)) return; + + navigator.mediaSession.setActionHandler("play", () => undefined); + navigator.mediaSession.setActionHandler("pause", () => undefined); + navigator.mediaSession.setActionHandler("previoustrack", () => undefined); + navigator.mediaSession.setActionHandler("nexttrack", () => undefined); - const setReady = React.useCallback(() => { - setIsReady(true); + return () => { + navigator.mediaSession.setActionHandler("play", null); + navigator.mediaSession.setActionHandler("pause", null); + navigator.mediaSession.setActionHandler("previoustrack", null); + navigator.mediaSession.setActionHandler("nexttrack", null); + }; }, []); return ( <> - {isReady ? ( <> - {currentTime !== 0 && } - {playTimes.map((playTime) => ( + {currentTime !== 0 && ( + + )} + + {playTimes.map((t) => ( ))} + 1s 16s - {!play && ( + + {!play ? ( - )} - {play && ( + ) : ( )} ) : ( -

Loading player...

+

Loading audio...

)} ); -- cgit v1.2.3