diff --git a/package.json b/package.json index 6f8ca26..d1f8611 100644 --- a/package.json +++ b/package.json @@ -34,13 +34,16 @@ }, "dependencies": { "@ant-design/icons": "^4.8.0", + "@monaco-editor/react": "^4.4.6", "@tauri-apps/api": "^1.2.0", "antd": "^5.1.0", + "clsx": "^1.2.1", "dayjs": "^1.11.7", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^8.0.4", + "react-resizable-panels": "^0.0.33", "react-router-dom": "^6.4.5", "react-syntax-highlighter": "^15.5.0", "uuid": "^9.0.0" diff --git a/src/components/FilePath/index.tsx b/src/components/FilePath/index.tsx new file mode 100644 index 0000000..8976710 --- /dev/null +++ b/src/components/FilePath/index.tsx @@ -0,0 +1,36 @@ +import { FC, useEffect, useState } from 'react'; +import clsx from 'clsx'; +import { path, shell } from '@tauri-apps/api'; + +import { chatRoot } from '@/utils'; + +interface FilePathProps { + paths?: string; + label?: string; + className?: string; + content?: string; + url?: string; +} + +const FilePath: FC = ({ className, label = 'PATH', paths = '', url, content }) => { + const [filePath, setPath] = useState(''); + + useEffect(() => { + if (!path && !url) return; + (async () => { + if (url) { + setPath(url); + return; + } + setPath(await path.join(await chatRoot(), ...paths.split('/').filter(i => !!i))); + })() + }, [url, paths]) + + return ( +
+
{label}: shell.open(filePath)} title={filePath}>{content ? content : filePath}
+
+ ); +} + +export default FilePath; \ No newline at end of file diff --git a/src/components/Markdown/Editor.tsx b/src/components/Markdown/Editor.tsx new file mode 100644 index 0000000..2db5368 --- /dev/null +++ b/src/components/Markdown/Editor.tsx @@ -0,0 +1,25 @@ +import Editor from "@monaco-editor/react"; +import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; + +import './index.scss'; + +const MarkdownEditor = () => { + return ( +
+ + + + + + +
1284
+
+
+
+ ) +}; + +export default MarkdownEditor; \ No newline at end of file diff --git a/src/components/Markdown/index.scss b/src/components/Markdown/index.scss index a53c67c..1c5bcb0 100644 --- a/src/components/Markdown/index.scss +++ b/src/components/Markdown/index.scss @@ -4,4 +4,16 @@ pre, code { font-family: monospace, monospace; } -} \ No newline at end of file +} + +.resize-handle { + width: 0.25rem; + transition: 250ms linear background-color; + background-color: #7f8082; + outline: none; + + &:hover, + &[data-resize-handle-active] { + background-color: #5194eb; + } +} diff --git a/src/main.scss b/src/main.scss index a2eabaa..d94bad3 100644 --- a/src/main.scss +++ b/src/main.scss @@ -19,6 +19,7 @@ html, body { margin: 0; } +.ant-table-selection-col, .ant-table-selection-column { width: 50px !important; min-width: 50px !important; diff --git a/src/routes.tsx b/src/routes.tsx index 41527cb..187c2b6 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -17,6 +17,7 @@ import SyncCustom from '@/view/model/SyncCustom'; import SyncRecord from '@/view/model/SyncRecord'; import Download from '@/view/download'; import Notes from '@/view/notes'; +import Markdown from '@/view/markdown'; export type ChatRouteMetaObject = { label: string; @@ -48,6 +49,11 @@ export const routes: Array = [ icon: , }, }, + { + path: '/md/:id', + element: , + hideMenu: true, + }, { path: '/model', meta: { diff --git a/src/utils.ts b/src/utils.ts index b90a7bd..ba74daf 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,6 +2,7 @@ import { readTextFile, writeTextFile, exists, createDir } from '@tauri-apps/api/ import { homeDir, join, dirname } from '@tauri-apps/api/path'; import dayjs from 'dayjs'; +export const CHAT_CONF_JSON = 'chat.conf.json'; export const CHAT_MODEL_JSON = 'chat.model.json'; export const CHAT_MODEL_CMD_JSON = 'chat.model.cmd.json'; export const CHAT_DOWNLOAD_JSON = 'chat.download.json'; diff --git a/src/view/General.tsx b/src/view/General.tsx index 6dfbdab..7e709ad 100644 --- a/src/view/General.tsx +++ b/src/view/General.tsx @@ -1,14 +1,15 @@ import { useEffect, useState } from 'react'; import { Form, Radio, Switch, Input, Button, Space, message, Tooltip } from 'antd'; import { QuestionCircleOutlined } from '@ant-design/icons'; -import { invoke, shell, path } from '@tauri-apps/api'; +import { invoke } from '@tauri-apps/api'; import { platform } from '@tauri-apps/api/os'; import { ask } from '@tauri-apps/api/dialog'; import { relaunch } from '@tauri-apps/api/process'; import { clone, omit, isEqual } from 'lodash'; import useInit from '@/hooks/useInit'; -import { DISABLE_AUTO_COMPLETE, chatRoot } from '@/utils'; +import FilePath from '@/components/FilePath'; +import { DISABLE_AUTO_COMPLETE, CHAT_CONF_JSON } from '@/utils'; const AutoUpdateLabel = () => { return ( @@ -68,13 +69,10 @@ const GlobalShortcutLabel = () => { export default function General() { const [form] = Form.useForm(); - const [jsonPath, setJsonPath] = useState(''); const [platformInfo, setPlatform] = useState(''); const [chatConf, setChatConf] = useState(null); useInit(async () => { - setJsonPath(await path.join(await chatRoot(), 'chat.conf.json')); - setPlatform(await platform()); const chatData = await invoke('get_chat_conf'); setChatConf(chatData); @@ -117,11 +115,7 @@ export default function General() { return ( <> - +
(CHAT_DOWNLOAD_JSON); const selectedItems = rowSelection.selectedRowKeys || []; - useInit(async () => { - const file = await path.join(await chatRoot(), CHAT_DOWNLOAD_JSON); - setDownloadPath(file); - }); - useEffect(() => { if (!json || json.length <= 0) return; opInit(json); @@ -118,11 +112,7 @@ export default function Download() { )} - + { + setFilePath(await getPath(state)); + }) + + return ( + <> + + + + + + {filePath} + + + + + ); +} \ No newline at end of file diff --git a/src/view/model/SyncCustom/index.tsx b/src/view/model/SyncCustom/index.tsx index 936283c..d20b045 100644 --- a/src/view/model/SyncCustom/index.tsx +++ b/src/view/model/SyncCustom/index.tsx @@ -3,9 +3,9 @@ import { Table, Modal, Button, message } from 'antd'; import { invoke, path, fs } from '@tauri-apps/api'; import useData from '@/hooks/useData'; -import useChatModel, { useCacheModel } from '@/hooks/useChatModel'; import useColumns from '@/hooks/useColumns'; import { TABLE_PAGINATION } from '@/hooks/useTable'; +import useChatModel, { useCacheModel } from '@/hooks/useChatModel'; import { CHAT_MODEL_JSON, chatRoot, readJSON, genCmd } from '@/utils'; import { syncColumns, getPath } from './config'; import SyncForm from './Form'; diff --git a/src/view/model/SyncPrompts/index.tsx b/src/view/model/SyncPrompts/index.tsx index 7db4d2e..8a26a84 100644 --- a/src/view/model/SyncPrompts/index.tsx +++ b/src/view/model/SyncPrompts/index.tsx @@ -1,10 +1,11 @@ import { useEffect, useState } from 'react'; import { Table, Button, Popconfirm } from 'antd'; -import { invoke, path, shell } from '@tauri-apps/api'; +import { invoke, path } from '@tauri-apps/api'; import useInit from '@/hooks/useInit'; import useData from '@/hooks/useData'; import useColumns from '@/hooks/useColumns'; +import FilePath from '@/components/FilePath'; import useChatModel, { useCacheModel } from '@/hooks/useChatModel'; import { useTableRowSelection, TABLE_PAGINATION } from '@/hooks/useTable'; import { fmtDate, chatRoot } from '@/utils'; @@ -80,8 +81,8 @@ export default function SyncPrompts() { diff --git a/src/view/model/SyncRecord/index.tsx b/src/view/model/SyncRecord/index.tsx index 9f22759..b74344a 100644 --- a/src/view/model/SyncRecord/index.tsx +++ b/src/view/model/SyncRecord/index.tsx @@ -2,14 +2,15 @@ import { useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { ArrowLeftOutlined } from '@ant-design/icons'; import { Table, Button } from 'antd'; -import { shell, path } from '@tauri-apps/api'; +import { path } from '@tauri-apps/api'; -import useColumns from '@/hooks/useColumns'; import useData from '@/hooks/useData'; +import useColumns from '@/hooks/useColumns'; +import FilePath from '@/components/FilePath'; import { useCacheModel } from '@/hooks/useChatModel'; import { useTableRowSelection, TABLE_PAGINATION } from '@/hooks/useTable'; -import { fmtDate, chatRoot } from '@/utils'; import { getPath } from '@/view/model/SyncCustom/config'; +import { fmtDate, chatRoot } from '@/utils'; import { syncColumns } from './config'; import useInit from '@/hooks/useInit'; @@ -66,8 +67,8 @@ export default function SyncRecord() {
{state?.last_updated && Last updated on {fmtDate(state?.last_updated)}}
diff --git a/src/view/model/UserCustom/index.tsx b/src/view/model/UserCustom/index.tsx index 985fe41..5c85e84 100644 --- a/src/view/model/UserCustom/index.tsx +++ b/src/view/model/UserCustom/index.tsx @@ -1,11 +1,12 @@ import { useState, useRef, useEffect } from 'react'; import { Table, Button, Modal, message } from 'antd'; -import { shell, path } from '@tauri-apps/api'; +import { path } from '@tauri-apps/api'; import useInit from '@/hooks/useInit'; import useData from '@/hooks/useData'; -import useChatModel, { useCacheModel } from '@/hooks/useChatModel'; import useColumns from '@/hooks/useColumns'; +import FilePath from '@/components/FilePath'; +import useChatModel, { useCacheModel } from '@/hooks/useChatModel'; import { useTableRowSelection, TABLE_PAGINATION } from '@/hooks/useTable'; import { chatRoot, fmtDate } from '@/utils'; import { modelColumns } from './config'; @@ -108,11 +109,8 @@ export default function LanguageModel() { )} - {/*
PATH: {modelPath}
*/}
- + {lastUpdated && Last updated on {fmtDate(lastUpdated)}}
[ return ( actions.setRecord(row, 'preview')}>Preview - actions.setRecord(row, 'edit')}>Edit + Edit actions.setRecord(row, 'delete')} diff --git a/src/view/notes/index.tsx b/src/view/notes/index.tsx index 5b29c6e..1ce675a 100644 --- a/src/view/notes/index.tsx +++ b/src/view/notes/index.tsx @@ -1,18 +1,17 @@ import { useEffect, useState } from 'react'; import { Table, Modal, Popconfirm, Button, message } from 'antd'; -import { invoke, path, shell, fs } from '@tauri-apps/api'; +import { invoke, path, fs } from '@tauri-apps/api'; -import useInit from '@/hooks/useInit'; import useJson from '@/hooks/useJson'; import useData from '@/hooks/useData'; import useColumns from '@/hooks/useColumns'; import Markdown from '@/components/Markdown'; +import FilePath from '@/components/FilePath'; import { useTableRowSelection, TABLE_PAGINATION } from '@/hooks/useTable'; import { chatRoot, CHAT_NOTES_JSON } from '@/utils'; import { notesColumns } from './config'; export default function Notes() { - const [notesPath, setNotesPath] = useState(''); const [source, setSource] = useState(''); const [isVisible, setVisible] = useState(false); const { opData, opInit, opReplace, opSafeKey } = useData([]); @@ -21,11 +20,6 @@ export default function Notes() { const { json, refreshJson, updateJson } = useJson(CHAT_NOTES_JSON); const selectedItems = rowSelection.selectedRowKeys || []; - useInit(async () => { - const file = await path.join(await chatRoot(), CHAT_NOTES_JSON); - setNotesPath(file); - }); - useEffect(() => { if (!json || json.length <= 0) return; opInit(json); @@ -42,9 +36,6 @@ export default function Notes() { setVisible(true); return; } - if (opInfo.opType === 'edit') { - alert('TODO'); - } if (opInfo.opType === 'delete') { await fs.removeFile(file); await handleRefresh(); @@ -111,11 +102,7 @@ export default function Notes() { )} - +