From 3ab73d8369ef80d3d3ccb95d35779a0fd2869092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=A0=91=E4=BA=BA?= Date: Sun, 18 May 2025 23:18:01 +0900 Subject: [PATCH] adjust dark mode and layout --- .../AdbInstructionTemplate.tsx | 5 +++++ src/components/HelpText/Headers.tsx | 6 ++--- src/faq/KugouFAQ.tsx | 2 +- src/faq/KuwoFAQ.tsx | 8 +++---- src/faq/OtherFAQ.tsx | 4 ++-- src/faq/QQMusicFAQ.tsx | 4 ++-- src/faq/SegmentKeyImportInstructions.tsx | 4 ++-- src/faq/SegmentTryOfficialPlayer.tsx | 4 ++-- src/features/file-listing/FileRow.tsx | 22 ++++++------------- .../__tests__/FileListing.test.tsx | 2 +- .../file-listing/__tests__/FileRow.test.tsx | 7 ++---- .../__tests__/__fixture__/file-list.ts | 3 +++ src/features/file-listing/fileListingSlice.ts | 11 +++++++--- src/features/nav/ResponsiveNav.tsx | 2 +- src/tabs/FaqTab.tsx | 8 +++---- src/util/cleanFilename.ts | 6 +++++ 16 files changed, 53 insertions(+), 45 deletions(-) create mode 100644 src/util/cleanFilename.ts diff --git a/src/components/AndroidADBPullInstruction/AdbInstructionTemplate.tsx b/src/components/AndroidADBPullInstruction/AdbInstructionTemplate.tsx index 8d78871..7604eee 100644 --- a/src/components/AndroidADBPullInstruction/AdbInstructionTemplate.tsx +++ b/src/components/AndroidADBPullInstruction/AdbInstructionTemplate.tsx @@ -48,6 +48,11 @@ export function AdbInstructionTemplate({ dir, file, platform }: AdbInstructionTe {command} +
※ 安卓模拟器可能需要额外操作,如 + + 网易 MuMu 模拟器 + + 需要提前使用 adb connect ... 指令连接模拟器。详细请参考官方说明文档并调整上述脚本。
  • 提交当前目录下的 {file} 文件。 diff --git a/src/components/HelpText/Headers.tsx b/src/components/HelpText/Headers.tsx index cb55286..e41eab1 100644 --- a/src/components/HelpText/Headers.tsx +++ b/src/components/HelpText/Headers.tsx @@ -8,7 +8,7 @@ export interface HeaderProps { export function Header3({ children, className, id }: HeaderProps) { return ( -

    +

    {children}

    ); @@ -16,7 +16,7 @@ export function Header3({ children, className, id }: HeaderProps) { export function Header4({ children, className, id }: HeaderProps) { return ( -

    +

    {children}

    ); @@ -24,7 +24,7 @@ export function Header4({ children, className, id }: HeaderProps) { export function Header5({ children, className, id }: HeaderProps) { return ( -
    +
    {children}
    ); diff --git a/src/faq/KugouFAQ.tsx b/src/faq/KugouFAQ.tsx index 7482f0f..586b3f4 100644 --- a/src/faq/KugouFAQ.tsx +++ b/src/faq/KugouFAQ.tsx @@ -10,7 +10,7 @@ export function KugouFAQ() {

    酷狗现在对部分用户推送了 kgg 加密格式(安卓、Windows 客户端)。

    -

    根据平台不同,你需要提取密钥数据库。

    +

    根据平台不同,你需要提取密钥数据库。

    diff --git a/src/faq/KuwoFAQ.tsx b/src/faq/KuwoFAQ.tsx index 67ab2a7..f814590 100644 --- a/src/faq/KuwoFAQ.tsx +++ b/src/faq/KuwoFAQ.tsx @@ -11,7 +11,7 @@ export function KuwoFAQ() { <> 解锁失败 -

    +

    日前,仅手机客户端下载的 至臻全景声 @@ -22,10 +22,10 @@ export function KuwoFAQ() { 音质的音乐文件采用新版加密。

    -

    其他音质目前不需要提取密钥。

    -

    PC平台暂未推出使用新版加密的音质。

    +

    其他音质目前不需要提取密钥。

    +

    PC平台暂未推出使用新版加密的音质。

    -
    +

    安卓用户提取密钥需要 root 权限,或注入文件提供器。

    diff --git a/src/faq/OtherFAQ.tsx b/src/faq/OtherFAQ.tsx index 5728440..d6a0331 100644 --- a/src/faq/OtherFAQ.tsx +++ b/src/faq/OtherFAQ.tsx @@ -50,8 +50,8 @@ export function OtherFAQ() { 对安卓设备获取 root 特权通常会破坏系统的完整性并导致部分功能无法使用。 例如部分厂商的安卓设备会在解锁后丧失保修资格,或导致无法使用 NFC 移动支付等限制。

    -

    如果希望不破坏系统完整性,你可以考虑在电脑上使用安卓模拟器。

    -

    +

    如果希望不破坏系统完整性,你可以考虑在电脑上使用安卓模拟器。

    +

    很多安卓模拟器都提供了 root 特权支持,可以很方便的启用,例如 网易 MuMu 模拟器(安卓 12,推荐) diff --git a/src/faq/QQMusicFAQ.tsx b/src/faq/QQMusicFAQ.tsx index b3ce4c9..b1e0391 100644 --- a/src/faq/QQMusicFAQ.tsx +++ b/src/faq/QQMusicFAQ.tsx @@ -7,8 +7,8 @@ export function QQMusicFAQ() { <> 解锁失败 -

    重复下载同一首的歌曲不重复扣下载配额,但是同一首歌的两个版本会重复扣下载配额,请仔细分辨。

    -

    +

    重复下载同一首的歌曲不重复扣下载配额,但是同一首歌的两个版本会重复扣下载配额,请仔细分辨。

    +

    部分平台获取的加密文件未包含密钥。选择你下载文件时使用的客户端来查看说明。

    diff --git a/src/faq/SegmentKeyImportInstructions.tsx b/src/faq/SegmentKeyImportInstructions.tsx index 2d5df66..0fb76d6 100644 --- a/src/faq/SegmentKeyImportInstructions.tsx +++ b/src/faq/SegmentKeyImportInstructions.tsx @@ -16,7 +16,7 @@ export function SegmentKeyImportInstructions({ }: SegmentKeyImportInstructionsProps) { return ( <> -

    导入密钥可以参考下面的步骤:

    +

    导入密钥可以参考下面的步骤:

    1. @@ -28,7 +28,7 @@ export function SegmentKeyImportInstructions({
    2. -

      {keyInstructionText}

      +

      {keyInstructionText}

      {clientInstructions}
    diff --git a/src/faq/SegmentTryOfficialPlayer.tsx b/src/faq/SegmentTryOfficialPlayer.tsx index 27e5090..f67efee 100644 --- a/src/faq/SegmentTryOfficialPlayer.tsx +++ b/src/faq/SegmentTryOfficialPlayer.tsx @@ -1,8 +1,8 @@ import { RiErrorWarningLine } from 'react-icons/ri'; -export function SegmentTryOfficialPlayer() { +export function SegmentTryOfficialPlayer({ className = '' }: { className?: string }) { return ( -
    +

    尝试用下载音乐的设备播放一次看看,如果官方客户端都无法播放,那解锁肯定会失败哦。

    diff --git a/src/features/file-listing/FileRow.tsx b/src/features/file-listing/FileRow.tsx index 72cde1e..6cf8c9f 100644 --- a/src/features/file-listing/FileRow.tsx +++ b/src/features/file-listing/FileRow.tsx @@ -11,31 +11,23 @@ interface FileRowProps { export function FileRow({ id, file }: FileRowProps) { 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 decryptedName = file.cleanName + '.' + file.ext; return (
    -

    - {metadata?.name ?? nameWithoutExt} +

    + + {file.cleanName} + + {isDecrypted && file.ext &&
    {file.ext}
    }

    {file.state === ProcessState.ERROR && } {isDecrypted && ( -
    diff --git a/src/features/file-listing/__tests__/FileListing.test.tsx b/src/features/file-listing/__tests__/FileListing.test.tsx index a694595..eebc45f 100644 --- a/src/features/file-listing/__tests__/FileListing.test.tsx +++ b/src/features/file-listing/__tests__/FileListing.test.tsx @@ -14,5 +14,5 @@ test('should be able to render a list of 3 items', () => { }); expect(screen.getAllByTestId('file-row')).toHaveLength(3); - expect(screen.getByText('Für Alice')).toBeInTheDocument(); + expect(screen.getByText('ready')).toBeInTheDocument(); }); diff --git a/src/features/file-listing/__tests__/FileRow.test.tsx b/src/features/file-listing/__tests__/FileRow.test.tsx index 3d1412d..1e58397 100644 --- a/src/features/file-listing/__tests__/FileRow.test.tsx +++ b/src/features/file-listing/__tests__/FileRow.test.tsx @@ -3,17 +3,14 @@ import { untouchedFile } from './__fixture__/file-list'; import { FileRow } from '../FileRow'; import { completedFile } from './__fixture__/file-list'; -test('should render no metadata when unavailable', () => { +test('should render basic title (ready)', () => { renderWithProviders(); expect(screen.getAllByTestId('file-row')).toHaveLength(1); expect(screen.getByTestId('audio-meta-song-name')).toHaveTextContent('ready'); - expect(screen.queryByTestId('audio-meta-album-name')).toBeFalsy(); - expect(screen.queryByTestId('audio-meta-song-artist')).toBeFalsy(); - expect(screen.queryByTestId('audio-meta-album-artist')).toBeFalsy(); }); -test('should render metadata when file has been processed', () => { +test('should render basic title (done)', () => { renderWithProviders(); expect(screen.getAllByTestId('file-row')).toHaveLength(1); diff --git a/src/features/file-listing/__tests__/__fixture__/file-list.ts b/src/features/file-listing/__tests__/__fixture__/file-list.ts index 4bdfdab..11fd37e 100644 --- a/src/features/file-listing/__tests__/__fixture__/file-list.ts +++ b/src/features/file-listing/__tests__/__fixture__/file-list.ts @@ -1,6 +1,7 @@ import { DecryptedAudioFile, ProcessState } from '../../fileListingSlice'; export const untouchedFile: DecryptedAudioFile = { + cleanName: 'ready', fileName: 'ready.bin', raw: 'blob://localhost/file-a', decrypted: '', @@ -13,6 +14,7 @@ export const untouchedFile: DecryptedAudioFile = { export const completedFile: DecryptedAudioFile = { fileName: 'hello-b.bin', + cleanName: 'hello-b', raw: 'blob://localhost/file-b', decrypted: 'blob://localhost/file-b-decrypted', ext: 'flac', @@ -30,6 +32,7 @@ export const completedFile: DecryptedAudioFile = { export const fileWithError: DecryptedAudioFile = { fileName: 'hello-c.bin', + cleanName: 'hello-c', raw: 'blob://localhost/file-c', decrypted: 'blob://localhost/file-c-decrypted', ext: 'flac', diff --git a/src/features/file-listing/fileListingSlice.ts b/src/features/file-listing/fileListingSlice.ts index 02a792e..17e43cb 100644 --- a/src/features/file-listing/fileListingSlice.ts +++ b/src/features/file-listing/fileListingSlice.ts @@ -5,9 +5,11 @@ import type { RootState } from '~/store'; import { DECRYPTION_WORKER_ACTION_NAME, type DecryptionResult } from '~/decrypt-worker/constants'; import type { DecryptCommandOptions, - FetchMusicExNamePayload, ParseKugouHeaderPayload, ParseKugouHeaderResponse, + FetchMusicExNamePayload, + ParseKugouHeaderPayload, + ParseKugouHeaderResponse, ParseKuwoHeaderPayload, - ParseKuwoHeaderResponse + ParseKuwoHeaderResponse, } from '~/decrypt-worker/types'; import { decryptionQueue, workerClientBus } from '~/decrypt-worker/client'; import { DecryptErrorType } from '~/decrypt-worker/util/DecryptError'; @@ -15,8 +17,9 @@ import { selectKugouKey, selectKWMv2Key, selectQMCv2KeyByFileName, - selectQtfmAndroidKey + selectQtfmAndroidKey, } from '../settings/settingsSelector'; +import { cleanFilename } from '~/util/cleanFilename'; export enum ProcessState { QUEUED = 'QUEUED', @@ -40,6 +43,7 @@ export interface AudioMetadata { export interface DecryptedAudioFile { fileName: string; + cleanName: string; raw: string; // blob uri ext: string; decrypted: string; // blob uri @@ -106,6 +110,7 @@ export const fileListingSlice = createSlice({ addNewFile: (state, { payload }: PayloadAction<{ id: string; fileName: string; blobURI: string }>) => { state.files[payload.id] = { fileName: payload.fileName, + cleanName: cleanFilename(payload.fileName), raw: payload.blobURI, decrypted: '', ext: '', diff --git a/src/features/nav/ResponsiveNav.tsx b/src/features/nav/ResponsiveNav.tsx index ddd196d..0a15ab2 100644 --- a/src/features/nav/ResponsiveNav.tsx +++ b/src/features/nav/ResponsiveNav.tsx @@ -20,7 +20,7 @@ export function ResponsiveNav({ className={`@container/nav grow grid grid-cols-1 grid-rows-[auto_1fr] md:grid-rows-1 md:grid-cols-[10rem_1fr] ${className}`} > {/* Sidebar */} - + {/* Main content */}
    {children}
    diff --git a/src/tabs/FaqTab.tsx b/src/tabs/FaqTab.tsx index d4a2e67..d3352e5 100644 --- a/src/tabs/FaqTab.tsx +++ b/src/tabs/FaqTab.tsx @@ -1,4 +1,4 @@ -import { FC, Fragment } from 'react'; +import { ComponentType, Fragment } from 'react'; import { Header3 } from '~/components/HelpText/Headers'; import { KuwoFAQ } from '~/faq/KuwoFAQ'; import { OtherFAQ } from '~/faq/OtherFAQ'; @@ -8,7 +8,7 @@ import { KugouFAQ } from '~/faq/KugouFAQ.tsx'; type FAQEntry = { id: string; title: string; - Help: FC; + Help: ComponentType; }; const faqEntries: FAQEntry[] = [ @@ -20,10 +20,10 @@ const faqEntries: FAQEntry[] = [ export function FaqTab() { return ( -
    +

    常见问题解答

    答疑目录 -