Skip to content

Commit

Permalink
support ocr plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Pylogmon committed Sep 3, 2023
1 parent 99eb8ca commit e047200
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 12 deletions.
16 changes: 13 additions & 3 deletions src/window/Config/pages/Service/Recognize/ConfigModal/index.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, Spacer } from '@nextui-org/react';
import { useTranslation } from 'react-i18next';
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useAtomValue } from 'jotai';

import * as buildinServices from '../../../../../../services/recognize';
import { PluginConfig } from '../PluginConfig';
import { pluginListAtom } from '..';

export default function ConfigModal(props) {
const { isOpen, onOpenChange, name, updateServiceList } = props;
const serviceType = name.startsWith('[plugin]') ? 'plugin' : 'buildin';
const pluginList = useAtomValue(pluginListAtom);
const { t } = useTranslation();
const ConfigComponent = name.startsWith('[plugin]') ? PluginConfig : buildinServices[name].Config;

const ConfigComponent = buildinServices[name].Config;
return (
<Modal
isOpen={isOpen}
Expand All @@ -18,9 +23,14 @@ export default function ConfigModal(props) {
<ModalContent className='max-h-[75vh]'>
{(onClose) => (
<>
<ModalHeader>{t(`services.recognize.${name}.title`)}</ModalHeader>
<ModalHeader>
{serviceType === 'buildin'
? t(`services.recognize.${name}.title`)
: `${pluginList[name].display} [${t('common.plugin')}]`}
</ModalHeader>
<ModalBody>
<ConfigComponent
name={name}
updateServiceList={updateServiceList}
onClose={onClose}
/>
Expand Down
90 changes: 90 additions & 0 deletions src/window/Config/pages/Service/Recognize/PluginConfig/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useTranslation } from 'react-i18next';
import { Button, Input } from '@nextui-org/react';
import toast, { Toaster } from 'react-hot-toast';
import React, { useState } from 'react';
import { useAtomValue } from 'jotai';

import { useConfig, useToastStyle } from '../../../../../../hooks';
import { invoke } from '@tauri-apps/api';
import { pluginListAtom } from '..';

export function PluginConfig(props) {
const pluginList = useAtomValue(pluginListAtom);
const { updateServiceList, onClose, name } = props;
const [loading, setLoading] = useState(false);
const [pluginConfig, setPluginConfig] = useConfig(name, {}, { sync: false });

const toastStyle = useToastStyle();
const { t } = useTranslation();

return (
<>
<Toaster />
{pluginList[name].needs.length === 0 ? (
<div>{t('services.no_need')}</div>
) : (
pluginList[name].needs.map((x) => {
return (
pluginConfig && (
<div
key={x.key}
className={`config-item`}
>
<h3 className='my-auto'>{x.display}</h3>
<Input
value={`${pluginConfig.hasOwnProperty(x.key) ? pluginConfig[x.key] : ''}`}
variant='bordered'
className='max-w-[50%]'
onValueChange={(value) => {
setPluginConfig({
...pluginConfig,
[x.key]: value,
});
}}
/>
</div>
)
);
})
)}

<div>
<Button
isLoading={loading}
fullWidth
color='primary'
onPress={() => {
if (Object.keys(pluginConfig).length !== 0) {
setLoading(true);
invoke('invoke_plugin', {
name,
pluginType: 'recognize',
text: 'Hello',
from: pluginList[name].language['auto'],
to: pluginList[name].language['zh_cn'],
needs: pluginConfig,
}).then(
(_) => {
setLoading(false);
setPluginConfig(pluginConfig, true);
updateServiceList(name);
onClose();
},
(err) => {
setLoading(false);
toast.error(err.toString(), { style: toastStyle });
}
);
} else {
setPluginConfig(pluginConfig, true);
updateServiceList(name);
onClose();
}
}}
>
{t('common.save')}
</Button>
</div>
</>
);
}
133 changes: 133 additions & 0 deletions src/window/Config/pages/Service/Recognize/SelectPluginModal/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react';
import { removeDir, BaseDirectory } from '@tauri-apps/api/fs';
import toast, { Toaster } from 'react-hot-toast';
import { MdDeleteOutline } from 'react-icons/md';
import { useTranslation } from 'react-i18next';
import { open } from '@tauri-apps/api/dialog';
import { invoke } from '@tauri-apps/api';
import React, { useState } from 'react';
import { useAtomValue } from 'jotai';

import { useToastStyle } from '../../../../../../hooks';
import { pluginListAtom } from '..';

export default function SelectPluginModal(props) {
const { isOpen, onOpenChange, setConfigName, onConfigOpen, getPluginList } = props;
const [installing, setInstalling] = useState(false);
const pluginList = useAtomValue(pluginListAtom);
const { t } = useTranslation();
const toastStyle = useToastStyle();

return (
<Modal
isOpen={isOpen}
onOpenChange={onOpenChange}
scrollBehavior='inside'
>
<Toaster />
<ModalContent className='max-h-[80vh]'>
{(onClose) => (
<>
<ModalHeader>{t('config.service.add_service')}</ModalHeader>
<ModalBody>
{Object.keys(pluginList).map((x) => {
return (
<div
className='flex justify-between'
key={x}
>
<Button
fullWidth
className='mr-[8px]'
onPress={() => {
setConfigName(x);
onConfigOpen();
}}
>
<div className='w-full'>{pluginList[x].display}</div>
</Button>
<Button
isIconOnly
color='danger'
variant='flat'
onPress={() => {
removeDir(`plugins/recognize/${x}`, {
dir: BaseDirectory.AppConfig,
recursive: true,
}).then(
(v) => {
toast.success(t('config.service.uninstall_success'), {
style: toastStyle,
});
getPluginList();
},
(e) => {
toast.error(e.toString(), { style: toastStyle });
}
);
}}
>
<MdDeleteOutline className='text-xl' />
</Button>
</div>
);
})}
<div>
<Button
fullWidth
isLoading={installing}
color='secondary'
variant='flat'
onPress={async () => {
setInstalling(true);
const selected = await open({
multiple: true,
directory: false,
filters: [
{
name: '*.potext',
extensions: ['potext'],
},
],
});
if (selected !== null) {
invoke('install_plugin', {
pathList: selected,
pluginType: 'recognize',
}).then(
(count) => {
setInstalling(false);
toast.success('Installed ' + count + ' plugins', {
style: toastStyle,
});
getPluginList();
},
(e) => {
setInstalling(false);
toast.error(e.toString(), { style: toastStyle });
}
);
} else {
setInstalling(false);
}
}}
>
<div className='w-full'>{t('config.service.install_plugin')}</div>
</Button>
</div>
</ModalBody>
<ModalFooter>
<Button
color='danger'
variant='light'
onClick={onClose}
>
{t('common.cancel')}
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
);
}
10 changes: 10 additions & 0 deletions src/window/Config/pages/Service/Recognize/ServiceItem/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ import { Spacer, Button } from '@nextui-org/react';
import { MdDeleteOutline } from 'react-icons/md';
import { useTranslation } from 'react-i18next';
import { BiSolidEdit } from 'react-icons/bi';
import { useAtomValue } from 'jotai';
import React from 'react';

import { pluginListAtom } from '..';

export default function ServiceItem(props) {
const { name, deleteService, setConfigName, onConfigOpen, ...drag } = props;
const pluginList = useAtomValue(pluginListAtom);
const serviceType = name.startsWith('[plugin]') ? 'plugin' : 'buildin';

const { t } = useTranslation();

return (
Expand All @@ -19,6 +25,10 @@ export default function ServiceItem(props) {
<RxDragHandleHorizontal />
</div>
<Spacer x={2} />
{serviceType === 'buildin' && <h2 className='my-auto'>{t(`services.recognize.${name}.title`)}</h2>}
{serviceType === 'plugin' && name in pluginList && (
<h2 className='my-auto'>{`${pluginList[name].display} [${t('common.plugin')}]`}</h2>
)}
<h2 className='my-auto'>{t(`services.recognize.${name}.title`)}</h2>
</div>
<div className='flex'>
Expand Down
57 changes: 48 additions & 9 deletions src/window/Config/pages/Service/Recognize/index.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
import { readDir, BaseDirectory, readTextFile, exists } from '@tauri-apps/api/fs';
import { Card, Spacer, Button, useDisclosure, Tooltip } from '@nextui-org/react';
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
import toast, { Toaster } from 'react-hot-toast';
import { useTranslation } from 'react-i18next';
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { atom, useSetAtom } from 'jotai';

import { useToastStyle } from '../../../../../hooks';
import SelectPluginModal from './SelectPluginModal';
import { useConfig } from '../../../../../hooks';
import ServiceItem from './ServiceItem';
import SelectModal from './SelectModal';
import ConfigModal from './ConfigModal';

export const pluginListAtom = atom({});

export default function Recognize() {
const setPluginList = useSetAtom(pluginListAtom);
const {
isOpen: isSelectPluginOpen,
onOpen: onSelectPluginOpen,
onOpenChange: onSelectPluginOpenChange,
} = useDisclosure();
const { isOpen: isSelectOpen, onOpen: onSelectOpen, onOpenChange: onSelectOpenChange } = useDisclosure();
const { isOpen: isConfigOpen, onOpen: onConfigOpen, onOpenChange: onConfigOpenChange } = useDisclosure();
const [openConfigName, setOpenConfigName] = useState('system');
Expand Down Expand Up @@ -50,6 +61,29 @@ export default function Recognize() {
setRecognizeServiceList(newList);
}
};
const getPluginList = () => {
exists('plugins/recognize', { dir: BaseDirectory.AppConfig }).then((isExist) => {
if (!isExist) {
return;
}
readDir('plugins/recognize', { dir: BaseDirectory.AppConfig }).then((plugins) => {
let temp = {};
for (const plugin of plugins) {
readTextFile(`plugins/recognize/${plugin.name}/info.json`, {
dir: BaseDirectory.AppConfig,
}).then((infoStr) => {
temp[plugin.name] = JSON.parse(infoStr);
});
}
setPluginList(temp);
});
});
};

useEffect(() => {
getPluginList();
}, []);

return (
<>
<Toaster />
Expand Down Expand Up @@ -107,16 +141,21 @@ export default function Recognize() {
{t('config.service.add_buildin_service')}
</Button>
<Spacer x={2} />
<Tooltip content={t('common.coming')}>
<Button
fullWidth
variant='light'
>
{t('config.service.add_external_service')}
</Button>
</Tooltip>
<Button
fullWidth
onPress={onSelectPluginOpen}
>
{t('config.service.add_external_service')}
</Button>
</div>
</Card>
<SelectPluginModal
isOpen={isSelectPluginOpen}
onOpenChange={onSelectPluginOpenChange}
setConfigName={setOpenConfigName}
onConfigOpen={onConfigOpen}
getPluginList={getPluginList}
/>
<SelectModal
isOpen={isSelectOpen}
onOpenChange={onSelectOpenChange}
Expand Down

0 comments on commit e047200

Please sign in to comment.