mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-13 05:59:58 +02:00
properly handle settings state on lyrics follow
This commit is contained in:
@@ -21,10 +21,14 @@ export interface UseLyricsAnimationEngineOptions {
|
||||
enabled?: boolean;
|
||||
followRef?: React.RefObject<boolean>;
|
||||
followScrollAlignmentRef?: React.RefObject<number>;
|
||||
fontSize?: number;
|
||||
gap?: number;
|
||||
lineIdPrefix: 'karaoke-line' | 'lyric';
|
||||
lineLeadTimeMsRef?: React.RefObject<number>;
|
||||
lyrics: SynchronizedLyrics;
|
||||
onLineActive?: (lineIndex: number) => void;
|
||||
paddingLeft?: number;
|
||||
paddingRight?: number;
|
||||
scrollContainerId: string;
|
||||
}
|
||||
|
||||
@@ -34,10 +38,14 @@ export const useLyricsAnimationEngine = ({
|
||||
enabled = true,
|
||||
followRef,
|
||||
followScrollAlignmentRef,
|
||||
fontSize,
|
||||
gap,
|
||||
lineIdPrefix,
|
||||
lineLeadTimeMsRef,
|
||||
lyrics,
|
||||
onLineActive,
|
||||
paddingLeft,
|
||||
paddingRight,
|
||||
scrollContainerId,
|
||||
}: UseLyricsAnimationEngineOptions) => {
|
||||
const internalAnimStateRef = useRef<AnimEngineState>(createAnimEngineState());
|
||||
@@ -83,6 +91,7 @@ export const useLyricsAnimationEngine = ({
|
||||
const recalculatePositions = useCallback(() => {
|
||||
if (lyricsDataRef.current) {
|
||||
recalculateLinePositions(lyricsDataRef.current);
|
||||
animStateRef.current.scroll.pendingScroll = true;
|
||||
animStateRef.current.scroll.wasUserScrolling = true;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- animStateRef is read via .current at call time
|
||||
@@ -149,20 +158,51 @@ export const useLyricsAnimationEngine = ({
|
||||
};
|
||||
}, [lyrics, enabled, rebuildLyricsData, reset]);
|
||||
|
||||
useEffect(() => {
|
||||
const frame = requestAnimationFrame(() => {
|
||||
recalculatePositions();
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(frame);
|
||||
};
|
||||
}, [fontSize, gap, paddingLeft, paddingRight, recalculatePositions]);
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
const observedElements = new Set<Element>();
|
||||
|
||||
const observer = new ResizeObserver(() => {
|
||||
recalculatePositions();
|
||||
});
|
||||
|
||||
observer.observe(container);
|
||||
const observeLayoutTargets = () => {
|
||||
if (!observedElements.has(container)) {
|
||||
observer.observe(container);
|
||||
observedElements.add(container);
|
||||
}
|
||||
|
||||
const content = container.firstElementChild;
|
||||
if (content && !observedElements.has(content)) {
|
||||
observer.observe(content);
|
||||
observedElements.add(content);
|
||||
}
|
||||
};
|
||||
|
||||
observeLayoutTargets();
|
||||
|
||||
const mutationObserver = new MutationObserver(() => {
|
||||
observeLayoutTargets();
|
||||
});
|
||||
mutationObserver.observe(container, { childList: true });
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
mutationObserver.disconnect();
|
||||
};
|
||||
}, [containerRef, recalculatePositions]);
|
||||
|
||||
|
||||
@@ -94,9 +94,13 @@ export const SynchronizedKaraokeLyrics = ({
|
||||
containerRef,
|
||||
followRef,
|
||||
followScrollAlignmentRef,
|
||||
fontSize: settings.fontSize,
|
||||
gap: settings.gap,
|
||||
lineIdPrefix: 'karaoke-line',
|
||||
lineLeadTimeMsRef,
|
||||
lyrics: normalizedLyrics,
|
||||
paddingLeft: settings.paddingLeft,
|
||||
paddingRight: settings.paddingRight,
|
||||
scrollContainerId: LYRICS_SCROLL_CONTAINER_ID,
|
||||
});
|
||||
|
||||
|
||||
@@ -82,9 +82,13 @@ export const SynchronizedLyrics = ({
|
||||
containerRef,
|
||||
followRef,
|
||||
followScrollAlignmentRef,
|
||||
fontSize: settings.fontSize,
|
||||
gap: settings.gap,
|
||||
lineIdPrefix: 'lyric',
|
||||
lineLeadTimeMsRef,
|
||||
lyrics: normalizedLyrics,
|
||||
paddingLeft: settings.paddingLeft,
|
||||
paddingRight: settings.paddingRight,
|
||||
scrollContainerId: LYRICS_SCROLL_CONTAINER_ID,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user