diff --git a/src/main.scss b/src/main.scss
index 8ac1c5b..cd4b9de 100644
--- a/src/main.scss
+++ b/src/main.scss
@@ -114,3 +114,25 @@ body,
cursor: pointer;
}
}
+
+.editor-task {
+ margin-bottom: 5px;
+ display: flex;
+ justify-content: space-between;
+
+ .ant-breadcrumb-link {
+ padding: 3px 5px;
+ transition: all 300ms ease;
+ border-radius: 4px;
+ &:hover {
+ color: rgba(0, 0, 0, 0.88);
+ background-color: rgba(0, 0, 0, 0.06);
+ cursor: pointer;
+ }
+ }
+
+ .editor-btn {
+ cursor: pointer;
+ margin-left: 5px;
+ }
+}
diff --git a/src/routes.tsx b/src/routes.tsx
index 9206c29..e310f19 100644
--- a/src/routes.tsx
+++ b/src/routes.tsx
@@ -14,6 +14,7 @@ import type { MenuProps } from 'antd';
import Settings from '@/view/settings';
import About from '@/view/about';
import Scripts from '@/view/scripts';
+import ScriptsEditor from '@/view/scripts/Editor';
import UserCustom from '@/view/prompts/UserCustom';
import SyncPrompts from '@/view/prompts/SyncPrompts';
import SyncCustom from '@/view/prompts/SyncCustom';
@@ -103,6 +104,11 @@ export const routes: Array
= [
icon: ,
},
},
+ {
+ path: '/scripts/:id',
+ element: ,
+ hideMenu: true,
+ },
{
path: '/about',
element: ,
diff --git a/src/utils.ts b/src/utils.ts
index 7bf47bb..45e5f9c 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -23,6 +23,10 @@ export const chatRoot = async () => {
return join(await homeDir(), '.chatgpt');
};
+export const scriptRoot = async () => {
+ return join(await chatRoot(), 'scripts');
+};
+
export const chatPromptPath = async (): Promise => {
return join(await chatRoot(), CHAT_PROMPT_JSON);
};
diff --git a/src/view/markdown/index.scss b/src/view/markdown/index.scss
deleted file mode 100644
index 964eb74..0000000
--- a/src/view/markdown/index.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-.md-task {
- margin-bottom: 5px;
- display: flex;
- justify-content: space-between;
-
- .ant-breadcrumb-link {
- padding: 3px 5px;
- transition: all 300ms ease;
- border-radius: 4px;
- &:hover {
- color: rgba(0, 0, 0, 0.88);
- background-color: rgba(0, 0, 0, 0.06);
- cursor: pointer;
- }
- }
-}
diff --git a/src/view/markdown/index.tsx b/src/view/markdown/index.tsx
index 292c7e2..8ed5f5d 100644
--- a/src/view/markdown/index.tsx
+++ b/src/view/markdown/index.tsx
@@ -8,7 +8,6 @@ import { fs, shell } from '@tauri-apps/api';
import useInit from '@/hooks/useInit';
import SplitIcon from '@/icons/SplitIcon';
import { getPath } from '@/view/notes/config';
-import './index.scss';
const modeMap: any = {
0: 'split',
@@ -41,7 +40,7 @@ export default function Markdown() {
return (
<>
-
+
history.go(-1)}>
diff --git a/src/view/notes/config.tsx b/src/view/notes/config.tsx
index fa100ac..7e26367 100644
--- a/src/view/notes/config.tsx
+++ b/src/view/notes/config.tsx
@@ -67,5 +67,5 @@ const RenderPath = ({ row }: any) => {
};
export const getPath = async (row: any) => {
- return (await path.join(await chatRoot(), 'notes', row.id)) + `.${row.ext}`;
+ return await path.join(await chatRoot(), 'notes', `${row.id}.md`);
};
diff --git a/src/view/prompts/SyncPrompts/config.tsx b/src/view/prompts/SyncPrompts/config.tsx
index b6381de..0896e07 100644
--- a/src/view/prompts/SyncPrompts/config.tsx
+++ b/src/view/prompts/SyncPrompts/config.tsx
@@ -7,7 +7,6 @@ export const syncColumns = () => [
title: '/{cmd}',
dataIndex: 'cmd',
fixed: 'left',
- // width: 120,
key: 'cmd',
render: (_: string, row: Record) => (
/{genCmd(row.act)}
@@ -17,20 +16,17 @@ export const syncColumns = () => [
title: 'Act',
dataIndex: 'act',
key: 'act',
- // width: 200,
},
{
title: 'Tags',
dataIndex: 'tags',
key: 'tags',
- // width: 150,
- render: () => chatgpt-prompts,
+ render: () => built-in,
},
{
title: 'Enable',
dataIndex: 'enable',
key: 'enable',
- // width: 80,
render: (v: boolean = false, row: Record, action: Record) => (
action.setRecord({ ...row, enable: v }, 'enable')} />
),
@@ -40,7 +36,6 @@ export const syncColumns = () => [
title: 'Prompt',
dataIndex: 'prompt',
key: 'prompt',
- // width: 300,
render: (v: string) => {v},
},
];
diff --git a/src/view/prompts/SyncPrompts/index.tsx b/src/view/prompts/SyncPrompts/index.tsx
index d588374..7b9c957 100644
--- a/src/view/prompts/SyncPrompts/index.tsx
+++ b/src/view/prompts/SyncPrompts/index.tsx
@@ -12,7 +12,8 @@ import { fmtDate, chatRoot } from '@/utils';
import { syncColumns } from './config';
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';
+const promptsURL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv';
export default function SyncPrompts() {
const { rowSelection, selectedRowIDs } = useTableRowSelection();
@@ -83,7 +84,7 @@ export default function SyncPrompts() {
-
+
{lastUpdated && (
diff --git a/src/view/prompts/SyncRecord/config.tsx b/src/view/prompts/SyncRecord/config.tsx
index 66ffd23..18a1dbe 100644
--- a/src/view/prompts/SyncRecord/config.tsx
+++ b/src/view/prompts/SyncRecord/config.tsx
@@ -7,7 +7,6 @@ export const syncColumns = () => [
title: '/{cmd}',
dataIndex: 'cmd',
fixed: 'left',
- // width: 120,
key: 'cmd',
render: (_: string, row: Record
) => (
/{row.cmd ? row.cmd : genCmd(row.act)}
@@ -17,13 +16,11 @@ export const syncColumns = () => [
title: 'Act',
dataIndex: 'act',
key: 'act',
- // width: 200,
},
{
title: 'Tags',
dataIndex: 'tags',
key: 'tags',
- // width: 150,
render: (v: string[]) => (
{v?.map((i) => (
@@ -36,7 +33,6 @@ export const syncColumns = () => [
title: 'Enable',
dataIndex: 'enable',
key: 'enable',
- // width: 80,
render: (v: boolean = false, row: Record, action: Record) => (
action.setRecord({ ...row, enable: v }, 'enable')} />
),
@@ -46,7 +42,6 @@ export const syncColumns = () => [
title: 'Prompt',
dataIndex: 'prompt',
key: 'prompt',
- // width: 300,
render: (v: string) => {v},
},
];
diff --git a/src/view/prompts/SyncRecord/index.tsx b/src/view/prompts/SyncRecord/index.tsx
index 260e83b..5f3c0ab 100644
--- a/src/view/prompts/SyncRecord/index.tsx
+++ b/src/view/prompts/SyncRecord/index.tsx
@@ -73,7 +73,7 @@ export default function SyncRecord() {
-
+
{state?.last_updated && (
diff --git a/src/view/prompts/UserCustom/Form.tsx b/src/view/prompts/UserCustom/Form.tsx
index 9d4e306..15b991b 100644
--- a/src/view/prompts/UserCustom/Form.tsx
+++ b/src/view/prompts/UserCustom/Form.tsx
@@ -45,12 +45,6 @@ const UserCustomForm: ForwardRefRenderFunction
=
>
-
-
-
-
-
-
=
>
+
+
+
+
+
+
);
};
diff --git a/src/view/scripts/Editor.tsx b/src/view/scripts/Editor.tsx
index 9546eea..401800e 100644
--- a/src/view/scripts/Editor.tsx
+++ b/src/view/scripts/Editor.tsx
@@ -1,32 +1,74 @@
-import { FC, useEffect, useState } from 'react';
+import { FC, useState } from 'react';
+import { useLocation } from 'react-router-dom';
import Editor from '@monaco-editor/react';
+import { Breadcrumb, Tag, Popconfirm } from 'antd';
+import { ArrowLeftOutlined } from '@ant-design/icons';
+import { fs, shell, dialog, process } from '@tauri-apps/api';
-interface MarkdownEditorProps {
- value?: string;
+import useInit from '@/hooks/useInit';
+import { getPath } from './config';
+
+interface ScriptEditorProps {
onChange?: (v: string) => void;
- mode?: string;
}
-const ScriptEditor: FC = ({
- value = 'console.log',
- onChange,
- mode = 'split',
-}) => {
- const [content, setContent] = useState(value);
+const ScriptEditor: FC = ({ onChange }) => {
+ const [filePath, setFilePath] = useState('');
+ const [source, setSource] = useState('// write your script here\n');
+ const location = useLocation();
+ const state = location?.state;
- useEffect(() => {
- setContent(value);
- onChange && onChange(value);
- }, [value]);
+ useInit(async () => {
+ const file = await getPath(state);
+ setFilePath(file);
+ setSource(await fs.readTextFile(file));
+ });
const handleEdit = (e: any) => {
- setContent(e);
+ setSource(e);
onChange && onChange(e);
};
+ const handleSave = async () => {
+ await fs.writeTextFile(filePath, source);
+ const isOk = await dialog.ask(
+ 'The script will take effect after the application is restarted. Do you want to restart now?',
+ {
+ title: 'Script saved successfully',
+ },
+ );
+
+ if (isOk) {
+ process.relaunch();
+ }
+ };
+
+ const handleReset = async () => {
+ setSource(await fs.readTextFile(filePath));
+ };
+
return (
-
+
+ history.go(-1)}>
+
+
+
+
+ Save
+
+
+ shell.open(filePath)}>{filePath}
+
+
);
};
diff --git a/src/view/scripts/Head.tsx b/src/view/scripts/Head.tsx
deleted file mode 100644
index 3ac7f60..0000000
--- a/src/view/scripts/Head.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import { useEffect, useState } from 'react';
-import { Tag, Collapse, Tooltip } from 'antd';
-import { EditOutlined, FileSyncOutlined } from '@ant-design/icons';
-import { path, fs, shell } from '@tauri-apps/api';
-
-import { chatRoot } from '@/utils';
-import useInit from '@/hooks/useInit';
-
-export type ScriptInfo = {
- name: string;
- filePath: string;
- file: string;
-};
-
-interface ScriptHeadProps {
- name: string;
- onEdit?: (data: ScriptInfo) => void;
- activeKey: string;
-}
-
-export default function ScriptHead({ name, onEdit, activeKey }: ScriptHeadProps) {
- const [file, setFile] = useState('');
- const [filePath, setFilePath] = useState('');
- const [editing, setEdit] = useState(false);
-
- useEffect(() => {
- if (activeKey !== name) {
- setEdit(false);
- }
- }, [activeKey]);
-
- useInit(async () => {
- const filePath = await path.join(await chatRoot(), 'scripts', name);
- setFilePath(filePath);
- const content = await fs.readTextFile(filePath);
- setFile(content);
- });
-
- const handleGoFile = () => {
- shell.open(filePath);
- };
-
- const handleEdit = async () => {
- setEdit(true);
- onEdit && onEdit({ name, filePath, file });
- };
-
- const handleCancel = async () => {
- setEdit(false);
- };
-
- const handleSave = async () => {
- setEdit(false);
- };
-
- const handleSync = async () => {};
-
- const handleURL = async () => {
- shell.open(`https://github.com/lencx/ChatGPT/blob/main/scripts/${name}`);
- };
-
- const version = '0.1.0';
- return (
- <>
-
- {version}
-
- {editing ? (
-
-
- Cancel
-
-
- Save
-
-
- ) : (
-
-
-
- )}
-
-
-
-
-
- Path: {filePath}
-
-
-
-
- URL: lencx/ChatGPT/scripts/{name}
-
-
- >
- );
-}
diff --git a/src/view/scripts/config.tsx b/src/view/scripts/config.tsx
index af459b6..1eb3b19 100644
--- a/src/view/scripts/config.tsx
+++ b/src/view/scripts/config.tsx
@@ -1,25 +1,37 @@
import { useState } from 'react';
import { Link } from 'react-router-dom';
import { Tag, Space, Popconfirm } from 'antd';
+import { ArrowRightOutlined } from '@ant-design/icons';
import { path, shell } from '@tauri-apps/api';
import useInit from '@/hooks/useInit';
import { fmtDate, chatRoot } from '@/utils';
-export const scriptColumns = () => [
+export const scriptColumns = ({ scriptsMap }: any) => [
{
title: 'File Name',
dataIndex: 'name',
key: 'name',
- width: 120,
- render: (v: string) => {v},
+ fixed: 'left',
+ width: 160,
+ render: (v: string) => {v},
},
{
title: 'Version',
- dataIndex: 'version',
- key: 'version',
- width: 120,
- render: (v: string) => {v},
+ width: 200,
+ render: (_: string, row: any) => {
+ const next = scriptsMap?.[row.name]?.next_version;
+ const curr = scriptsMap?.[row.name]?.curr_version;
+ return (
+ row.name !== 'main.js' && (
+
+ {curr && {curr}}
+ {next && next !== curr && }
+ {next && next !== curr && {next}}
+
+ )
+ );
+ },
},
{
title: 'Path',
@@ -28,6 +40,14 @@ export const scriptColumns = () => [
width: 200,
render: (_: string, row: any) => ,
},
+ {
+ title: 'Remote File',
+ width: 200,
+ render: (_: string, row: any) => {
+ const uri = `https://raw.githubusercontent.com/lencx/ChatGPT/main/scripts/${row.name}`;
+ return shell.open(uri)}>{uri};
+ },
+ },
{
title: 'Created',
dataIndex: 'created',
@@ -38,28 +58,41 @@ export const scriptColumns = () => [
{
title: 'Action',
fixed: 'right',
- width: 160,
+ width: 100,
render: (_: any, row: any, actions: any) => {
+ const isExternal = row.name === 'main.js';
+
+ const next = scriptsMap?.[row.name]?.next_version;
+ const curr = scriptsMap?.[row.name]?.curr_version;
+
return (
-
+
Edit
- actions.setRecord(row, 'sync')}
- okText="Yes"
- cancelText="No"
- >
- Sync
-
+ {!isExternal && next && next !== curr && (
+ actions.setRecord(row, 'sync')}
+ okText="Yes"
+ cancelText="No"
+ overlayStyle={{ width: 300 }}
+ >
+ Sync
+
+ )}
);
},
},
];
-const RenderPath = ({ row }: any) => {
+export const RenderPath = ({ row }: any) => {
const [filePath, setFilePath] = useState('');
useInit(async () => {
setFilePath(await getPath(row));
@@ -68,5 +101,5 @@ const RenderPath = ({ row }: any) => {
};
export const getPath = async (row: any) => {
- return (await path.join(await chatRoot(), 'notes', row.id)) + `.${row.ext}`;
+ return await path.join(await chatRoot(), 'scripts', `${row.name}`);
};
diff --git a/src/view/scripts/index.scss b/src/view/scripts/index.scss
deleted file mode 100644
index 26dcc78..0000000
--- a/src/view/scripts/index.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-.chatgpt-script {
- .ant-collapse-header {
- user-select: none;
- -webkit-user-select: none;
- }
-}
-
-.script-editor {
- height: 300px;
-}
diff --git a/src/view/scripts/index.tsx b/src/view/scripts/index.tsx
index c46066b..acc5b6e 100644
--- a/src/view/scripts/index.tsx
+++ b/src/view/scripts/index.tsx
@@ -1,17 +1,15 @@
-import { useState } from 'react';
-import { Table, Tag } from 'antd';
+import { useEffect, useState } from 'react';
+import { Table } from 'antd';
+import { path, fs, invoke } from '@tauri-apps/api';
-import useData from '@/hooks/useData';
+import useInit from '@/hooks/useInit';
import useColumns from '@/hooks/useColumns';
-import { useTableRowSelection, TABLE_PAGINATION } from '@/hooks/useTable';
+import { TABLE_PAGINATION } from '@/hooks/useTable';
+import { scriptRoot } from '@/utils';
import { scriptColumns } from './config';
-import ScriptHead, { type ScriptInfo } from './Head';
-import ScriptEditor from './Editor';
-import './index.scss';
-
-// const { Panel } = Collapse;
const SCRIPTS = [
+ 'main.js',
'core.js',
'chat.js',
'cmd.js',
@@ -22,51 +20,54 @@ const SCRIPTS = [
];
export default function Scripts() {
- const [activeKey, setActiveKey] = useState('core.js');
+ const [scriptsMap, setScriptsMap] = useState({});
+ const { columns, ...opInfo } = useColumns(scriptColumns({ scriptsMap }));
- const { columns, ...opInfo } = useColumns(scriptColumns());
+ const handleInit = async () => {
+ try {
+ const manifestPath = await path.join(await scriptRoot(), 'manifest.json');
+ const data = await fs.readTextFile(manifestPath);
+ const { scripts } = JSON.parse(data);
+ const infoMap: Record = {};
- const handleActiveKeyChange = (key: any) => {
- setActiveKey(key);
+ for (const script of scripts) {
+ const scriptInfo: any = await invoke('get_script_info', { name: script.name });
+ infoMap[script.name] = {
+ curr_version: scriptInfo?.version,
+ next_version: script.version,
+ };
+ }
+ setScriptsMap(infoMap);
+ } catch (error) {
+ console.error(error);
+ }
};
- const panelHeadProps = {
- onEdit(data: ScriptInfo) {
- setActiveKey(data.name);
- },
- activeKey,
- };
+ useInit(handleInit);
+
+ useEffect(() => {
+ if (!opInfo.opType) return;
+ (async () => {
+ if (opInfo.opType === 'sync') {
+ const isOk = await invoke('sync_scripts', { name: opInfo?.opRecord?.name });
+ if (isOk) {
+ await handleInit();
+ opInfo.resetRecord();
+ }
+ }
+ })();
+ }, [opInfo.opType]);
return (
({ name: i }))}
{...TABLE_PAGINATION}
+ pagination={false}
/>
- {/* {
- return {
- label: {i},
- key: i,
- children: ,
- }
- })}
- /> */}
- {/*
- {SCRIPTS.map((i) => {
- return (
- } key={i}>
-
-
- )
- })}
- */}
);
}