diff --git a/src/features/settings/Settings.tsx b/src/features/settings/Settings.tsx
index 9681cf9..55ee431 100644
--- a/src/features/settings/Settings.tsx
+++ b/src/features/settings/Settings.tsx
@@ -1,20 +1,95 @@
-import { Tab, TabList, TabPanel, TabPanels, Tabs, Text } from '@chakra-ui/react';
-import { PanelQMC } from './panels/PanelQMC';
+import {
+ Button,
+ Flex,
+ Menu,
+ MenuButton,
+ MenuItem,
+ MenuList,
+ Portal,
+ Tab,
+ TabList,
+ TabPanel,
+ TabPanels,
+ Tabs,
+ Text,
+ useBreakpointValue,
+} from '@chakra-ui/react';
+import { PanelQMCv2Key } from './panels/PanelQMCv2Key';
+import { useState } from 'react';
+import { MdExpandMore, MdMenu } from 'react-icons/md';
+
+const TABS: { name: string; Tab: () => JSX.Element }[] = [
+ { name: 'QMCv2 密钥', Tab: PanelQMCv2Key },
+ {
+ name: '其它/待定',
+ Tab: () => (
+
+ 这里空空如也~
+
+ ),
+ },
+];
export function Settings() {
- return (
-
-
- QQ 音乐
- 其它
-
+ const isLargeWidthDevice =
+ useBreakpointValue({
+ base: false,
+ lg: true,
+ }) ?? false;
-
-
-
- 待定
-
-
-
+ const [tabIndex, setTabIndex] = useState(0);
+ const handleTabChange = (idx: number) => {
+ setTabIndex(idx);
+ };
+
+ return (
+
+
+
+
+
+ {TABS.map(({ name }) => (
+ {name}
+ ))}
+
+
+
+ {TABS.map(({ name, Tab }) => (
+
+ ))}
+
+
+
);
}
diff --git a/src/features/settings/panels/PanelQMC.tsx b/src/features/settings/panels/PanelQMC.tsx
deleted file mode 100644
index 932d430..0000000
--- a/src/features/settings/panels/PanelQMC.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import {
- Box,
- Button,
- ButtonGroup,
- Flex,
- HStack,
- Heading,
- Icon,
- IconButton,
- Input,
- InputGroup,
- InputLeftElement,
- InputRightElement,
- List,
- ListItem,
- Menu,
- MenuButton,
- MenuDivider,
- MenuItem,
- MenuList,
- Spacer,
- TabPanel,
- Text,
- VStack,
-} from '@chakra-ui/react';
-import { useSelector } from 'react-redux';
-import { selectQM2CSettings } from '../settingsSlice';
-import React, { useEffect, useState } from 'react';
-import { nanoid } from 'nanoid';
-import { produce } from 'immer';
-import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload, MdVpnKey } from 'react-icons/md';
-
-interface InternalQMCKeys {
- id: string;
- name: string;
- key: string;
-}
-
-export function PanelQMC() {
- const qmcSettings = useSelector(selectQM2CSettings);
- const [qmcKeys, setQMCKeys] = useState([]);
- const resetQmcKeys = () => {
- const result: InternalQMCKeys[] = [];
- for (const [name, key] of Object.entries(qmcSettings.keys)) {
- result.push({ id: name, name, key });
- }
- setQMCKeys(result);
- };
- const addRow = () => {
- setQMCKeys((prev) => [...prev, { id: nanoid(), key: '', name: '' }]);
- };
- const updateKey = (prop: 'name' | 'key', id: string, e: React.ChangeEvent) => {
- setQMCKeys((prev) =>
- produce(prev, (draft) => {
- const item = draft.find((item) => item.id === id);
- if (item) {
- item[prop] = e.target.value;
- }
- })
- );
- };
- const applyChanges = () => {
- //
- };
- const clearAll = () => setQMCKeys([]);
- useEffect(resetQmcKeys, [qmcSettings.keys]);
-
- return (
-
-
-
- 密钥
-
-
-
-
- {qmcKeys.map(({ id, key, name }, i) => (
-
-
-
- {i + 1}
-
-
-
- updateKey('name', id, e)}
- />
-
-
-
-
-
- updateKey('key', id, e)}
- />
-
-
- {key.length || '?'}
-
-
-
-
-
-
- ))}
-
- {qmcKeys.length === 0 && 还没有添加密钥。}
-
-
-
-
- 密钥填充完毕后,按下「应用」来使用新的设置。
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/features/settings/panels/PanelQMCv2Key.tsx b/src/features/settings/panels/PanelQMCv2Key.tsx
new file mode 100644
index 0000000..1be0f5b
--- /dev/null
+++ b/src/features/settings/panels/PanelQMCv2Key.tsx
@@ -0,0 +1,183 @@
+import {
+ Box,
+ Button,
+ ButtonGroup,
+ Center,
+ Flex,
+ HStack,
+ Heading,
+ Icon,
+ IconButton,
+ Input,
+ InputGroup,
+ InputLeftElement,
+ InputRightElement,
+ List,
+ ListItem,
+ Menu,
+ MenuButton,
+ MenuDivider,
+ MenuItem,
+ MenuList,
+ Spacer,
+ TabPanel,
+ Text,
+ VStack,
+ useToast,
+} from '@chakra-ui/react';
+import { useDispatch, useSelector } from 'react-redux';
+import { selectQM2CSettings, updateQMC2Keys } from '../settingsSlice';
+import React, { useEffect, useState } from 'react';
+import { nanoid } from 'nanoid';
+import { produce } from 'immer';
+import { MdAdd, MdAndroid, MdDeleteForever, MdExpandMore, MdFileUpload, MdVpnKey } from 'react-icons/md';
+import { objectify } from 'radash';
+
+interface InternalQMCKeys {
+ id: string;
+ name: string;
+ key: string;
+}
+
+export function PanelQMCv2Key() {
+ const toast = useToast();
+ const dispatch = useDispatch();
+ const qmcSettings = useSelector(selectQM2CSettings);
+ const [isModified, setIsModified] = useState(false);
+ const [qmcKeys, setQMCKeys] = useState([]);
+ const resetQmcKeys = () => {
+ const result: InternalQMCKeys[] = [];
+ for (const [name, key] of Object.entries(qmcSettings.keys)) {
+ result.push({ id: name, name, key });
+ }
+ setQMCKeys(result);
+ };
+ const addRow = () => {
+ setIsModified(true);
+ setQMCKeys((prev) => [...prev, { id: nanoid(), key: '', name: '' }]);
+ };
+ const updateKey = (prop: 'name' | 'key', id: string, e: React.ChangeEvent) => {
+ setIsModified(true);
+ setQMCKeys((prev) =>
+ produce(prev, (draft) => {
+ const item = draft.find((item) => item.id === id);
+ if (item) {
+ item[prop] = e.target.value;
+ }
+ })
+ );
+ };
+ const applyChanges = () => {
+ dispatch(
+ updateQMC2Keys(
+ objectify(
+ qmcKeys,
+ (item) => item.name,
+ (item) => item.key
+ )
+ )
+ );
+
+ toast({
+ title: 'QMCv2 密钥的更改已保存。',
+ status: 'success',
+ isClosable: true,
+ duration: 2500,
+ });
+ };
+ const clearAll = () => setQMCKeys([]);
+ useEffect(resetQmcKeys, [qmcSettings.keys]);
+
+ return (
+
+
+ 密钥
+
+
+
+
+ }>
+ 添加
+
+
+
+
+
+
+
+ {qmcKeys.map(({ id, key, name }, i) => (
+
+
+
+ {i + 1}
+
+
+
+ updateKey('name', id, e)}
+ />
+
+
+
+
+
+ updateKey('key', id, e)} />
+
+
+ {key.length || '?'}
+
+
+
+
+
+
+ ))}
+
+ {qmcKeys.length === 0 && 还没有添加密钥。}
+
+
+
+
+
+
+ 重复项只保留最后一项。
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/features/settings/settingsSlice.ts b/src/features/settings/settingsSlice.ts
index c215886..2891840 100644
--- a/src/features/settings/settingsSlice.ts
+++ b/src/features/settings/settingsSlice.ts
@@ -21,13 +21,16 @@ export const settingsSlice = createSlice({
updateSettings: (_state, { payload }: PayloadAction) => {
return payload;
},
+ updateQMC2Keys: (state, { payload }: PayloadAction) => {
+ state.qmc2.keys = payload;
+ },
resetConfig: () => {
return initialState;
},
},
});
-export const { updateSettings, resetConfig } = settingsSlice.actions;
+export const { updateSettings, resetConfig, updateQMC2Keys } = settingsSlice.actions;
export const selectQM2CSettings = (state: RootState) => state.settings.qmc2;
diff --git a/src/tabs/SettingsTab.tsx b/src/tabs/SettingsTab.tsx
index c105ed6..2642feb 100644
--- a/src/tabs/SettingsTab.tsx
+++ b/src/tabs/SettingsTab.tsx
@@ -1,9 +1,14 @@
-import { Container, Flex } from '@chakra-ui/react';
+import { Container, Flex, useBreakpointValue } from '@chakra-ui/react';
import { Settings } from '~/features/settings/Settings';
export function SettingsTab() {
+ const containerProps = useBreakpointValue({
+ base: { p: '0' },
+ lg: { p: undefined },
+ });
+
return (
-
+
);
diff --git a/src/themes/Tabs.tsx b/src/themes/Tabs.tsx
index ac78b2d..e13a42b 100644
--- a/src/themes/Tabs.tsx
+++ b/src/themes/Tabs.tsx
@@ -17,6 +17,13 @@ const variantLineInvert = definePartsStyle((props) => {
[borderProp]: '2px solid',
borderColor: 'inherit',
},
+ tabpanels: {
+ flex: 1,
+ minH: 0,
+ },
+ tabpanel: {
+ padding: 0,
+ },
tab: {
[borderProp]: '2px solid',
borderColor: 'transparent',
@@ -42,7 +49,10 @@ const variantLineInvert = definePartsStyle((props) => {
bg: $bg.reference,
},
root: {
+ display: 'flex',
+ flexDir: isVertical ? 'row' : 'column',
gap: 8,
+ minH: 0,
},
};
});