refactor: batch 3

This commit is contained in:
鲁树人
2025-05-18 02:41:20 +09:00
parent 75b43e1e84
commit 2e4e57be45
52 changed files with 933 additions and 1136 deletions

View File

@@ -1,24 +0,0 @@
import { Box, Image } from '@chakra-ui/react';
import noCoverFallbackImageURL from '~/assets/no-cover.svg';
interface AlbumImageProps {
url?: string;
name?: string;
}
export function AlbumImage({ name, url }: AlbumImageProps) {
const coverAlternativeText = name ? `${name} 的专辑封面` : '专辑封面';
return (
<Box w="160px" h="160px" m="auto">
<Image
border="2px solid"
borderColor="gray.400"
borderRadius="50%"
objectFit="cover"
src={url || noCoverFallbackImageURL}
alt={coverAlternativeText}
/>
</Box>
);
}

View File

@@ -1,5 +1,6 @@
import { Box, Button, chakra, Collapse, Text, useDisclosure } from '@chakra-ui/react';
import { toast } from 'react-toastify';
import { DecryptErrorType } from '~/decrypt-worker/util/DecryptError';
import { applyTemplate } from '~/util/applyTemplate';
export interface FileErrorProps {
error: null | string;
@@ -7,33 +8,55 @@ export interface FileErrorProps {
}
const errorMap = new Map<string | null | DecryptErrorType, string>([
[DecryptErrorType.UNSUPPORTED_FILE, '尚未支持的文件格式'],
[DecryptErrorType.UNSUPPORTED_FILE, '支持的文件类型'],
]);
const ERROR_TEMPLATE = `解密错误:{{summary}}
详细信息:
\`\`\`text
{{error}}
\`\`\`
<!-- 报告错误时请提交上述【全部内容】 -->
`;
export function FileError({ error, code }: FileErrorProps) {
const { isOpen, onToggle } = useDisclosure();
const errorSummary = errorMap.get(code) ?? '未知错误';
const summary = errorMap.get(code) ?? '未知错误';
const copyError = () => {
if (error) {
navigator.clipboard
.writeText(applyTemplate(ERROR_TEMPLATE, { summary, error }))
.then(() => {
toast.success('错误信息已复制到剪贴板');
})
.catch((e) => {
toast.error(`复制错误信息失败: ${e}`);
});
}
};
return (
<Box>
<Text>
<chakra.span>
<chakra.span color="red.700">{errorSummary}</chakra.span>
</chakra.span>
{error && (
<Button ml="2" onClick={onToggle} type="button">
</Button>
)}
</Text>
<>
<p>
<span className="text-red-600">{summary}</span>
</p>
{error && (
<Collapse in={isOpen} animateOpacity>
<Box as="pre" display="inline-block" mt="2" px="4" py="2" bg="red.100" color="red.800" rounded="md">
{error}
</Box>
</Collapse>
<div className="collapse border-error border w-full text-left my-2 py-0">
<input className="[&&&]:py-2 [&&&]:min-h-[1.5rem]" type="checkbox" />
<div className="collapse-title font-semibold text-center [&&&]:min-h-[1.5rem] [&&&]:py-2"></div>
<div className="collapse-content text-sm overflow-hidden">
<pre className="overflow-x-auto w-full">{error}</pre>
<p className="mt-2 text-center">
<button type="button" className="btn btn-secondary" onClick={copyError}>
</button>
</p>
</div>
</div>
)}
</Box>
</>
);
}

View File

@@ -26,7 +26,7 @@ export function FileRow({ id, file }: FileRowProps) {
{metadata?.name ?? nameWithoutExt}
</h2>
<div>
<div className="w-full grow">
{file.state === ProcessState.ERROR && <FileError error={file.errorMessage} code={file.errorCode} />}
{isDecrypted && (
<audio

View File

@@ -1,22 +0,0 @@
import { Box, Text } from '@chakra-ui/react';
import type { AudioMetadata } from './fileListingSlice';
export interface SongMetadataProps {
metadata: AudioMetadata;
}
export function SongMetadata({ metadata }: SongMetadataProps) {
return (
<Box>
<Text>
: <span data-testid="audio-meta-album-name">{metadata.album}</span>
</Text>
<Text>
: <span data-testid="audio-meta-song-artist">{metadata.artist}</span>
</Text>
<Text>
: <span data-testid="audio-meta-album-artist">{metadata.albumArtist}</span>
</Text>
</Box>
);
}