diff --git a/src/components/AppRoot.tsx b/src/components/AppRoot.tsx index e205487..a457092 100644 --- a/src/components/AppRoot.tsx +++ b/src/components/AppRoot.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react'; -import { MdSettings, MdHome } from 'react-icons/md'; +import { MdSettings, MdHome, MdQuestionAnswer } from 'react-icons/md'; import { ChakraProvider, Tabs, TabList, TabPanels, Tab, TabPanel, Icon, chakra } from '@chakra-ui/react'; import { MainTab } from '~/tabs/MainTab'; @@ -10,6 +10,7 @@ import { theme } from '~/theme'; import { persistSettings } from '~/features/settings/persistSettings'; import { setupStore } from '~/store'; import { Footer } from '~/components/Footer'; +import { FaqTab } from '~/tabs/FaqTab'; // Private to this file only. const store = setupStore(); @@ -30,6 +31,10 @@ export function AppRoot() { 设置 + + + 问答 + @@ -39,6 +44,9 @@ export function AppRoot() { + + + diff --git a/src/components/HelpText/Header3.tsx b/src/components/HelpText/Header3.tsx new file mode 100644 index 0000000..67e1caf --- /dev/null +++ b/src/components/HelpText/Header3.tsx @@ -0,0 +1,26 @@ +import { Heading } from '@chakra-ui/react'; +import React from 'react'; + +export interface Header3Props { + children: React.ReactNode; + id?: string; + className?: string; +} + +export function Header3({ children, className, id }: Header3Props) { + return ( + + {children} + + ); +} diff --git a/src/components/HelpText/Header4.tsx b/src/components/HelpText/Header4.tsx new file mode 100644 index 0000000..f2b8deb --- /dev/null +++ b/src/components/HelpText/Header4.tsx @@ -0,0 +1,16 @@ +import { Heading } from '@chakra-ui/react'; +import React from 'react'; + +export interface Header4Props { + children: React.ReactNode; + id?: string; + className?: string; +} + +export function Header4({ children, className, id }: Header4Props) { + return ( + + {children} + + ); +} diff --git a/src/components/HelpText/HiWord.tsx b/src/components/HelpText/HiWord.tsx new file mode 100644 index 0000000..54bee0f --- /dev/null +++ b/src/components/HelpText/HiWord.tsx @@ -0,0 +1,9 @@ +import { Mark } from '@chakra-ui/react'; + +export function HiWord({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/src/components/HelpText/VQuote.tsx b/src/components/HelpText/VQuote.tsx new file mode 100644 index 0000000..274637c --- /dev/null +++ b/src/components/HelpText/VQuote.tsx @@ -0,0 +1,13 @@ +import { chakra, css } from '@chakra-ui/react'; + +const cssUnselectable = css({ pointerEvents: 'none', userSelect: 'none' }); + +export function VQuote({ children }: { children: React.ReactNode }) { + return ( + <> + + {children} + + + ); +} diff --git a/src/components/ProjectIssue.tsx b/src/components/ProjectIssue.tsx new file mode 100644 index 0000000..e56055a --- /dev/null +++ b/src/components/ProjectIssue.tsx @@ -0,0 +1,17 @@ +export interface ProjectIssueProps { + id: number | string; + title?: string; +} + +export function ProjectIssue({ id, title }: ProjectIssueProps) { + return ( + + {`#${id}`} + {title && ` - ${title}`} + + ); +} diff --git a/src/faq/KuwoFAQ.tsx b/src/faq/KuwoFAQ.tsx new file mode 100644 index 0000000..c955de1 --- /dev/null +++ b/src/faq/KuwoFAQ.tsx @@ -0,0 +1,50 @@ +import { Alert, AlertIcon, Container, List, ListItem, Text, VStack, chakra } from '@chakra-ui/react'; +import { Header4 } from '~/components/HelpText/Header4'; +import { VQuote } from '~/components/HelpText/VQuote'; +import { SegmentTryOfficialPlayer } from './SegmentTryOfficialPlayer'; +import { HiWord } from '~/components/HelpText/HiWord'; +import { KWMv2AllInstructions } from '~/features/settings/panels/KWMv2/KWMv2AllInstructions'; +import { SegmentKeyImportInstructions } from './SegmentKeyImportInstructions'; + +export function KuwoFAQ() { + return ( + <> + 解锁失败 + + + + + + + 2、检查您的平台 + + + 日前,仅手机客户端下载的 + + 至臻全景声 + + 及 + + 至臻母带 + + {'音质的音乐文件采用新版加密。'} + + 其他音质目前不需要提取密钥。 + PC平台暂未推出使用新版加密的音质。 + + + + + + Android 用户提取密钥需要 root 权限,或注入文件提供器。 + 请注意:项目组不提倡使用第三方修改版应用亦不会提供,使用前请自行评估风险。 + + + + + } /> + + + + ); +} diff --git a/src/faq/OtherFAQ.tsx b/src/faq/OtherFAQ.tsx new file mode 100644 index 0000000..f044698 --- /dev/null +++ b/src/faq/OtherFAQ.tsx @@ -0,0 +1,28 @@ +import { ExternalLinkIcon } from '@chakra-ui/icons'; +import { Link, Text } from '@chakra-ui/react'; +import { Header4 } from '~/components/HelpText/Header4'; +import { ProjectIssue } from '~/components/ProjectIssue'; + +export function OtherFAQ() { + return ( + <> + 解密后没有封面等信息 + 该项目进行解密处理。如果加密前的资源没有内嵌元信息或封面,解密的文件也没有。 + 请使用第三方工具进行编辑或管理元信息。 + 如何批量下载 + + 暂时没有实现,不过你可以在 以及{' '} + 追踪该问题。 + + 有更多问题? + + {'欢迎进入 '} + + Telegram “音乐解锁-交流” 交流群 + + + {' 一起探讨。'} + + + ); +} diff --git a/src/faq/QQMusicFAQ.tsx b/src/faq/QQMusicFAQ.tsx new file mode 100644 index 0000000..33d3bc8 --- /dev/null +++ b/src/faq/QQMusicFAQ.tsx @@ -0,0 +1,40 @@ +import { Alert, AlertIcon, Container, List, ListItem, Text, chakra } from '@chakra-ui/react'; +import { Header4 } from '~/components/HelpText/Header4'; +import { SegmentTryOfficialPlayer } from './SegmentTryOfficialPlayer'; +import { QMCv2AllInstructions } from '~/features/settings/panels/QMCv2/QMCv2AllInstructions'; +import { SegmentKeyImportInstructions } from './SegmentKeyImportInstructions'; + +export function QQMusicFAQ() { + return ( + <> + 解锁失败 + + + + + + + 2、检查您的平台 + + 日前,仅Windows客户端下载的歌曲无需密钥,其余平台的官方正式版本均需要提取密钥。 + + + + + iOS用户提取歌曲困难,建议换用电脑操作;Android用户提取密钥需要root,也建议用电脑操作。 + + + + + + + 重复下载同一首的歌曲不重复扣下载配额,但是同一首歌的两个版本会重复扣下载配额,请仔细分辨。 + + + + } /> + + + + ); +} diff --git a/src/faq/SegmentAddKeyDropdown.tsx b/src/faq/SegmentAddKeyDropdown.tsx new file mode 100644 index 0000000..c529e82 --- /dev/null +++ b/src/faq/SegmentAddKeyDropdown.tsx @@ -0,0 +1,25 @@ +import { Flex, IconButton } from '@chakra-ui/react'; +import { MdExpandMore } from 'react-icons/md'; +import { HiWord } from '~/components/HelpText/HiWord'; +import { VQuote } from '~/components/HelpText/VQuote'; + +export function SegmentAddKeyDropdown() { + return ( + + 按下添加一条密钥按钮 + 右侧的 + } + ml="2" + borderTopLeftRadius={0} + borderBottomLeftRadius={0} + isDisabled + css={{ ':disabled': { opacity: 1 } }} + aria-label="示例按钮" + /> + + ); +} diff --git a/src/faq/SegmentKeyImportInstructions.tsx b/src/faq/SegmentKeyImportInstructions.tsx new file mode 100644 index 0000000..8d35f47 --- /dev/null +++ b/src/faq/SegmentKeyImportInstructions.tsx @@ -0,0 +1,44 @@ +import { Flex, Icon, ListItem, OrderedList, Tabs, Text } from '@chakra-ui/react'; +import { SegmentTopNavSettings } from './SegmentTopNavSettings'; +import { VQuote } from '~/components/HelpText/VQuote'; +import { SegmentAddKeyDropdown } from './SegmentAddKeyDropdown'; +import React from 'react'; +import { MdFileUpload } from 'react-icons/md'; + +export interface SegmentKeyImportInstructionsProps { + clientInstructions: React.ReactNode; + tab: string; +} + +export function SegmentKeyImportInstructions({ clientInstructions, tab }: SegmentKeyImportInstructionsProps) { + return ( + <> + 导入密钥可以参考下面的步骤: + + + + + + 设定区域选择{tab} + + + + + + + {'选择 '} + + 从文件导入密钥… + + + + + 选择你的客户端平台来查看密钥提取说明: + + {clientInstructions} + + + + + ); +} diff --git a/src/faq/SegmentTopNavSettings.tsx b/src/faq/SegmentTopNavSettings.tsx new file mode 100644 index 0000000..918ab6e --- /dev/null +++ b/src/faq/SegmentTopNavSettings.tsx @@ -0,0 +1,9 @@ +import { VQuote } from '~/components/HelpText/VQuote'; + +export function SegmentTopNavSettings() { + return ( + <> + 点击顶部的设置 + + ); +} diff --git a/src/faq/SegmentTryOfficialPlayer.tsx b/src/faq/SegmentTryOfficialPlayer.tsx new file mode 100644 index 0000000..3142621 --- /dev/null +++ b/src/faq/SegmentTryOfficialPlayer.tsx @@ -0,0 +1,12 @@ +import { Text, chakra } from '@chakra-ui/react'; + +export function SegmentTryOfficialPlayer() { + return ( + <> + + 1、请检查您的文件 + + 尝试用下载音乐的设备播放一次看看,如果官方客户端都无法播放,那解锁肯定会失败哦。 + + ); +} diff --git a/src/features/settings/panels/KWMv2/KWMv2AllInstructions.tsx b/src/features/settings/panels/KWMv2/KWMv2AllInstructions.tsx new file mode 100644 index 0000000..144e604 --- /dev/null +++ b/src/features/settings/panels/KWMv2/KWMv2AllInstructions.tsx @@ -0,0 +1,25 @@ +import { Tab, TabList, TabPanel, TabPanels } from '@chakra-ui/react'; +import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; +import { InstructionsPC } from './InstructionsPC'; + +export function KWMv2AllInstructions() { + return ( + <> + + 安卓 + Windows + + + + + + + + + + + ); +} diff --git a/src/features/settings/panels/PanelKWMv2Key.tsx b/src/features/settings/panels/PanelKWMv2Key.tsx index ba6d4e7..ca97311 100644 --- a/src/features/settings/panels/PanelKWMv2Key.tsx +++ b/src/features/settings/panels/PanelKWMv2Key.tsx @@ -14,10 +14,6 @@ import { MenuDivider, MenuItem, MenuList, - Tab, - TabList, - TabPanel, - TabPanels, Text, useToast, } from '@chakra-ui/react'; @@ -32,8 +28,7 @@ import { kwm2AddKey, kwm2ClearKeys, kwm2ImportKeys } from '../settingsSlice'; import { selectStagingKWMv2Keys } from '../settingsSelector'; import { KWMv2EKeyItem } from './KWMv2/KWMv2EKeyItem'; import type { StagingKWMv2Key } from '../keyFormats'; -import { InstructionsPC } from './KWMv2/InstructionsPC'; -import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; +import { KWMv2AllInstructions } from './KWMv2/KWMv2AllInstructions'; export function PanelKWMv2Key() { const toast = useToast(); @@ -120,21 +115,7 @@ export function PanelKWMv2Key() { onClose={() => setShowImportModal(false)} onImport={handleSecretImport} > - - 安卓 - Windows - - - - - - - - - + ); diff --git a/src/features/settings/panels/PanelQMCv2Key.tsx b/src/features/settings/panels/PanelQMCv2Key.tsx index c309b2c..802eac7 100644 --- a/src/features/settings/panels/PanelQMCv2Key.tsx +++ b/src/features/settings/panels/PanelQMCv2Key.tsx @@ -14,10 +14,6 @@ import { MenuDivider, MenuItem, MenuList, - Tab, - TabList, - TabPanel, - TabPanels, Text, Tooltip, useToast, @@ -34,10 +30,7 @@ import { StagingQMCv2Key } from '../keyFormats'; import { DatabaseKeyExtractor } from '~/util/DatabaseKeyExtractor'; import { MMKVParser } from '~/util/MMKVParser'; import { getFileName } from '~/util/pathHelper'; -import { InstructionsIOS } from './QMCv2/InstructionsIOS'; -import { InstructionsMac } from './QMCv2/InstructionsMac'; -import { InstructionsPC } from './QMCv2/InstructionsPC'; -import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; +import { QMCv2AllInstructions } from './QMCv2/QMCv2AllInstructions'; export function PanelQMCv2Key() { const toast = useToast(); @@ -171,26 +164,7 @@ export function PanelQMCv2Key() { onClose={() => setShowImportModal(false)} onImport={handleSecretImport} > - - 安卓 - iOS - Mac - Windows - - - - - - - - - - - - - - - + ); diff --git a/src/features/settings/panels/QMCv2/QMCv2AllInstructions.tsx b/src/features/settings/panels/QMCv2/QMCv2AllInstructions.tsx new file mode 100644 index 0000000..3cfd9f5 --- /dev/null +++ b/src/features/settings/panels/QMCv2/QMCv2AllInstructions.tsx @@ -0,0 +1,32 @@ +import { Tab, TabList, TabPanel, TabPanels } from '@chakra-ui/react'; +import { AndroidADBPullInstruction } from '~/components/AndroidADBPullInstruction/AndroidADBPullInstruction'; +import { InstructionsIOS } from './InstructionsIOS'; +import { InstructionsMac } from './InstructionsMac'; +import { InstructionsPC } from './InstructionsPC'; + +export function QMCv2AllInstructions() { + return ( + <> + + 安卓 + iOS + Mac + Windows + + + + + + + + + + + + + + + + + ); +} diff --git a/src/tabs/FaqTab.tsx b/src/tabs/FaqTab.tsx new file mode 100644 index 0000000..2ac9c3a --- /dev/null +++ b/src/tabs/FaqTab.tsx @@ -0,0 +1,21 @@ +import { Center, Container, Heading } from '@chakra-ui/react'; +import { Header3 } from '~/components/HelpText/Header3'; +import { KuwoFAQ } from '~/faq/KuwoFAQ'; +import { OtherFAQ } from '~/faq/OtherFAQ'; +import { QQMusicFAQ } from '~/faq/QQMusicFAQ'; + +export function FaqTab() { + return ( + +
+ 常见问题解答 +
+ QQ 音乐 + + 酷我音乐 + + 其它问题 + +
+ ); +}