metadata fixes, redux start. Lifecycle fixes for regions, etc
This commit is contained in:
@ -1,6 +1,3 @@
|
||||
import { use, useEffect, useState } from 'react';
|
||||
import AudioTrimmer from './AudioTrimer';
|
||||
import { ClipMetadata, PlaybackType } from '../../ipc/audio/types';
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
@ -12,99 +9,90 @@ import {
|
||||
arrayMove,
|
||||
SortableContext,
|
||||
verticalListSortingStrategy,
|
||||
useSortable,
|
||||
} from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
|
||||
import AudioTrimmer from './AudioTrimer';
|
||||
import { ClipMetadata } from '../../redux/types';
|
||||
import { useAppDispatch, useAppSelector } from '../hooks';
|
||||
|
||||
export interface ClipListProps {
|
||||
collection: string;
|
||||
}
|
||||
|
||||
const testData: ClipMetadata[] = [
|
||||
{
|
||||
name: 'test 1',
|
||||
filePath:
|
||||
'C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250118_000351.wav',
|
||||
volume: 1,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
playbackType: PlaybackType.PlayStop,
|
||||
},
|
||||
{
|
||||
name: 'test 2',
|
||||
filePath:
|
||||
'C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250105_131700.wav',
|
||||
volume: 1,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
playbackType: PlaybackType.PlayStop,
|
||||
},
|
||||
{
|
||||
name: 'test 3',
|
||||
filePath:
|
||||
'C:\\Users\\mickl\\Music\\clips\\original\\audio_capture_20250117_194006.wav',
|
||||
volume: 1,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
playbackType: PlaybackType.PlayStop,
|
||||
},
|
||||
];
|
||||
|
||||
function SortableTrimmer({ trimmer, id }) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||
useSortable({ id });
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
marginBottom: '1rem',
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style}>
|
||||
{/* Only this div is draggable */}
|
||||
<div
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
style={{
|
||||
cursor: 'grab',
|
||||
padding: '4px',
|
||||
background: '#6e44ba',
|
||||
color: 'white',
|
||||
borderRadius: '4px',
|
||||
marginBottom: '8px',
|
||||
width: 'fit-content',
|
||||
}}
|
||||
>
|
||||
Drag
|
||||
</div>
|
||||
{/* Wavesurfer and rest of AudioTrimmer are NOT draggable */}
|
||||
<AudioTrimmer metadata={trimmer} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ClipList({ collection }: ClipListProps) {
|
||||
const [metadata, setMetadata] = useState<ClipMetadata[]>(testData);
|
||||
useEffect(() => {
|
||||
setMetadata(testData);
|
||||
}, [collection]);
|
||||
const metadata = useAppSelector(
|
||||
(state) => state.collections[collection] || [],
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
|
||||
);
|
||||
|
||||
function handleDragEnd(event) {
|
||||
async function handleDragEnd(event) {
|
||||
const { active, over } = event;
|
||||
if (active.id !== over?.id) {
|
||||
const oldIndex = metadata.findIndex(
|
||||
(item) => item.filePath === active.id,
|
||||
(item) => item.filename === active.id,
|
||||
);
|
||||
const newIndex = metadata.findIndex((item) => item.filePath === over.id);
|
||||
const newIndex = metadata.findIndex((item) => item.filename === over.id);
|
||||
const newMetadata = arrayMove(metadata, oldIndex, newIndex);
|
||||
console.log('New order:', newMetadata);
|
||||
setMetadata(newMetadata);
|
||||
dispatch({
|
||||
type: 'metadata/setCollections',
|
||||
payload: { collection, newMetadata },
|
||||
});
|
||||
try {
|
||||
const response = await fetch(
|
||||
'http://localhost:5010/meta/collection/clips/reorder',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: collection,
|
||||
clips: newMetadata,
|
||||
}),
|
||||
},
|
||||
);
|
||||
const data = await response.json();
|
||||
console.log('handle reorder return:', data.collections);
|
||||
dispatch({ type: 'metadata/setAllData', payload: data });
|
||||
} catch (error) {
|
||||
console.error('Error saving new clip order:', error);
|
||||
}
|
||||
// setMetadata(newMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleClipSave(meta: ClipMetadata) {
|
||||
try {
|
||||
dispatch({
|
||||
type: 'metadata/editClip',
|
||||
payload: { collection, clip: meta },
|
||||
});
|
||||
const response = await fetch(
|
||||
'http://localhost:5010/meta/collection/clips/edit',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: collection,
|
||||
clip: meta,
|
||||
}),
|
||||
},
|
||||
);
|
||||
const data = await response.json();
|
||||
// console.log('handle clip save return:', data.collections);
|
||||
dispatch({
|
||||
type: 'metadata/editClip',
|
||||
payload: { collection, clip: meta },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error saving clip metadata:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,11 +105,15 @@ export default function ClipList({ collection }: ClipListProps) {
|
||||
modifiers={[restrictToVerticalAxis]}
|
||||
>
|
||||
<SortableContext
|
||||
items={metadata.map((item) => item.filePath)}
|
||||
items={metadata.map((item) => item.filename)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{metadata.map((trimmer) => (
|
||||
<AudioTrimmer key={trimmer.filePath} metadata={trimmer} />
|
||||
<AudioTrimmer
|
||||
key={trimmer.filename}
|
||||
filename={trimmer.filename}
|
||||
onSave={handleClipSave}
|
||||
/>
|
||||
))}
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
|
||||
Reference in New Issue
Block a user