From 18eb1371c6e0da645ab2b519afa5f195912cae7d Mon Sep 17 00:00:00 2001 From: Haoyu Xu Date: Fri, 3 Mar 2023 16:20:36 -0500 Subject: [PATCH] fix(directory): fixed issues related to voice and vcs --- changelogs.yaml | 2 + directory/Version | 2 +- directory/src/libs/stable_navigate.jsx | 30 ----- directory/src/libs/voice.jsx | 63 +++++++++++ directory/src/routes/path/home.jsx | 54 +++------ directory/src/routes/path/operator.jsx | 148 ++++++++++++++----------- src/components/player.js | 2 +- 7 files changed, 168 insertions(+), 133 deletions(-) delete mode 100644 directory/src/libs/stable_navigate.jsx create mode 100644 directory/src/libs/voice.jsx diff --git a/changelogs.yaml b/changelogs.yaml index 7e4bae7..9ee50b5 100644 --- a/changelogs.yaml +++ b/changelogs.yaml @@ -36,6 +36,8 @@ showcase: 2021/05/26: - First commit directory: + 2023/03/03: + - Fixed Voice and VCs issues 2023/03/02: - Added Voice, VCs, Operator Logo 2023/03/01: diff --git a/directory/Version b/directory/Version index dc2c2a7..aa0ea79 100644 --- a/directory/Version +++ b/directory/Version @@ -1 +1 @@ -0.5.28 \ No newline at end of file +0.5.29 \ No newline at end of file diff --git a/directory/src/libs/stable_navigate.jsx b/directory/src/libs/stable_navigate.jsx deleted file mode 100644 index 2c92737..0000000 --- a/directory/src/libs/stable_navigate.jsx +++ /dev/null @@ -1,30 +0,0 @@ -// taken from: https://shallowdepth.online/posts/2022/04/why-usenavigate-hook-in-react-router-v6-triggers-waste-re-renders-and-how-to-solve-it/ -import { createContext, useContext, useRef } from 'react' -import { useNavigate } from 'react-router-dom' - -const StableNavigateContext = createContext(null) - -const StableNavigateContextProvider = ({ children }) => { - const navigate = useNavigate() - const navigateRef = useRef(navigate) - - return ( - - {children} - - ) -} - -const useStableNavigate = () => { - const navigateRef = useContext(StableNavigateContext) - if (navigateRef.current === null) - throw new Error('StableNavigate context is not initialized') - - return navigateRef.current -} - -export { - StableNavigateContext, - StableNavigateContextProvider, - useStableNavigate, -} \ No newline at end of file diff --git a/directory/src/libs/voice.jsx b/directory/src/libs/voice.jsx new file mode 100644 index 0000000..dbe0152 --- /dev/null +++ b/directory/src/libs/voice.jsx @@ -0,0 +1,63 @@ +import { + useState, + useEffect, + useRef, +} from "react" +import { useCallback } from "react" +const audioEl = new Audio() + +export default function useAudio() { + const [isPlaying, _setIsPlaying] = useState(false) + const isPlayingRef = useRef(isPlaying) + const setIsPlaying = (data) => { + isPlayingRef.current = data + _setIsPlaying(data) + } + + useEffect(() => { + audioEl.addEventListener('ended', () => setIsPlaying(false)) + return () => { + audioEl.removeEventListener('ended', () => setIsPlaying(false)) + } + }, []) + + const play = useCallback( + ( + link, + options = { + overwrite: false + }, + callback = () => { } + ) => { + if (!options.overwrite && audioEl.src === (window.location.href.replace(/\/$/g, '') + link)) return + audioEl.src = link + let startPlayPromise = audioEl.play() + if (startPlayPromise !== undefined) { + setIsPlaying(true) + startPlayPromise + .then(() => { + callback() + return + }) + .catch(() => { + return + }) + } + }, []) + + const stop = useCallback(() => { + audioEl.pause() + setIsPlaying(false) + }, []) + + const getSrc = useCallback(() => audioEl.src, []) + + return { + play, + stop, + getSrc, + isPlaying, + isPlayingRef, + } + +} \ No newline at end of file diff --git a/directory/src/routes/path/home.jsx b/directory/src/routes/path/home.jsx index d4c4bd1..42f2a67 100644 --- a/directory/src/routes/path/home.jsx +++ b/directory/src/routes/path/home.jsx @@ -15,47 +15,15 @@ import { } from '@/state/language' import { useHeader } from '@/state/header'; import { useAppbar } from '@/state/appbar'; +import useAudio from '@/libs/voice'; import { useAtom } from 'jotai' -import { atom } from 'jotai'; +import { atomWithStorage } from 'jotai/utils'; import CharIcon from '@/component/char_icon'; import MainBorder from '@/component/main_border'; import useUmami from '@parcellab/react-use-umami'; import Switch from '@/component/switch'; -const audioEl = new Audio() -let isPlaying = false -let voiceOnState = false -const voiceOnStateAtom = atom(voiceOnState) -const voiceOnAtom = atom( - (get) => get(voiceOnStateAtom), - (get, set, newState) => { - voiceOnState = newState - set(voiceOnStateAtom, voiceOnState) - // you can set as many atoms as you want at the same time - } -) - -const playVoice = (link) => { - const audioUrl = `/${link}/assets/${JSON.parse(import.meta.env.VITE_VOICE_FOLDERS).main}/${import.meta.env.VITE_APP_VOICE_URL}` - if (!voiceOnState || (audioEl.src === (window.location.href.replace(/\/$/g, '') + audioUrl) && isPlaying)) return - audioEl.src = audioUrl - let startPlayPromise = audioEl.play() - if (startPlayPromise !== undefined) { - startPlayPromise - .then(() => { - isPlaying = true - const audioEndedFunc = () => { - audioEl.removeEventListener('ended', audioEndedFunc) - isPlaying = false - } - audioEl.addEventListener('ended', audioEndedFunc) - }) - .catch((e) => { - console.log(e) - return - }) - } -} +const voiceOnAtom = atomWithStorage('voiceOn', false) export default function Home() { // eslint-disable-next-line no-unused-vars @@ -68,6 +36,7 @@ export default function Home() { } = useHeader() const { config } = useConfig() const [content, setContent] = useState([]) + const { stop } = useAudio() useEffect(() => { setTitle('dynamic_compile') @@ -79,7 +48,8 @@ export default function Home() { key: 'skin' }]) setHeaderIcon(null) - }, [setHeaderIcon, setTabs, setTitle]) + stop() + }, [setHeaderIcon, setTabs, setTitle, stop]) useEffect(() => { setContent(config?.operators || []) @@ -100,7 +70,6 @@ export default function Home() {