um-react/src/features/settings/Settings.tsx

160 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
chakra,
Box,
Button,
Center,
Flex,
HStack,
Icon,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Spacer,
Tab,
TabList,
TabPanel,
TabPanels,
Tabs,
Text,
VStack,
useBreakpointValue,
useToast,
} from '@chakra-ui/react';
import { PanelQMCv2Key } from './panels/PanelQMCv2Key';
import { useState } from 'react';
import { MdExpandMore, MdMenu, MdOutlineSettingsBackupRestore } from 'react-icons/md';
import { useAppDispatch, useAppSelector } from '~/hooks';
import { commitStagingChange, discardStagingChanges } from './settingsSlice';
import { PanelKWMv2Key } from './panels/PanelKWMv2Key';
import { selectIsSettingsNotSaved } from './settingsSelector';
const TABS: { name: string; Tab: () => JSX.Element }[] = [
{ name: 'QMCv2 密钥', Tab: PanelQMCv2Key },
{ name: 'KWMv2 密钥', Tab: PanelKWMv2Key },
{
name: '其它/待定',
Tab: () => <Text></Text>,
},
];
export function Settings() {
const toast = useToast();
const dispatch = useAppDispatch();
const isLargeWidthDevice =
useBreakpointValue({
base: false,
lg: true,
}) ?? false;
const [tabIndex, setTabIndex] = useState(0);
const handleTabChange = (idx: number) => {
setTabIndex(idx);
};
const handleResetSettings = () => {
dispatch(discardStagingChanges());
toast({
status: 'info',
title: '未储存的设定已舍弃',
description: '已还原到更改前的状态。',
isClosable: true,
});
};
const handleApplySettings = () => {
dispatch(commitStagingChange());
toast({
status: 'success',
title: '设定已应用',
isClosable: true,
});
};
const isSettingsNotSaved = useAppSelector(selectIsSettingsNotSaved);
return (
<Flex flexDir="column" flex={1}>
<Menu>
<MenuButton
as={Button}
leftIcon={<MdMenu />}
rightIcon={<MdExpandMore />}
colorScheme="gray"
variant="outline"
w="full"
flexShrink={0}
hidden={isLargeWidthDevice}
mb="4"
>
{TABS[tabIndex].name}
</MenuButton>
<Portal>
<MenuList w="100px">
{TABS.map(({ name }, i) => (
<MenuItem key={name} onClick={() => setTabIndex(i)}>
{name}
</MenuItem>
))}
</MenuList>
</Portal>
</Menu>
<Tabs
orientation={isLargeWidthDevice ? 'vertical' : 'horizontal'}
align="start"
variant="line-i"
display="flex"
flex={1}
index={tabIndex}
onChange={handleTabChange}
>
<TabList hidden={!isLargeWidthDevice} minW="8em" width="8em" textAlign="right" justifyContent="center">
{TABS.map(({ name }) => (
<Tab key={name}>{name}</Tab>
))}
</TabList>
<TabPanels>
{TABS.map(({ name, Tab }) => (
<Flex as={TabPanel} flex={1} flexDir="column" h="100%" key={name}>
<Flex h="100%" flex={1} minH={0}>
<Tab />
</Flex>
<VStack mt="4" alignItems="flex-start" w="full">
<Flex flexDir="row" gap="2" w="full">
<Center>
{isSettingsNotSaved ? (
<Box color="gray">
{' '}
<chakra.span color="red" wordBreak="keep-all">
</chakra.span>
</Box>
) : (
<Box color="gray"></Box>
)}
</Center>
<Spacer />
<HStack gap="2" justifyContent="flex-end">
<IconButton
icon={<Icon as={MdOutlineSettingsBackupRestore} />}
onClick={handleResetSettings}
colorScheme="red"
variant="ghost"
title="放弃未储存的更改,将设定还原为储存前的状态。"
aria-label="放弃未储存的更改"
/>
<Button onClick={handleApplySettings}></Button>
</HStack>
</Flex>
</VStack>
</Flex>
))}
</TabPanels>
</Tabs>
</Flex>
);
}