From 8175a775c3707c95ea2eb83dbbc13d8bb9d7a730 Mon Sep 17 00:00:00 2001 From: an-lee Date: Mon, 17 Jun 2024 16:28:51 +0800 Subject: [PATCH] Feat: remember last active segment of audio/video (#681) * remember last segment index for each audio/video * fix for video * auto scroll to cached segment --- .../components/audios/audio-player.tsx | 21 ++++++++---- .../components/medias/media-transcription.tsx | 18 +++++++---- .../components/videos/video-player.tsx | 21 ++++++++---- .../context/media-player-provider.tsx | 32 ++++++++++++++++++- enjoy/tsconfig.json | 2 +- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/enjoy/src/renderer/components/audios/audio-player.tsx b/enjoy/src/renderer/components/audios/audio-player.tsx index dd43a773..55e72c3c 100644 --- a/enjoy/src/renderer/components/audios/audio-player.tsx +++ b/enjoy/src/renderer/components/audios/audio-player.tsx @@ -17,20 +17,29 @@ export const AudioPlayer = (props: { segmentIndex?: number; }) => { const { id, md5, segmentIndex } = props; - const { setMedia, layout, setCurrentSegmentIndex } = useContext( - MediaPlayerProviderContext - ); + const { + media, + setMedia, + layout, + setCurrentSegmentIndex, + getCachedSegmentIndex, + } = useContext(MediaPlayerProviderContext); const { audio } = useAudio({ id, md5 }); + const updateCurrentSegmentIndex = async () => { + let index = segmentIndex || (await getCachedSegmentIndex()); + setCurrentSegmentIndex(index); + }; + useEffect(() => { if (!audio) return; setMedia(audio); }, [audio]); useEffect(() => { - if (!segmentIndex) return; - setCurrentSegmentIndex(segmentIndex); - }, []); + if (!media) return; + updateCurrentSegmentIndex(); + }, [media]); if (!layout) return ; diff --git a/enjoy/src/renderer/components/medias/media-transcription.tsx b/enjoy/src/renderer/components/medias/media-transcription.tsx index 7418e3d3..37bba283 100644 --- a/enjoy/src/renderer/components/medias/media-transcription.tsx +++ b/enjoy/src/renderer/components/medias/media-transcription.tsx @@ -32,6 +32,7 @@ import { MediaTranscriptionReadButton } from "./media-transcription-read-button" export const MediaTranscription = () => { const containerRef = useRef(); const { + decoded, media, currentSegmentIndex, wavesurfer, @@ -83,14 +84,17 @@ export const MediaTranscription = () => { useEffect(() => { if (!containerRef?.current) return; + if (!decoded) return; - containerRef.current - ?.querySelector(`#segment-${currentSegmentIndex}`) - ?.scrollIntoView({ - block: "center", - inline: "center", - } as ScrollIntoViewOptions); - }, [currentSegmentIndex, transcription, containerRef]); + setTimeout(() => { + containerRef.current + ?.querySelector(`#segment-${currentSegmentIndex}`) + ?.scrollIntoView({ + block: "center", + inline: "center", + } as ScrollIntoViewOptions); + }, 300); + }, [decoded, currentSegmentIndex, transcription, containerRef]); if (!transcription?.result?.timeline) { return null; diff --git a/enjoy/src/renderer/components/videos/video-player.tsx b/enjoy/src/renderer/components/videos/video-player.tsx index 02d71460..ea8c8eba 100644 --- a/enjoy/src/renderer/components/videos/video-player.tsx +++ b/enjoy/src/renderer/components/videos/video-player.tsx @@ -17,11 +17,20 @@ export const VideoPlayer = (props: { segmentIndex?: number; }) => { const { id, md5, segmentIndex } = props; - const { setMedia, layout, setCurrentSegmentIndex } = useContext( - MediaPlayerProviderContext - ); + const { + media, + setMedia, + layout, + setCurrentSegmentIndex, + getCachedSegmentIndex, + } = useContext(MediaPlayerProviderContext); const { video } = useVideo({ id, md5 }); + const updateCurrentSegmentIndex = async () => { + let index = segmentIndex || (await getCachedSegmentIndex()); + setCurrentSegmentIndex(index); + }; + useEffect(() => { if (!video) return; @@ -29,9 +38,9 @@ export const VideoPlayer = (props: { }, [video]); useEffect(() => { - if (!segmentIndex) return; - setCurrentSegmentIndex(segmentIndex); - }, []); + if (!media) return; + updateCurrentSegmentIndex(); + }, [media]); if (!layout) return ; diff --git a/enjoy/src/renderer/context/media-player-provider.tsx b/enjoy/src/renderer/context/media-player-provider.tsx index bfa84d8f..e1cc313a 100644 --- a/enjoy/src/renderer/context/media-player-provider.tsx +++ b/enjoy/src/renderer/context/media-player-provider.tsx @@ -91,6 +91,8 @@ type MediaPlayerContextType = { createSegment: () => Promise; // remote config ipaMappings: { [key: string]: string }; + getCachedSegmentIndex: () => Promise; + setCachedSegmentIndex: (index: number) => void; }; export const MediaPlayerProviderContext = @@ -191,6 +193,25 @@ export const MediaPlayerProvider = ({ segmentIndex: currentSegmentIndex, }); + const getCachedSegmentIndex = async () => { + if (!media) return; + + const index = await EnjoyApp.cacheObjects.get( + `${media.mediaType.toLowerCase()}-${media.id}-last-segment-index` + ); + + return index || 0; + }; + + const setCachedSegmentIndex = (index: number) => { + if (!media) return; + + return EnjoyApp.cacheObjects.set( + `${media.mediaType.toLowerCase()}-${media.id}-last-segment-index`, + index + ); + }; + const { notes, createNote } = useNotes({ targetId: segment?.id, targetType: "Segment", @@ -428,7 +449,6 @@ export const MediaPlayerProvider = ({ setCurrentTime(0); const subscriptions = [ - wavesurfer.on("loading", (percent: number) => console.log(`${percent}%`)), wavesurfer.on("timeupdate", (time: number) => setCurrentTime(time)), wavesurfer.on("decode", () => { const peaks: Float32Array = wavesurfer @@ -555,6 +575,14 @@ export const MediaPlayerProvider = ({ }; }, []); + /* cache last segment index */ + useEffect(() => { + if (!media) return; + if (!currentSegmentIndex) return; + + setCachedSegmentIndex(currentSegmentIndex); + }, [currentSegmentIndex]); + return ( <> {children} diff --git a/enjoy/tsconfig.json b/enjoy/tsconfig.json index 63bf0480..138d3867 100644 --- a/enjoy/tsconfig.json +++ b/enjoy/tsconfig.json @@ -9,7 +9,7 @@ "sourceMap": true, "baseUrl": ".", "outDir": "dist", - "moduleResolution": "Bundler", + "moduleResolution": "node", "resolveJsonModule": true, "jsx": "react-jsx", "paths": {