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": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^4.8.0",
|
"@ant-design/icons": "^4.8.0",
|
||||||
"@tauri-apps/api": "^1.2.0",
|
"@tauri-apps/api": "^1.2.0",
|
||||||
"antd": "^5.0.6",
|
"antd": "^5.1.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ serde_json = "1.0"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
|
tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
|
||||||
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
|
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
|
||||||
|
tokio = { version = "1.23.0", features = ["macros"] }
|
||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
csv = "1.1.6"
|
csv = "1.1.6"
|
||||||
thiserror = "1.0.38"
|
thiserror = "1.0.38"
|
||||||
|
reqwest = "0.11.13"
|
||||||
|
|
||||||
[dependencies.tauri-plugin-log]
|
[dependencies.tauri-plugin-log]
|
||||||
git = "https://github.com/tauri-apps/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
|
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(
|
let preferences_menu = Submenu::new(
|
||||||
"Preferences",
|
"Preferences",
|
||||||
Menu::with_items([
|
Menu::with_items([
|
||||||
|
CustomMenuItem::new("control_center".to_string(), "Control Center")
|
||||||
|
.accelerator("CmdOrCtrl+Shift+P")
|
||||||
|
.into(),
|
||||||
|
MenuItem::Separator.into(),
|
||||||
Submenu::new(
|
Submenu::new(
|
||||||
"Theme",
|
"Theme",
|
||||||
Menu::new()
|
Menu::new()
|
||||||
@@ -67,13 +71,11 @@ pub fn init() -> Menu {
|
|||||||
titlebar_menu.into(),
|
titlebar_menu.into(),
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
CustomMenuItem::new("hide_dock_icon".to_string(), "Hide Dock Icon").into(),
|
CustomMenuItem::new("hide_dock_icon".to_string(), "Hide Dock Icon").into(),
|
||||||
MenuItem::Separator.into(),
|
|
||||||
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
|
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
|
||||||
.accelerator("CmdOrCtrl+J")
|
.accelerator("CmdOrCtrl+J")
|
||||||
.into(),
|
.into(),
|
||||||
CustomMenuItem::new("control_center".to_string(), "Control Center")
|
MenuItem::Separator.into(),
|
||||||
.accelerator("CmdOrCtrl+Shift+P")
|
CustomMenuItem::new("sync_prompts".to_string(), "Sync Prompts").into(),
|
||||||
.into(),
|
|
||||||
MenuItem::Separator.into(),
|
MenuItem::Separator.into(),
|
||||||
CustomMenuItem::new("go_conf".to_string(), "Go to Config")
|
CustomMenuItem::new("go_conf".to_string(), "Go to Config")
|
||||||
.accelerator("CmdOrCtrl+Shift+G")
|
.accelerator("CmdOrCtrl+Shift+G")
|
||||||
@@ -178,6 +180,21 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
"go_conf" => utils::open_file(utils::chat_root()),
|
"go_conf" => utils::open_file(utils::chat_root()),
|
||||||
"clear_conf" => utils::clear_conf(&app),
|
"clear_conf" => utils::clear_conf(&app),
|
||||||
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
|
"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" => {
|
"hide_dock_icon" => {
|
||||||
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app)).unwrap()
|
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app)).unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ use tauri_plugin_log::{
|
|||||||
LogTarget, LoggerBuilder,
|
LogTarget, LoggerBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
ChatConfJson::init();
|
ChatConfJson::init();
|
||||||
let chat_conf = ChatConfJson::get_chat_conf();
|
let chat_conf = ChatConfJson::get_chat_conf();
|
||||||
let context = tauri::generate_context!();
|
let context = tauri::generate_context!();
|
||||||
@@ -59,6 +60,7 @@ fn main() {
|
|||||||
cmd::open_file,
|
cmd::open_file,
|
||||||
cmd::get_chat_model,
|
cmd::get_chat_model,
|
||||||
cmd::parse_prompt,
|
cmd::parse_prompt,
|
||||||
|
cmd::window_reload,
|
||||||
fs_extra::metadata,
|
fs_extra::metadata,
|
||||||
])
|
])
|
||||||
.setup(setup::init)
|
.setup(setup::init)
|
||||||
|
|||||||
2
src/hooks/useChatModel.ts
vendored
2
src/hooks/useChatModel.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { clone } from 'lodash';
|
import { clone } from 'lodash';
|
||||||
|
import { invoke } from '@tauri-apps/api';
|
||||||
|
|
||||||
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
import { CHAT_MODEL_JSON, readJSON, writeJSON } from '@/utils';
|
||||||
import useInit from '@/hooks/useInit';
|
import useInit from '@/hooks/useInit';
|
||||||
@@ -16,6 +17,7 @@ export default function useChatModel(key: string) {
|
|||||||
const oData = clone(modelJson);
|
const oData = clone(modelJson);
|
||||||
oData[key] = data;
|
oData[key] = data;
|
||||||
await writeJSON(CHAT_MODEL_JSON, oData);
|
await writeJSON(CHAT_MODEL_JSON, oData);
|
||||||
|
await invoke('window_reload', { label: 'core' });
|
||||||
setModelJson(oData);
|
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"
|
mode="inline"
|
||||||
inlineIndent={12}
|
inlineIndent={12}
|
||||||
items={menuItems}
|
items={menuItems}
|
||||||
|
defaultOpenKeys={['/model']}
|
||||||
onClick={(i) => go(i.key)}
|
onClick={(i) => go(i.key)}
|
||||||
/>
|
/>
|
||||||
</Sider>
|
</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 { BrowserRouter } from 'react-router-dom';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
|
import useEvent from '@/hooks/useEvent';
|
||||||
import Layout from '@/layout';
|
import Layout from '@/layout';
|
||||||
import './main.scss';
|
import './main.scss';
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
useEvent();
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<Layout/>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<BrowserRouter>
|
<App />
|
||||||
<Layout/>
|
|
||||||
</BrowserRouter>
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
|
|||||||
10
src/routes.tsx
vendored
10
src/routes.tsx
vendored
@@ -9,9 +9,9 @@ import {
|
|||||||
import type { MenuProps } from 'antd';
|
import type { MenuProps } from 'antd';
|
||||||
|
|
||||||
import General from '@view/General';
|
import General from '@view/General';
|
||||||
import LanguageModel from '@/view/LanguageModel';
|
import UserCustom from '@/view/model/UserCustom';
|
||||||
import SyncPrompts from '@/view/SyncPrompts';
|
import SyncPrompts from '@/view/model/SyncPrompts';
|
||||||
import SyncMore from '@/view/SyncMore';
|
import SyncMore from '@/view/model/SyncMore';
|
||||||
|
|
||||||
export type ChatRouteMetaObject = {
|
export type ChatRouteMetaObject = {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -35,7 +35,7 @@ export const routes: Array<ChatRouteObject> = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/language-model',
|
path: '/model',
|
||||||
meta: {
|
meta: {
|
||||||
label: 'Language Model',
|
label: 'Language Model',
|
||||||
icon: <BulbOutlined />,
|
icon: <BulbOutlined />,
|
||||||
@@ -43,7 +43,7 @@ export const routes: Array<ChatRouteObject> = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'user-custom',
|
path: 'user-custom',
|
||||||
element: <LanguageModel />,
|
element: <UserCustom />,
|
||||||
meta: {
|
meta: {
|
||||||
label: 'User Custom',
|
label: 'User Custom',
|
||||||
icon: <UserOutlined />,
|
icon: <UserOutlined />,
|
||||||
|
|||||||
4
src/utils.ts
vendored
4
src/utils.ts
vendored
@@ -48,4 +48,6 @@ export const writeJSON = async (path: string, data: Record<string, any>) => {
|
|||||||
await writeTextFile(file, JSON.stringify(data, null, 2));
|
await writeTextFile(file, JSON.stringify(data, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fmtDate = (date: any) => dayjs(date).format('YYYY-MM-DD HH:mm:ss');
|
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>
|
<Button className="add-btn" type="primary">Add URL</Button>
|
||||||
<Table
|
<Table
|
||||||
key="id"
|
key="id"
|
||||||
rowKey="act"
|
rowKey="url"
|
||||||
columns={[]}
|
columns={[]}
|
||||||
scroll={{ x: 'auto' }}
|
scroll={{ x: 'auto' }}
|
||||||
dataSource={[]}
|
dataSource={[]}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Switch, Tag, Tooltip } from 'antd';
|
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 = () => [
|
export const modelColumns = () => [
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react';
|
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 { invoke } from '@tauri-apps/api';
|
||||||
import { fetch, ResponseType } from '@tauri-apps/api/http';
|
import { fetch, ResponseType } from '@tauri-apps/api/http';
|
||||||
import { writeTextFile } from '@tauri-apps/api/fs';
|
import { writeTextFile } from '@tauri-apps/api/fs';
|
||||||
@@ -8,15 +8,14 @@ import useColumns from '@/hooks/useColumns';
|
|||||||
import useData from '@/hooks/useData';
|
import useData from '@/hooks/useData';
|
||||||
import useChatModel from '@/hooks/useChatModel';
|
import useChatModel from '@/hooks/useChatModel';
|
||||||
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
import useTable, { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL } from '@/utils';
|
import { fmtDate, chatPromptsPath, GITHUB_PROMPTS_CSV_URL, genCmd } from '@/utils';
|
||||||
import { modelColumns, genCmd } from './config';
|
import { modelColumns } from './config';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
const promptsURL = 'https://github.com/f/awesome-chatgpt-prompts/blob/main/prompts.csv';
|
||||||
|
|
||||||
export default function LanguageModel() {
|
export default function LanguageModel() {
|
||||||
const { rowSelection, selectedRowIDs } = useTable();
|
const { rowSelection, selectedRowIDs } = useTable();
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [lastUpdated, setLastUpdated] = useState();
|
const [lastUpdated, setLastUpdated] = useState();
|
||||||
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
const { modelJson, modelSet } = useChatModel('sys_sync_prompts');
|
||||||
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
const { opData, opInit, opReplace, opReplaceItems, opSafeKey } = useData([]);
|
||||||
@@ -35,7 +34,6 @@ export default function LanguageModel() {
|
|||||||
}, [modelJson?.sys_sync_prompts])
|
}, [modelJson?.sys_sync_prompts])
|
||||||
|
|
||||||
const handleSync = async () => {
|
const handleSync = async () => {
|
||||||
setLoading(true);
|
|
||||||
const res = await fetch(GITHUB_PROMPTS_CSV_URL, {
|
const res = await fetch(GITHUB_PROMPTS_CSV_URL, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
responseType: ResponseType.Text,
|
responseType: ResponseType.Text,
|
||||||
@@ -52,7 +50,6 @@ export default function LanguageModel() {
|
|||||||
} else {
|
} else {
|
||||||
message.error('ChatGPT Prompts data sync failed, please try again!');
|
message.error('ChatGPT Prompts data sync failed, please try again!');
|
||||||
}
|
}
|
||||||
setLoading(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -79,7 +76,15 @@ export default function LanguageModel() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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>
|
||||||
<div className="chat-table-tip">
|
<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>
|
<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 useChatModel from '@/hooks/useChatModel';
|
||||||
import useColumns from '@/hooks/useColumns';
|
import useColumns from '@/hooks/useColumns';
|
||||||
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
import { TABLE_PAGINATION } from '@/hooks/useTable';
|
||||||
import { chatModelPath } from '@/utils';
|
import { chatModelPath, genCmd } from '@/utils';
|
||||||
import { modelColumns } from './config';
|
import { modelColumns } from './config';
|
||||||
import LanguageModelForm from './Form';
|
import LanguageModelForm from './Form';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
Reference in New Issue
Block a user