chore: export

This commit is contained in:
lencx
2023-01-13 23:59:38 +08:00
parent 0eb6c559c6
commit a2fcfa3b89
6 changed files with 100 additions and 34 deletions

View File

@@ -185,24 +185,30 @@ pub struct FileMetadata {
pub id: String, pub id: String,
} }
#[command] #[tauri::command]
pub fn download_list(filename: Option<String>, id: Option<String>) { pub fn get_download_list(pathname: &str) -> (Vec<serde_json::Value>, PathBuf) {
info!("download_list"); info!("get_download_list: {}", pathname);
let download_path = chat_root().join("chat.download.json"); let download_path = chat_root().join(PathBuf::from(pathname));
let content = fs::read_to_string(&download_path).unwrap_or_else(|err| { let content = fs::read_to_string(&download_path).unwrap_or_else(|err| {
info!("download_list_error: {}", err); info!("download_list_error: {}", err);
fs::write(&download_path, "[]").unwrap(); fs::write(&download_path, "[]").unwrap();
"[]".to_string() "[]".to_string()
}); });
let mut list = serde_json::from_str::<Vec<serde_json::Value>>(&content) let list = serde_json::from_str::<Vec<serde_json::Value>>(&content).unwrap_or_else(|err| {
.unwrap_or_else(|err| { info!("download_list_parse_error: {}", err);
info!("download_list_parse_error: {}", err); vec![]
vec![] });
});
let list2 = &list; (list, download_path)
}
#[command]
pub fn download_list(pathname: &str, filename: Option<String>, id: Option<String>) {
info!("download_list: {}", pathname);
let data = get_download_list(pathname);
let mut list = vec![];
let mut my_hashmap = HashMap::new(); let mut my_hashmap = HashMap::new();
utils::vec_to_hashmap(list2.clone().into_iter(), "id", &mut my_hashmap); utils::vec_to_hashmap(data.0.into_iter(), "id", &mut my_hashmap);
for entry in WalkDir::new(utils::chat_root().join("download")) for entry in WalkDir::new(utils::chat_root().join("download"))
.into_iter() .into_iter()
@@ -236,15 +242,14 @@ pub fn download_list(filename: Option<String>, id: Option<String>) {
} }
} }
dbg!(&list); // dbg!(&list);
list.sort_by(|a, b| { list.sort_by(|a, b| {
let a1 = a.get("created").unwrap().as_u64().unwrap(); let a1 = a.get("created").unwrap().as_u64().unwrap();
let b1 = b.get("created").unwrap().as_u64().unwrap(); let b1 = b.get("created").unwrap().as_u64().unwrap();
a1.cmp(&b1).reverse() a1.cmp(&b1).reverse()
}); });
fs::write(download_path, serde_json::to_string_pretty(&list).unwrap()).unwrap(); fs::write(data.1, serde_json::to_string_pretty(&list).unwrap()).unwrap();
} }
#[command] #[command]

View File

@@ -30,7 +30,7 @@ async fn main() {
trace: Color::Cyan, trace: Color::Cyan,
}; };
cmd::download_list(None, None); cmd::download_list("chat.download.json", None, None);
let chat_conf = ChatConfJson::get_chat_conf(); let chat_conf = ChatConfJson::get_chat_conf();
@@ -76,6 +76,7 @@ async fn main() {
cmd::dalle2_window, cmd::dalle2_window,
cmd::cmd_list, cmd::cmd_list,
cmd::download_list, cmd::download_list,
cmd::get_download_list,
fs_extra::metadata, fs_extra::metadata,
]) ])
.setup(setup::init) .setup(setup::init)

17
src/hooks/useJson.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
import { useState } from 'react';
import { readJSON } from '@/utils';
import useInit from '@/hooks/useInit';
export default function useJson<T>(file: string) {
const [json, setData] = useState<T>();
const refreshJson = async () => {
const data = await readJSON(file);
setData(data);
};
useInit(refreshJson);
return { json, refreshJson };
}

1
src/utils.ts vendored
View File

@@ -4,6 +4,7 @@ import dayjs from 'dayjs';
export const CHAT_MODEL_JSON = 'chat.model.json'; export const CHAT_MODEL_JSON = 'chat.model.json';
export const CHAT_MODEL_CMD_JSON = 'chat.model.cmd.json'; export const CHAT_MODEL_CMD_JSON = 'chat.model.cmd.json';
export const CHAT_DOWNLOAD_JSON = 'chat.download.json';
export const CHAT_PROMPTS_CSV = 'chat.prompts.csv'; export const CHAT_PROMPTS_CSV = 'chat.prompts.csv';
export const GITHUB_PROMPTS_CSV_URL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv'; export const GITHUB_PROMPTS_CSV_URL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv';
export const DISABLE_AUTO_COMPLETE = { export const DISABLE_AUTO_COMPLETE = {

View File

@@ -1,28 +1,37 @@
import { Switch, Tag, Tooltip, Space, Popconfirm } from 'antd'; import { Tag, Space, Popconfirm } from 'antd';
import { fmtDate } from '@/utils';
const colorMap: any = {
pdf: 'blue',
png: 'orange',
}
export const syncColumns = () => [ export const syncColumns = () => [
{ {
title: 'Name', title: 'Name',
dataIndex: 'name', dataIndex: 'name',
fixed: 'left', fixed: 'left',
// width: 120,
key: 'name', key: 'name',
}, },
{ {
title: 'Type', title: 'Extension',
dataIndex: 'type', dataIndex: 'ext',
key: 'type', key: 'ext',
render: () => { render: (v: string) => <Tag color={colorMap[v]}>{v}</Tag>,
return <Tag>{}</Tag>; },
} {
// width: 200, title: 'Created',
dataIndex: 'created',
key: 'created',
render: fmtDate,
}, },
{ {
title: 'Action', title: 'Action',
render: (_: any, row: any, actions: any) => { render: (_: any, row: any, actions: any) => {
return ( return (
<Space> <Space>
<a>View</a> <a onClick={() => actions.setRecord(row, 'view')}>View</a>
<Popconfirm <Popconfirm
title="Are you sure to delete this file?" title="Are you sure to delete this file?"
onConfirm={() => actions.setRecord(row, 'delete')} onConfirm={() => actions.setRecord(row, 'delete')}

View File

@@ -1,27 +1,52 @@
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { Table } from 'antd'; import { Table, Modal } from 'antd';
import { path, shell } from '@tauri-apps/api'; import { path, shell, fs } from '@tauri-apps/api';
import useInit from '@/hooks/useInit'; import useInit from '@/hooks/useInit';
import useJson from '@/hooks/useJson';
import useColumns from '@/hooks/useColumns'; import useColumns from '@/hooks/useColumns';
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable'; import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
import { chatRoot, readJSON } from '@/utils'; import { chatRoot, CHAT_DOWNLOAD_JSON } from '@/utils';
import { syncColumns } from './config'; import { syncColumns } from './config';
import './index.scss'; import './index.scss';
function renderFile(buff: Uint8Array, type: string) {
const renderType = {
pdf: 'application/pdf',
png: 'image/png',
}[type];
return URL.createObjectURL(new Blob([buff], { type: renderType }));
}
export default function SyncPrompts() { export default function SyncPrompts() {
const { rowSelection, selectedRowIDs } = useTable(); const { rowSelection, selectedRowIDs } = useTable();
const [downloadPath, setDownloadPath] = useState('');
const [downloadData, setDownloadData] = useState([]);
const { columns, ...opInfo } = useColumns(syncColumns()); const { columns, ...opInfo } = useColumns(syncColumns());
const [downloadPath, setDownloadPath] = useState('');
const { json } = useJson<any[]>(CHAT_DOWNLOAD_JSON);
const [source, setSource] = useState('');
const [isVisible, setVisible] = useState(false);
useInit(async () => { useInit(async () => {
const file = await path.join(await chatRoot(), 'chat.download.json'); const file = await path.join(await chatRoot(), 'chat.download.json');
setDownloadPath(file); setDownloadPath(file);
const data = await readJSON(file, { isRoot: true, isList: true });
setDownloadData(data);
}); });
useEffect(() => {
if (!opInfo.opType) return;
(async () => {
const record = opInfo?.opRecord;
const isImg = ['png'].includes(record?.ext);
const file = await path.join(await chatRoot(), 'download', isImg ? 'img' : record?.ext, `${record?.id}.${record?.ext}`);
if (opInfo.opType === 'view') {
const data = await fs.readBinaryFile(file);
const sourceData = renderFile(data, record?.ext);
setSource(sourceData);
setVisible(true);
}
opInfo.resetRecord();
})()
}, [opInfo.opType])
return ( return (
<div> <div>
<div className="chat-table-tip"> <div className="chat-table-tip">
@@ -33,10 +58,18 @@ export default function SyncPrompts() {
rowKey="name" rowKey="name"
columns={columns} columns={columns}
scroll={{ x: 'auto' }} scroll={{ x: 'auto' }}
dataSource={downloadData} dataSource={json}
rowSelection={rowSelection} rowSelection={rowSelection}
pagination={TABLE_PAGINATION} pagination={TABLE_PAGINATION}
/> />
<Modal
open={isVisible}
onCancel={() => setVisible(false)}
footer={false}
destroyOnClose
>
<img style={{ maxWidth: '100%' }} src={source} />
</Modal>
</div> </div>
) )
} }