mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
chore: sync
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^4.8.0",
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"antd": "^5.0.6",
|
||||
"antd": "^5.1.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -19,9 +19,11 @@ serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
|
||||
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
|
||||
tokio = { version = "1.23.0", features = ["macros"] }
|
||||
log = "0.4.17"
|
||||
csv = "1.1.6"
|
||||
thiserror = "1.0.38"
|
||||
reqwest = "0.11.13"
|
||||
|
||||
[dependencies.tauri-plugin-log]
|
||||
git = "https://github.com/tauri-apps/tauri-plugin-log"
|
||||
|
||||
@@ -88,3 +88,12 @@ pub fn parse_prompt(data: String) -> Vec<PromptRecord> {
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
#[command]
|
||||
pub fn window_reload(app: AppHandle, label: &str) {
|
||||
app.app_handle()
|
||||
.get_window(label)
|
||||
.unwrap()
|
||||
.eval("window.location.reload()")
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ pub fn init() -> Menu {
|
||||
let preferences_menu = Submenu::new(
|
||||
"Preferences",
|
||||
Menu::with_items([
|
||||
CustomMenuItem::new("control_center".to_string(), "Control Center")
|
||||
.accelerator("CmdOrCtrl+Shift+P")
|
||||
.into(),
|
||||
MenuItem::Separator.into(),
|
||||
Submenu::new(
|
||||
"Theme",
|
||||
Menu::new()
|
||||
@@ -67,13 +71,11 @@ pub fn init() -> Menu {
|
||||
titlebar_menu.into(),
|
||||
#[cfg(target_os = "macos")]
|
||||
CustomMenuItem::new("hide_dock_icon".to_string(), "Hide Dock Icon").into(),
|
||||
MenuItem::Separator.into(),
|
||||
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
|
||||
.accelerator("CmdOrCtrl+J")
|
||||
.into(),
|
||||
CustomMenuItem::new("control_center".to_string(), "Control Center")
|
||||
.accelerator("CmdOrCtrl+Shift+P")
|
||||
.into(),
|
||||
MenuItem::Separator.into(),
|
||||
CustomMenuItem::new("sync_prompts".to_string(), "Sync Prompts").into(),
|
||||
MenuItem::Separator.into(),
|
||||
CustomMenuItem::new("go_conf".to_string(), "Go to Config")
|
||||
.accelerator("CmdOrCtrl+Shift+G")
|
||||
@@ -178,6 +180,21 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
||||
"go_conf" => utils::open_file(utils::chat_root()),
|
||||
"clear_conf" => utils::clear_conf(&app),
|
||||
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
|
||||
"sync_prompts" => {
|
||||
tauri::api::dialog::ask(
|
||||
app.get_window("main").as_ref(),
|
||||
"Sync Prompts",
|
||||
"Data sync will enable all prompts, are you sure you want to sync?",
|
||||
move |is_restart| {
|
||||
if is_restart {
|
||||
app.get_window("main")
|
||||
.unwrap()
|
||||
.eval("window.__sync_prompts && window.__sync_prompts()")
|
||||
.unwrap()
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
"hide_dock_icon" => {
|
||||
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app)).unwrap()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ use tauri_plugin_log::{
|
||||
LogTarget, LoggerBuilder,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
ChatConfJson::init();
|
||||
let chat_conf = ChatConfJson::get_chat_conf();
|
||||
let context = tauri::generate_context!();
|
||||
@@ -59,6 +60,7 @@ fn main() {
|
||||
cmd::open_file,
|
||||
cmd::get_chat_model,
|
||||
cmd::parse_prompt,
|
||||
cmd::window_reload,
|
||||
fs_extra::metadata,
|
||||
])
|
||||
.setup(setup::init)
|
||||
|
||||
2
src/hooks/useChatModel.ts
vendored
2
src/hooks/useChatModel.ts
vendored
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { clone } from 'lodash';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
|
||||
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
||||
import useInit from '@/hooks/useInit';
|
||||
@@ -16,6 +17,7 @@ export default function useChatModel(key: string) {
|
||||
const oData = clone(modelJson);
|
||||
oData[key] = data;
|
||||
await writeJSON(CHAT_MODEL_JSON, oData);
|
||||
await invoke('window_reload', { label: 'core' });
|
||||
setModelJson(oData);
|
||||
}
|
||||
|
||||
|
||||
28
src/hooks/useEvent.ts
vendored
Normal file
28
src/hooks/useEvent.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { invoke, http, fs, dialog } from '@tauri-apps/api';
|
||||
|
||||
import useInit from '@/hooks/useInit';
|
||||
import useChatModel from '@/hooks/useChatModel';
|
||||
import { GITHUB_PROMPTS_CSV_URL, chatPromptsPath, genCmd } from '@/utils';
|
||||
|
||||
export default function useEvent() {
|
||||
const { modelSet } = useChatModel('sys_sync_prompts');
|
||||
// Using `emit` and `listen` will be triggered multiple times in development mode.
|
||||
// So here we use `eval` to call `__sync_prompt`
|
||||
useInit(() => {
|
||||
(window as any).__sync_prompts = async () => {
|
||||
const res = await http.fetch(GITHUB_PROMPTS_CSV_URL, {
|
||||
method: 'GET',
|
||||
responseType: http.ResponseType.Text,
|
||||
});
|
||||
const data = (res.data || '') as string;
|
||||
if (res.ok) {
|
||||
await fs.writeTextFile(await chatPromptsPath(), data);
|
||||
const list: Record<string, string>[] = await invoke('parse_prompt', { data });
|
||||
modelSet(list.map(i => ({ cmd: genCmd(i.act), enable: true, tags: ['chatgpt-prompts'], ...i })));
|
||||
dialog.message('ChatGPT Prompts data has been synchronized!');
|
||||
} else {
|
||||
dialog.message('ChatGPT Prompts data sync failed, please try again!');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
1
src/layout/index.tsx
vendored
1
src/layout/index.tsx
vendored
@@ -39,6 +39,7 @@ const ChatLayout: FC<ChatLayoutProps> = ({ children }) => {
|
||||
mode="inline"
|
||||
inlineIndent={12}
|
||||
items={menuItems}
|
||||
defaultOpenKeys={['/model']}
|
||||
onClick={(i) => go(i.key)}
|
||||
/>
|
||||
</Sider>
|
||||
|
||||
14
src/main.tsx
vendored
14
src/main.tsx
vendored
@@ -2,15 +2,23 @@ import { StrictMode, Suspense } from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
|
||||
import useEvent from '@/hooks/useEvent';
|
||||
import Layout from '@/layout';
|
||||
import './main.scss';
|
||||
|
||||
const App = () => {
|
||||
useEvent();
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Layout/>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<StrictMode>
|
||||
<Suspense fallback={null}>
|
||||
<BrowserRouter>
|
||||
<Layout/>
|
||||
</BrowserRouter>
|
||||
<App />
|
||||
</Suspense>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
10
src/routes.tsx
vendored
10
src/routes.tsx
vendored
@@ -9,9 +9,9 @@ import {
|
||||
import type { MenuProps } from 'antd';
|
||||
|
||||
import General from '@view/General';
|
||||
import LanguageModel from '@/view/LanguageModel';
|
||||
import SyncPrompts from '@/view/SyncPrompts';
|
||||
import SyncMore from '@/view/SyncMore';
|
||||
import UserCustom from '@/view/model/UserCustom';
|
||||
import SyncPrompts from '@/view/model/SyncPrompts';
|
||||
import SyncMore from '@/view/model/SyncMore';
|
||||
|
||||
export type ChatRouteMetaObject = {
|
||||
label: string;
|
||||
@@ -35,7 +35,7 @@ export const routes: Array<ChatRouteObject> = [
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/language-model',
|
||||
path: '/model',
|
||||
meta: {
|
||||
label: 'Language Model',
|
||||
icon: <BulbOutlined />,
|
||||
@@ -43,7 +43,7 @@ export const routes: Array<ChatRouteObject> = [
|
||||
children: [
|
||||
{
|
||||
path: 'user-custom',
|
||||
element: <LanguageModel />,
|
||||
element: <UserCustom />,
|
||||
meta: {
|
||||
label: 'User Custom',
|
||||
icon: <UserOutlined />,
|
||||
|
||||
2
src/utils.ts
vendored
2
src/utils.ts
vendored
@@ -49,3 +49,5 @@ export const writeJSON = async (path: string, data: Record<string, any>) => {
|
||||
}
|
||||
|
||||
export const fmtDate = (date: any) => dayjs(date).format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
export const genCmd = (act: string) => act.replace(/\s+|\/+/g, '_').replace(/[^\d\w]/g, '').toLocaleLowerCase();
|
||||
22
src/view/SyncMore/config.tsx
vendored
22
src/view/SyncMore/config.tsx
vendored
@@ -1,22 +0,0 @@
|
||||
// import { Switch, Tag, Tooltip } from 'antd';
|
||||
|
||||
export const genCmd = (act: string) => act.replace(/\s+|\/+/g, '_').replace(/[^\d\w]/g, '').toLocaleLowerCase();
|
||||
|
||||
export const recordColumns = () => [
|
||||
{
|
||||
title: 'URL',
|
||||
dataIndex: 'url',
|
||||
// fixed: 'left',
|
||||
// width: 120,
|
||||
key: 'url',
|
||||
},
|
||||
{
|
||||
title: 'File Type',
|
||||
dataIndex: 'file_type',
|
||||
key: 'file_type',
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
}
|
||||
];
|
||||
15
src/view/model/SyncMore/config.tsx
vendored
Normal file
15
src/view/model/SyncMore/config.tsx
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export const recordColumns = () => [
|
||||
{
|
||||
title: 'URL',
|
||||
dataIndex: 'url',
|
||||
key: 'url',
|
||||
},
|
||||
{
|
||||
title: 'File Type',
|
||||
dataIndex: 'file_type',
|
||||
key: 'file_type',
|
||||
},
|
||||
{
|
||||
title: 'Action',
|
||||
}
|
||||
];
|
||||
@@ -9,7 +9,7 @@ export default function SyncMore() {
|
||||
<Button className="add-btn" type="primary">Add URL</Button>
|
||||
<Table
|
||||
key="id"
|
||||
rowKey="act"
|
||||
rowKey="url"
|
||||
columns={[]}
|
||||
scroll={{ x: 'auto' }}
|
||||
dataSource={[]}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Switch, Tag, Tooltip } from 'antd';
|
||||
|
||||
export const genCmd = (act: string) => act.replace(/\s+|\/+/g, '_').replace(/[^\d\w]/g, '').toLocaleLowerCase();
|
||||
import { genCmd } from '@/utils';
|
||||
|
||||
export const modelColumns = () => [
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Table, Button, message } from 'antd';
|
||||
import { Table, Button, message, Popconfirm } from 'antd';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { fetch, ResponseType } from '@tauri-apps/api/http';
|
||||
import { writeTextFile } from '@tauri-apps/api/fs';
|
||||
@@ -8,15 +8,14 @@ import useColumns from '@/hooks/useColumns';
|
||||
import useData from '@/hooks/useData';
|
||||
import useChatModel from '@/hooks/useChatModel';
|
||||
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL } from '@/utils';
|
||||
import { modelColumns, genCmd } from './config';
|
||||
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL, genCmd } from '@/utils';
|
||||
import { modelColumns } from './config';
|
||||
import './index.scss';
|
||||
|
||||
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
||||
|
||||
export default function LanguageModel() {
|
||||
const { rowSelection, selectedRowIDs } = useTable();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [lastUpdated, setLastUpdated] = useState();
|
||||
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
||||
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
||||
@@ -35,7 +34,6 @@ export default function LanguageModel() {
|
||||
}, [modelJson?.sys_sync_prompts])
|
||||
|
||||
const handleSync = async () => {
|
||||
setLoading(true);
|
||||
const res = await fetch(GITHUB_PROMPTS_CSV_URL, {
|
||||
method: 'GET',
|
||||
responseType: ResponseType.Text,
|
||||
@@ -52,7 +50,6 @@ export default function LanguageModel() {
|
||||
} else {
|
||||
message.error('ChatGPT Prompts data sync failed, please try again!');
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -79,7 +76,15 @@ export default function LanguageModel() {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Button type="primary" loading={loading} onClick={handleSync}>Sync</Button>
|
||||
<Popconfirm
|
||||
title={<span>Data sync will enable all prompts,<br/>are you sure you want to sync?</span>}
|
||||
placement="topLeft"
|
||||
onConfirm={handleSync}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
>
|
||||
<Button type="primary">Sync</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
<div className="chat-table-tip">
|
||||
<span className="chat-model-path">URL: <a href={promptsURL} target="_blank" title={promptsURL}>f/awesome-chatgpt-prompts/prompts.csv</a></span>
|
||||
@@ -7,7 +7,7 @@ import useData from '@/hooks/useData';
|
||||
import useChatModel from '@/hooks/useChatModel';
|
||||
import useColumns from '@/hooks/useColumns';
|
||||
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||
import { chatModelPath } from '@/utils';
|
||||
import { chatModelPath, genCmd } from '@/utils';
|
||||
import { modelColumns } from './config';
|
||||
import LanguageModelForm from './Form';
|
||||
import './index.scss';
|
||||
Reference in New Issue
Block a user