添加 Levenshtein 算法(QMCv2) #33
@ -7,26 +7,21 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
Input,
|
|
||||||
InputGroup,
|
|
||||||
InputLeftElement,
|
|
||||||
InputRightElement,
|
|
||||||
List,
|
List,
|
||||||
ListItem,
|
|
||||||
Menu,
|
Menu,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
MenuDivider,
|
MenuDivider,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
Text,
|
Text,
|
||||||
VStack,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { qmc2AddKey, qmc2ClearKeys, qmc2DeleteKey, qmc2UpdateKey } from '../settingsSlice';
|
import { qmc2AddKey, qmc2ClearKeys } from '../settingsSlice';
|
||||||
import { selectStagingQMCv2Settings } from '../settingsSelector';
|
import { selectStagingQMCv2Settings } from '../settingsSelector';
|
||||||
import React, { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { MdAdd, MdDelete, MdDeleteForever, MdExpandMore, MdFileUpload, MdVpnKey } from 'react-icons/md';
|
import { MdAdd, MdDeleteForever, MdExpandMore, MdFileUpload } from 'react-icons/md';
|
||||||
import { ImportFileModal } from './QMCv2/ImportFileModal';
|
import { ImportFileModal } from './QMCv2/ImportFileModal';
|
||||||
|
import { KeyInput } from './QMCv2/KeyInput';
|
||||||
|
|
||||||
export function PanelQMCv2Key() {
|
export function PanelQMCv2Key() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -34,9 +29,6 @@ export function PanelQMCv2Key() {
|
|||||||
const [showImportModal, setShowImportModal] = useState(false);
|
const [showImportModal, setShowImportModal] = useState(false);
|
||||||
|
|
||||||
const addKey = () => dispatch(qmc2AddKey());
|
const addKey = () => dispatch(qmc2AddKey());
|
||||||
const updateKey = (prop: 'name' | 'key', id: string, e: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(qmc2UpdateKey({ id, field: prop, value: e.target.value }));
|
|
||||||
const deleteKey = (id: string) => dispatch(qmc2DeleteKey({ id }));
|
|
||||||
const clearAll = () => dispatch(qmc2ClearKeys());
|
const clearAll = () => dispatch(qmc2ClearKeys());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -50,7 +42,7 @@ export function PanelQMCv2Key() {
|
|||||||
客户端的情况下,其「离线加密文件」对应的「密钥」储存在独立的数据库文件内。
|
客户端的情况下,其「离线加密文件」对应的「密钥」储存在独立的数据库文件内。
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Box pb={2} pt={2}>
|
<HStack pb={2} pt={2}>
|
||||||
<ButtonGroup isAttached colorScheme="purple" variant="outline">
|
<ButtonGroup isAttached colorScheme="purple" variant="outline">
|
||||||
<Button onClick={addKey} leftIcon={<Icon as={MdAdd} />}>
|
<Button onClick={addKey} leftIcon={<Icon as={MdAdd} />}>
|
||||||
添加一条密钥
|
添加一条密钥
|
||||||
@ -68,48 +60,12 @@ export function PanelQMCv2Key() {
|
|||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Box>
|
</HStack>
|
||||||
|
|
||||||
<Box flex={1} minH={0} overflow="auto" pr="4">
|
<Box flex={1} minH={0} overflow="auto" pr="4">
|
||||||
<List spacing={3}>
|
<List spacing={3}>
|
||||||
{qmc2Keys.map(({ id, key, name }, i) => (
|
{qmc2Keys.map(({ id, key, name }, i) => (
|
||||||
<ListItem key={id} mt={0} pt={2} pb={2} _even={{ bg: 'gray.50' }}>
|
<KeyInput key={id} id={id} ekey={key} name={name} i={i} />
|
||||||
<HStack>
|
|
||||||
<Text w="2em" textAlign="center">
|
|
||||||
{i + 1}
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<VStack flex={1}>
|
|
||||||
<Input
|
|
||||||
variant="flushed"
|
|
||||||
placeholder="文件名"
|
|
||||||
value={name}
|
|
||||||
onChange={(e) => updateKey('name', id, e)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<InputGroup size="xs">
|
|
||||||
<InputLeftElement pr="2">
|
|
||||||
<Icon as={MdVpnKey} />
|
|
||||||
</InputLeftElement>
|
|
||||||
<Input variant="flushed" placeholder="密钥" value={key} onChange={(e) => updateKey('key', id, e)} />
|
|
||||||
<InputRightElement>
|
|
||||||
<Text pl="2" color={key.length ? 'green.500' : 'red.500'}>
|
|
||||||
<code>{key.length || '?'}</code>
|
|
||||||
</Text>
|
|
||||||
</InputRightElement>
|
|
||||||
</InputGroup>
|
|
||||||
</VStack>
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
aria-label="删除该密钥"
|
|
||||||
icon={<Icon as={MdDelete} boxSize={6} />}
|
|
||||||
variant="ghost"
|
|
||||||
colorScheme="red"
|
|
||||||
type="button"
|
|
||||||
onClick={() => deleteKey(id)}
|
|
||||||
/>
|
|
||||||
</HStack>
|
|
||||||
</ListItem>
|
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
{qmc2Keys.length === 0 && <Text>还没有添加密钥。</Text>}
|
{qmc2Keys.length === 0 && <Text>还没有添加密钥。</Text>}
|
||||||
|
59
src/features/settings/panels/QMCv2/KeyInput.tsx
Normal file
59
src/features/settings/panels/QMCv2/KeyInput.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import {
|
||||||
|
HStack,
|
||||||
|
Icon,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
InputGroup,
|
||||||
|
InputLeftElement,
|
||||||
|
InputRightElement,
|
||||||
|
ListItem,
|
||||||
|
Text,
|
||||||
|
VStack,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { MdDelete, MdVpnKey } from 'react-icons/md';
|
||||||
|
import { qmc2DeleteKey, qmc2UpdateKey } from '../../settingsSlice';
|
||||||
|
import { useAppDispatch } from '~/hooks';
|
||||||
|
import { memo } from 'react';
|
||||||
|
|
||||||
|
export const KeyInput = memo(({ id, name, ekey, i }: { id: string; name: string; ekey: string; i: number }) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const updateKey = (prop: 'name' | 'key', e: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
dispatch(qmc2UpdateKey({ id, field: prop, value: e.target.value }));
|
||||||
|
const deleteKey = () => dispatch(qmc2DeleteKey({ id }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem mt={0} pt={2} pb={2} _even={{ bg: 'gray.50' }}>
|
||||||
|
<HStack>
|
||||||
|
<Text w="2em" textAlign="center">
|
||||||
|
{i + 1}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<VStack flex={1}>
|
||||||
|
<Input variant="flushed" placeholder="文件名" value={name} onChange={(e) => updateKey('name', e)} />
|
||||||
|
|
||||||
|
<InputGroup size="xs">
|
||||||
|
<InputLeftElement pr="2">
|
||||||
|
<Icon as={MdVpnKey} />
|
||||||
|
</InputLeftElement>
|
||||||
|
<Input variant="flushed" placeholder="密钥" value={ekey} onChange={(e) => updateKey('key', e)} />
|
||||||
|
<InputRightElement>
|
||||||
|
<Text pl="2" color={ekey.length ? 'green.500' : 'red.500'}>
|
||||||
|
<code>{ekey.length || '?'}</code>
|
||||||
|
</Text>
|
||||||
|
</InputRightElement>
|
||||||
|
</InputGroup>
|
||||||
|
</VStack>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
aria-label="删除该密钥"
|
||||||
|
icon={<Icon as={MdDelete} boxSize={6} />}
|
||||||
|
variant="ghost"
|
||||||
|
colorScheme="red"
|
||||||
|
type="button"
|
||||||
|
onClick={deleteKey}
|
||||||
|
/>
|
||||||
|
</HStack>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user