Refactor annotation tools and implement quality choice annotation feature
- Updated the annotation label from "bewertet" to "annotiert" in the HomePage component. - Removed the SingleChoiceView component and replaced it with a new QualityChoiceEntryView component for handling quality choice annotations. - Introduced QualityChoiceView component to manage the flow of quality choice annotations, including navigation and progress tracking. - Updated EditableExperimentHeader to default to 'quality-choice' annotation tool. - Added unique index for annotations in the database schema to prevent duplicate entries. - Enhanced WaveformPlayer to support audio playback state management.
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
|
||||
import { useAudio } from './AudioProvider';
|
||||
|
||||
interface WaveformPlayerProps {
|
||||
src: string;
|
||||
durationMs?: number | null;
|
||||
/** When false the player should stop if it was playing */
|
||||
isActive: boolean;
|
||||
onPlay: () => void;
|
||||
onPlay?: () => void;
|
||||
onFullyPlayed: () => void;
|
||||
}
|
||||
|
||||
@@ -16,10 +15,15 @@ const BAR_COUNT = 120;
|
||||
export default function WaveformPlayer({
|
||||
src,
|
||||
durationMs,
|
||||
isActive,
|
||||
onPlay,
|
||||
onFullyPlayed,
|
||||
}: WaveformPlayerProps) {
|
||||
const { currentAudioId, setCurrentAudio } = useAudio();
|
||||
|
||||
// Generate unique ID for this player instance
|
||||
const playerId = useMemo(() => Math.random().toString(36).slice(2), []);
|
||||
const isActive = currentAudioId === playerId;
|
||||
|
||||
const audioRef = useRef<HTMLAudioElement>(null);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const rafRef = useRef<number>(0);
|
||||
@@ -39,6 +43,21 @@ export default function WaveformPlayer({
|
||||
}
|
||||
}, [isActive, isPlaying]);
|
||||
|
||||
// Reset state when src changes and cancel playback
|
||||
|
||||
useEffect(() => {
|
||||
setPeaks([]);
|
||||
setCurrentTime(0);
|
||||
setDuration(durationMs ? durationMs / 1000 : 0);
|
||||
fullyPlayedRef.current = false;
|
||||
if (audioRef.current) {
|
||||
audioRef.current.pause();
|
||||
audioRef.current.currentTime = 0;
|
||||
}
|
||||
cancelAnimationFrame(rafRef.current);
|
||||
setIsPlaying(false);
|
||||
}, [src, durationMs]);
|
||||
|
||||
// Decode audio and generate waveform peaks
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
@@ -103,7 +122,8 @@ export default function WaveformPlayer({
|
||||
const handlePlay = () => {
|
||||
const audio = audioRef.current;
|
||||
if (!audio) return;
|
||||
onPlay();
|
||||
setCurrentAudio(playerId);
|
||||
onPlay?.();
|
||||
audio.play();
|
||||
setIsPlaying(true);
|
||||
rafRef.current = requestAnimationFrame(tick);
|
||||
@@ -122,7 +142,7 @@ export default function WaveformPlayer({
|
||||
cancelAnimationFrame(rafRef.current);
|
||||
if (!fullyPlayedRef.current) {
|
||||
fullyPlayedRef.current = true;
|
||||
onFullyPlayed();
|
||||
onFullyPlayed?.();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user