start of react migration

This commit is contained in:
michalcourson
2026-02-04 20:42:14 -05:00
parent 51ad065047
commit 17bace5eaf
71 changed files with 26503 additions and 6037 deletions

View File

@ -0,0 +1,235 @@
import React, { useEffect, useMemo, useState } from 'react';
// import WaveSurfer from 'wavesurfer.js';
import Regions from 'wavesurfer.js/dist/plugins/regions.esm.js';
// import { useWavesurfer } from '@wavesurfer/react';
import { BlockList } from 'net';
import WavesurferPlayer from '@wavesurfer/react';
// import { IpcRenderer } from 'electron';
export interface AudioTrimmerProps {
filePath: string;
section: string;
title?: string;
trimStart?: number;
trimEnd?: number;
onSave?: (trimStart: number, trimEnd: number, title?: string) => void;
onDelete?: () => void;
}
function getBaseName(filePath: string) {
return filePath.split(/[\\/]/).pop() || filePath;
}
export default function AudioTrimmer({ filePath }: { filePath: string }) {
const [blobUrl, setBlobUrl] = useState<string | undefined>(undefined);
const [wavesurfer, setWavesurfer] = useState(null);
const [isPlaying, setIsPlaying] = useState(false);
const plugins = useMemo(() => {
return [Regions.create()];
}, []);
useEffect(() => {
let url: string | null = null;
async function fetchAudio() {
// console.log('Loading audio buffer for file:', filePath);
const buffer =
await window.electron.ipcRenderer.loadAudioBuffer(filePath);
if (buffer && !buffer.error) {
const audioData = buffer.data ? new Uint8Array(buffer.data) : buffer;
url = URL.createObjectURL(new Blob([audioData]));
setBlobUrl(url);
console.log('Audio blob URL created:', url);
}
}
fetchAudio();
return () => {
if (url) URL.revokeObjectURL(url);
};
}, [filePath]);
const onReady = (ws) => {
setWavesurfer(ws);
setIsPlaying(false);
// setDuration(ws.getDuration());
// console.log('Wavesurfer ready, duration:', ws.getDuration());
// console.log('Wavesurfer regions plugin:', ws.plugins[0]);
ws.plugins[0].addRegion?.({
start: 0,
end: ws.getDuration(),
color: 'rgba(132, 81, 224, 0.3)',
drag: false,
resize: true,
});
};
const onPlayPause = () => {
if (wavesurfer === null) return;
wavesurfer.playPause();
};
// useEffect(() => {
// if (!containerRef.current || !blobUrl) return;
// const ws = WaveSurfer.create({
// container: containerRef.current,
// waveColor: 'purple',
// url: blobUrl,
// height: 100,
// width: 600,
// });
// return () => ws.destroy();
// }, [blobUrl]);
return (
<div>
{/* <div ref={containerRef} /> */}
<WavesurferPlayer
height={100}
width={600}
url={blobUrl}
onReady={onReady}
onPlay={() => setIsPlaying(true)}
onPause={() => setIsPlaying(false)}
plugins={plugins}
/>
<button type="button" onClick={onPlayPause}>
{isPlaying ? 'Pause' : 'Play'}
</button>
</div>
);
}
// export default function AudioTrimmer({
// filePath,
// section,
// title,
// trimStart = 0,
// trimEnd,
// onSave,
// onDelete,
// }: AudioTrimmerProps) {
// const [wavesurfer, setWavesurfer] = useState(null);
// const waveformRef = useRef<HTMLDivElement>(null);
// const wavesurferRef = useRef<WaveSurfer | null>(null);
// const [region, setRegion] = useState<{ start: number; end: number }>({
// start: trimStart,
// end: trimEnd || 0,
// });
// // eslint-disable-next-line @typescript-eslint/no-unused-vars
// const [duration, setDuration] = useState<number>(0);
// useEffect(() => {
// if (!waveformRef.current) return;
// // const regions = Regions.create({
// // color: 'rgba(132, 81, 224, 0.3)',
// // drag: false,
// // resize: true,
// // });
// const regions = Regions.create();
// const ws = WaveSurfer.create({
// container: waveformRef.current,
// waveColor: '#ccb1ff',
// progressColor: '#6e44ba',
// // responsive: true,
// height: 100,
// hideScrollbar: true,
// backend: 'WebAudio',
// plugins: [regions],
// });
// wavesurferRef.current = ws;
// ws.load(`file://${filePath}`);
// ws.on('ready', () => {
// setDuration(ws.getDuration());
// regions.clearRegions();
// // ws.clearRegions();
// regions.addRegion({
// start: trimStart,
// end: trimEnd || ws.getDuration(),
// color: 'rgba(132, 81, 224, 0.3)',
// drag: false,
// resize: true,
// });
// });
// regions.on('region-updated', (updatedRegion: any) => {
// setRegion({
// start: Math.max(0, updatedRegion.start),
// end: Math.min(ws.getDuration(), updatedRegion.end),
// });
// });
// // eslint-disable-next-line consistent-return
// return () => {
// ws.destroy();
// };
// }, [filePath, trimStart, trimEnd]);
// const formatTime = (seconds: number) => {
// const minutes = Math.floor(seconds / 60);
// const remainingSeconds = Math.floor(seconds % 60);
// return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
// };
// return (
// <div className="audio-trimmer-item" data-filepath={filePath}>
// <div className="audio-trimmer-header">
// <div className="audio-trimmer-title-container">
// <div className="audio-trimmer-title">
// {title || getBaseName(filePath)}
// </div>
// <div className="audio-trimmer-filename">
// {title ? getBaseName(filePath) : 'hidden'}
// </div>
// <div className="audio-trimmer-section">{section}</div>
// </div>
// <div className="audio-trimmer-controls">
// <button
// type="button"
// className="play-pause-btn"
// onClick={() => {
// const ws = wavesurferRef.current;
// if (!ws) return;
// if (ws.isPlaying()) {
// ws.pause();
// } else {
// ws.play(region.start, region.end);
// }
// }}
// >
// ▶️
// </button>
// <button
// type="button"
// className="save-trim"
// onClick={() => onSave?.(region.start, region.end, title)}
// >
// 💾
// </button>
// <button type="button" className="delete-btn" onClick={onDelete}>
// 🗑️
// </button>
// </div>
// </div>
// <div className="waveform-container">
// <div ref={waveformRef} className="waveform" />
// </div>
// <div className="trim-info">
// <div className="trim-time">
// <span>Start: </span>
// <span className="trim-start-time">{formatTime(region.start)}</span>
// </div>
// <div className="trim-time">
// <span>End: </span>
// <span className="trim-end-time">{formatTime(region.end)}</span>
// </div>
// </div>
// </div>
// );
// }
// export default AudioTrimmer;