添加 Levenshtein 算法(QMCv2) #33

Merged
lsr merged 4 commits from feat/levenshtein-key-finder into main 2023-06-16 19:45:48 +00:00
2 changed files with 66 additions and 51 deletions
Showing only changes of commit b8b2059558 - Show all commits

View File

@ -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>}

View 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>
);
});