styling and building out trimmer component

This commit is contained in:
michalcourson
2026-02-07 10:25:53 -05:00
parent c292350b25
commit 0346efd504
6 changed files with 645 additions and 65 deletions

View File

@ -5,8 +5,13 @@ import React, {
useCallback,
useRef,
} from 'react';
import Regions from 'wavesurfer.js/dist/plugins/regions.esm.js';
import { useWavesurfer } from '@wavesurfer/react';
import Regions from 'wavesurfer.js/dist/plugins/regions.esm.js';
import ZoomPlugin from 'wavesurfer.js/dist/plugins/zoom.esm.js';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import PauseIcon from '@mui/icons-material/Pause';
import SaveIcon from '@mui/icons-material/Save';
import DeleteIcon from '@mui/icons-material/Delete';
export interface AudioTrimmerProps {
filePath: string;
@ -29,14 +34,25 @@ export default function AudioTrimmer({
}: AudioTrimmerProps) {
const [blobUrl, setBlobUrl] = useState<string | undefined>(undefined);
const containerRef = useRef(null);
const [clipStart, setClipStart] = useState<number>(0);
const [clipEnd, setClipEnd] = useState<number>(0);
const plugins = useMemo(() => [Regions.create()], []);
const plugins = useMemo(
() => [
Regions.create(),
ZoomPlugin.create({
scale: 0.25,
}),
],
[],
);
const { wavesurfer, isReady, isPlaying } = useWavesurfer({
container: containerRef,
height: 100,
waveColor: '#ccb1ff',
progressColor: '#6e44ba',
hideScrollbar: true,
url: blobUrl,
plugins,
});
@ -50,6 +66,8 @@ export default function AudioTrimmer({
region.remove();
}
});
setClipStart(newRegion.start);
setClipEnd(newRegion.end);
},
[plugins, wavesurfer],
);
@ -57,6 +75,8 @@ export default function AudioTrimmer({
useEffect(() => {
console.log('ready, setting up regions plugin', wavesurfer);
if (trimStart !== undefined && trimEnd !== undefined) {
setClipStart(trimStart);
setClipEnd(trimEnd);
plugins[0].addRegion({
start: trimStart,
end: trimEnd,
@ -64,6 +84,9 @@ export default function AudioTrimmer({
drag: false,
resize: true,
});
} else {
setClipStart(0);
setClipEnd(wavesurfer ? wavesurfer.getDuration() : 0);
}
plugins[0].enableDragSelection({
@ -104,17 +127,56 @@ export default function AudioTrimmer({
}
};
const formatTime = (seconds: number) => {
const minutes = Math.floor(seconds / 60);
const secs = (seconds % 60).toFixed(0);
return `${minutes}:${secs.padStart(2, '0')}`;
};
return (
<div className="shadow-[0_4px_6px_rgba(0,0,0,0.5)] m-2 p-4 rounded-lg bg-darkDrop">
<div>
<text className="m-2 font-bold text-lg">{title}</text>
</div>
<div className="w-[100%] m-2 ">
<div ref={containerRef} />
<button type="button" onClick={onPlayPause}>
{isPlaying ? 'Pause' : 'Play'}
</button>
{/* <div className="flex flex-col"> */}
<div className="">
<div className="grid justify-items-stretch grid-cols-2">
<div className="m-1 mb-5px flex flex-col">
<text className="font-bold text-lg">{title}</text>
<text className="text-sm text-neutral-500">{filePath}</text>
</div>
<div className="flex justify-end">
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={onPlayPause}
>
{isPlaying ? <PauseIcon /> : <PlayArrowIcon />}
</button>
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={onSave}
>
<SaveIcon />
</button>
<button
type="button"
className="bg-plum hover:bg-plumDark text-white font-bold h-11 w-11 rounded-md ml-1"
onClick={onDelete}
>
<DeleteIcon />
</button>
</div>
</div>
<div className="m-1 wavesurfer-scroll-container">
<div ref={containerRef} className="wavesurfer-inner" />
</div>
<div className="grid justify-items-stretch grid-cols-2 text-neutral-500">
<div className="m-1">
<text className="text-sm ">Start: {formatTime(clipStart)}</text>
</div>
<div className="mx-1 flex justify-end">
<text className="text-sm">End: {formatTime(clipEnd)}</text>
</div>
</div>
</div>
</div>
);