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
This commit is contained in:
an-lee
2024-06-17 16:28:51 +08:00
committed by GitHub
parent e00ac27670
commit 8175a775c3
5 changed files with 73 additions and 21 deletions

View File

@@ -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 <LoaderSpin />;

View File

@@ -32,6 +32,7 @@ import { MediaTranscriptionReadButton } from "./media-transcription-read-button"
export const MediaTranscription = () => {
const containerRef = useRef<HTMLDivElement>();
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;

View File

@@ -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 <LoaderSpin />;

View File

@@ -91,6 +91,8 @@ type MediaPlayerContextType = {
createSegment: () => Promise<SegmentType | void>;
// remote config
ipaMappings: { [key: string]: string };
getCachedSegmentIndex: () => Promise<number>;
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 (
<>
<MediaPlayerProviderContext.Provider
@@ -602,6 +630,8 @@ export const MediaPlayerProvider = ({
currentSegment: segment,
createSegment,
ipaMappings,
getCachedSegmentIndex,
setCachedSegmentIndex,
}}
>
{children}

View File

@@ -9,7 +9,7 @@
"sourceMap": true,
"baseUrl": ".",
"outDir": "dist",
"moduleResolution": "Bundler",
"moduleResolution": "node",
"resolveJsonModule": true,
"jsx": "react-jsx",
"paths": {