mirror of
https://git.unlock-music.dev/um/um-react.git
synced 2025-05-23 16:27:41 +08:00
74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import { useRef } from 'react';
|
|
import { DecryptedAudioFile, deleteFile, ProcessState } from './fileListingSlice';
|
|
import { useAppDispatch } from '~/hooks';
|
|
import { AnimationDefinition } from 'framer-motion';
|
|
import { FileError } from './FileError';
|
|
import classNames from 'classnames';
|
|
|
|
interface FileRowProps {
|
|
id: string;
|
|
file: DecryptedAudioFile;
|
|
}
|
|
|
|
export function FileRow({ id, file }: FileRowProps) {
|
|
// const { isOpen, onClose } = useDisclosure({ defaultIsOpen: true });
|
|
const dispatch = useAppDispatch();
|
|
const isDecrypted = file.state === ProcessState.COMPLETE;
|
|
const metadata = file.metadata;
|
|
|
|
const nameWithoutExt = file.fileName.replace(/\.[a-z\d]{3,6}$/, '');
|
|
const decryptedName = nameWithoutExt + '.' + file.ext;
|
|
|
|
const audioPlayerRef = useRef<HTMLAudioElement>(null);
|
|
const _onCollapseAnimationComplete = (definition: AnimationDefinition) => {
|
|
if (definition === 'exit') {
|
|
dispatch(deleteFile({ id }));
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="card bg-base-100 shadow-sm w-full md:w-[30%] " data-testid="file-row">
|
|
<div className="card-body items-center text-center px-2">
|
|
<h2
|
|
className="card-title overflow-hidden text-ellipsis block max-w-full whitespace-nowrap"
|
|
data-testid="audio-meta-song-name"
|
|
>
|
|
{metadata?.name ?? nameWithoutExt}
|
|
</h2>
|
|
|
|
<div>
|
|
{file.state === ProcessState.ERROR && <FileError error={file.errorMessage} code={file.errorCode} />}
|
|
{isDecrypted && (
|
|
<audio
|
|
className="max-w-[100%]"
|
|
aria-disabled={!file.decrypted}
|
|
controls
|
|
autoPlay={false}
|
|
src={file.decrypted}
|
|
ref={audioPlayerRef}
|
|
/>
|
|
)}
|
|
</div>
|
|
|
|
<div className="card-actions justify-end">
|
|
<a
|
|
href={file.decrypted}
|
|
download={decryptedName}
|
|
title={`下载: ${decryptedName}`}
|
|
className={classNames('btn', {
|
|
'btn-primary': file.decrypted,
|
|
'cursor-not-allowed pointer-events-none': !file.decrypted,
|
|
})}
|
|
data-testid="audio-download"
|
|
>
|
|
下载
|
|
</a>
|
|
<button type="button" className="btn btn-error" onClick={() => dispatch(deleteFile({ id }))}>
|
|
删除
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|