mirror of
https://github.com/lencx/ChatGPT.git
synced 2024-10-01 01:06:13 -04:00
chore: scripts
This commit is contained in:
parent
882593479b
commit
ee0829d8db
@ -5,7 +5,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
[![English badge](https://img.shields.io/badge/%E8%8B%B1%E6%96%87-English-blue)](./README.md)
|
[![English badge](https://img.shields.io/badge/%E8%8B%B1%E6%96%87-English-blue)](./README.md)
|
||||||
[![简体中文 badge](https://img.shields.io/badge/%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-Simplified%20Chinese-blue)](./README-ZH_CN.md)
|
[![简体中文 badge](https://img.shields.io/badge/%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-Simplified%20Chinese-blue)](./README-ZH_CN.md)\
|
||||||
[![ChatGPT downloads](https://img.shields.io/github/downloads/lencx/ChatGPT/total.svg?style=flat-square)](https://github.com/lencx/ChatGPT/releases)
|
[![ChatGPT downloads](https://img.shields.io/github/downloads/lencx/ChatGPT/total.svg?style=flat-square)](https://github.com/lencx/ChatGPT/releases)
|
||||||
[![chat](https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord)](https://discord.gg/aPhCRf4zZr)
|
[![chat](https://img.shields.io/badge/chat-discord-blue?style=flat&logo=discord)](https://discord.gg/aPhCRf4zZr)
|
||||||
[![lencx](https://img.shields.io/badge/follow-lencx__-blue?style=flat&logo=Twitter)](https://twitter.com/lencx_)
|
[![lencx](https://img.shields.io/badge/follow-lencx__-blue?style=flat&logo=Twitter)](https://twitter.com/lencx_)
|
||||||
|
1417
pnpm-lock.yaml
1417
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,5 @@
|
|||||||
# ChatGPT Scripts
|
# ChatGPT Scripts
|
||||||
|
|
||||||
ChatGPT Desktop Application Core Extension Scripts.
|
> ChatGPT Desktop Application Core Extension Scripts.
|
||||||
|
|
||||||
|
[ChatGPT/scripts](https://github.com/lencx/ChatGPT/tree/main/scripts)
|
||||||
|
10
scripts/chat.js
vendored
10
scripts/chat.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/chat.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/chat.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var chatInit = (() => {
|
function chatInit() {
|
||||||
const ICONS = {
|
const ICONS = {
|
||||||
copy: `<svg class="chatappico copy" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>`,
|
copy: `<svg class="chatappico copy" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>`,
|
||||||
cpok: `<svg class="chatappico cpok" viewBox="0 0 24 24"><g fill="none" stroke="#10a37f" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2M16 4h2a2 2 0 0 1 2 2v4m1 4H11"/><path d="m15 10l-4 4l4 4"/></g></svg>`,
|
cpok: `<svg class="chatappico cpok" viewBox="0 0 24 24"><g fill="none" stroke="#10a37f" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2M16 4h2a2 2 0 0 1 2 2v4m1 4H11"/><path d="m15 10l-4 4l4 4"/></g></svg>`,
|
||||||
@ -114,12 +114,10 @@ var chatInit = (() => {
|
|||||||
currentIndex = -1;
|
currentIndex = -1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return { init };
|
|
||||||
})();
|
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
chatInit.init();
|
chatInit();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', chatInit.init);
|
document.addEventListener('DOMContentLoaded', chatInit);
|
||||||
}
|
}
|
||||||
|
346
scripts/cmd.js
vendored
346
scripts/cmd.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/cmd.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/cmd.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function init() {
|
function cmdInit() {
|
||||||
const styleDom = document.createElement('style');
|
const styleDom = document.createElement('style');
|
||||||
styleDom.innerHTML = `form {
|
styleDom.innerHTML = `form {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -140,203 +140,203 @@ function init() {
|
|||||||
subtree: true,
|
subtree: true,
|
||||||
});
|
});
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
|
||||||
|
|
||||||
async function cmdTip() {
|
async function cmdTip() {
|
||||||
initDom();
|
initDom();
|
||||||
const chatPromptJson = (await invoke('get_chat_prompt_cmd')) || {};
|
const chatPromptJson = (await invoke('get_chat_prompt_cmd')) || {};
|
||||||
const data = chatPromptJson.data;
|
const data = chatPromptJson.data;
|
||||||
if (data.length <= 0) return;
|
if (data.length <= 0) return;
|
||||||
|
|
||||||
let promptDom = document.querySelector('.chat-prompt-cmd-list');
|
let promptDom = document.querySelector('.chat-prompt-cmd-list');
|
||||||
if (!promptDom) {
|
if (!promptDom) {
|
||||||
const dom = document.createElement('div');
|
const dom = document.createElement('div');
|
||||||
dom.classList.add('chat-prompt-cmd-list');
|
dom.classList.add('chat-prompt-cmd-list');
|
||||||
document.querySelector('form').appendChild(dom);
|
document.querySelector('form').appendChild(dom);
|
||||||
promptDom = document.querySelector('.chat-prompt-cmd-list');
|
promptDom = document.querySelector('.chat-prompt-cmd-list');
|
||||||
|
|
||||||
// fix: tray window
|
// fix: tray window
|
||||||
if (__TAURI_METADATA__.__currentWindow.label === 'tray') {
|
if (__TAURI_METADATA__.__currentWindow.label === 'tray') {
|
||||||
promptDom.style.bottom = '54px';
|
promptDom.style.bottom = '54px';
|
||||||
}
|
|
||||||
|
|
||||||
const itemDom = (v) =>
|
|
||||||
`<div class="cmd-item" title="${v.prompt}" data-cmd="${
|
|
||||||
v.cmd
|
|
||||||
}" data-prompt="${encodeURIComponent(v.prompt)}"><b title="${v.cmd}">/${v.cmd}</b><i>${
|
|
||||||
v.act
|
|
||||||
}</i></div>`;
|
|
||||||
const renderList = (v) => {
|
|
||||||
initDom();
|
|
||||||
promptDom.innerHTML = `<div>${v.map(itemDom).join('')}</div>`;
|
|
||||||
window.__CHAT_CMD_PROMPT__ = v[0]?.prompt.trim();
|
|
||||||
window.__CHAT_CMD__ = v[0]?.cmd.trim();
|
|
||||||
window.__cmd_list = promptDom.querySelectorAll('.cmd-item');
|
|
||||||
window.__cmd_index = 0;
|
|
||||||
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
|
||||||
};
|
|
||||||
const setPrompt = (v = '') => {
|
|
||||||
if (v.trim()) {
|
|
||||||
window.__CHAT_CMD_PROMPT__ = window.__CHAT_CMD_PROMPT__?.replace(
|
|
||||||
/\{([^{}]*)\}/,
|
|
||||||
`{${v.trim()}}`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
const searchInput = document.querySelector('form textarea');
|
|
||||||
|
|
||||||
// Enter a command starting with `/` and press a space to automatically fill `chatgpt prompt`.
|
const itemDom = (v) =>
|
||||||
// If more than one command appears in the search results, the first one will be used by default.
|
`<div class="cmd-item" title="${v.prompt}" data-cmd="${
|
||||||
function cmdKeydown(event) {
|
v.cmd
|
||||||
if (!window.__CHAT_CMD_PROMPT__) {
|
}" data-prompt="${encodeURIComponent(v.prompt)}"><b title="${v.cmd}">/${v.cmd}</b><i>${
|
||||||
if (
|
v.act
|
||||||
!event.shiftKey &&
|
}</i></div>`;
|
||||||
event.keyCode === 13 &&
|
const renderList = (v) => {
|
||||||
__TAURI_METADATA__.__currentWindow.label === 'tray'
|
initDom();
|
||||||
) {
|
promptDom.innerHTML = `<div>${v.map(itemDom).join('')}</div>`;
|
||||||
const btn = document.querySelector('form button');
|
window.__CHAT_CMD_PROMPT__ = v[0]?.prompt.trim();
|
||||||
if (btn) btn.click();
|
window.__CHAT_CMD__ = v[0]?.cmd.trim();
|
||||||
|
window.__cmd_list = promptDom.querySelectorAll('.cmd-item');
|
||||||
|
window.__cmd_index = 0;
|
||||||
|
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
||||||
|
};
|
||||||
|
const setPrompt = (v = '') => {
|
||||||
|
if (v.trim()) {
|
||||||
|
window.__CHAT_CMD_PROMPT__ = window.__CHAT_CMD_PROMPT__?.replace(
|
||||||
|
/\{([^{}]*)\}/,
|
||||||
|
`{${v.trim()}}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const searchInput = document.querySelector('form textarea');
|
||||||
|
|
||||||
|
// Enter a command starting with `/` and press a space to automatically fill `chatgpt prompt`.
|
||||||
|
// If more than one command appears in the search results, the first one will be used by default.
|
||||||
|
function cmdKeydown(event) {
|
||||||
|
if (!window.__CHAT_CMD_PROMPT__) {
|
||||||
|
if (
|
||||||
|
!event.shiftKey &&
|
||||||
|
event.keyCode === 13 &&
|
||||||
|
__TAURI_METADATA__.__currentWindow.label === 'tray'
|
||||||
|
) {
|
||||||
|
const btn = document.querySelector('form button');
|
||||||
|
if (btn) btn.click();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Keyboard scrolling (ArrowUp | ArrowDown) --------------------------
|
||||||
|
if (event.keyCode === 38 && window.__cmd_index > 0) {
|
||||||
|
// ArrowUp
|
||||||
|
window.__cmd_list[window.__cmd_index].classList.remove('selected');
|
||||||
|
window.__cmd_index = window.__cmd_index - 1;
|
||||||
|
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
||||||
|
window.__CHAT_CMD_PROMPT__ = decodeURIComponent(
|
||||||
|
window.__cmd_list[window.__cmd_index].getAttribute('data-prompt'),
|
||||||
|
);
|
||||||
|
searchInput.value = `/${window.__cmd_list[window.__cmd_index].getAttribute('data-cmd')}`;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------ Keyboard scrolling (ArrowUp | ArrowDown) --------------------------
|
if (event.keyCode === 40 && window.__cmd_index < window.__cmd_list.length - 1) {
|
||||||
if (event.keyCode === 38 && window.__cmd_index > 0) {
|
// ArrowDown
|
||||||
// ArrowUp
|
window.__cmd_list[window.__cmd_index].classList.remove('selected');
|
||||||
window.__cmd_list[window.__cmd_index].classList.remove('selected');
|
window.__cmd_index = window.__cmd_index + 1;
|
||||||
window.__cmd_index = window.__cmd_index - 1;
|
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
||||||
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
window.__CHAT_CMD_PROMPT__ = decodeURIComponent(
|
||||||
window.__CHAT_CMD_PROMPT__ = decodeURIComponent(
|
window.__cmd_list[window.__cmd_index].getAttribute('data-prompt'),
|
||||||
window.__cmd_list[window.__cmd_index].getAttribute('data-prompt'),
|
);
|
||||||
);
|
searchInput.value = `/${window.__cmd_list[window.__cmd_index].getAttribute('data-cmd')}`;
|
||||||
searchInput.value = `/${window.__cmd_list[window.__cmd_index].getAttribute('data-cmd')}`;
|
event.preventDefault();
|
||||||
event.preventDefault();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (event.keyCode === 40 && window.__cmd_index < window.__cmd_list.length - 1) {
|
const containerHeight = promptDom.offsetHeight;
|
||||||
// ArrowDown
|
const itemHeight = window.__cmd_list[0].offsetHeight + 1;
|
||||||
window.__cmd_list[window.__cmd_index].classList.remove('selected');
|
|
||||||
window.__cmd_index = window.__cmd_index + 1;
|
|
||||||
window.__cmd_list[window.__cmd_index].classList.add('selected');
|
|
||||||
window.__CHAT_CMD_PROMPT__ = decodeURIComponent(
|
|
||||||
window.__cmd_list[window.__cmd_index].getAttribute('data-prompt'),
|
|
||||||
);
|
|
||||||
searchInput.value = `/${window.__cmd_list[window.__cmd_index].getAttribute('data-cmd')}`;
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
const containerHeight = promptDom.offsetHeight;
|
const itemTop = window.__cmd_list[window.__cmd_index].offsetTop;
|
||||||
const itemHeight = window.__cmd_list[0].offsetHeight + 1;
|
const itemBottom = itemTop + itemHeight;
|
||||||
|
if (itemTop < promptDom.scrollTop || itemBottom > promptDom.scrollTop + containerHeight) {
|
||||||
|
promptDom.scrollTop = itemTop;
|
||||||
|
}
|
||||||
|
|
||||||
const itemTop = window.__cmd_list[window.__cmd_index].offsetTop;
|
// ------------------ TAB key replaces `{q}` tag content -------------------------------
|
||||||
const itemBottom = itemTop + itemHeight;
|
// feat: https://github.com/lencx/ChatGPT/issues/54
|
||||||
if (itemTop < promptDom.scrollTop || itemBottom > promptDom.scrollTop + containerHeight) {
|
if (event.keyCode === 9 && !window.__CHAT_STATUS__) {
|
||||||
promptDom.scrollTop = itemTop;
|
const strGroup = window.__CHAT_CMD_PROMPT__.match(/\{([^{}]*)\}/) || [];
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------ TAB key replaces `{q}` tag content -------------------------------
|
if (strGroup[1]) {
|
||||||
// feat: https://github.com/lencx/ChatGPT/issues/54
|
searchInput.value = `/${window.__CHAT_CMD__}` + ` {${strGroup[1]}}` + ' |-> ';
|
||||||
if (event.keyCode === 9 && !window.__CHAT_STATUS__) {
|
window.__CHAT_STATUS__ = 1;
|
||||||
const strGroup = window.__CHAT_CMD_PROMPT__.match(/\{([^{}]*)\}/) || [];
|
} else {
|
||||||
|
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
||||||
|
initDom();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
if (strGroup[1]) {
|
if (window.__CHAT_STATUS__ === 1 && event.keyCode === 9) {
|
||||||
searchInput.value = `/${window.__CHAT_CMD__}` + ` {${strGroup[1]}}` + ' |-> ';
|
// TAB
|
||||||
window.__CHAT_STATUS__ = 1;
|
const data = searchInput.value.split('|->');
|
||||||
} else {
|
if (data[1]?.trim()) {
|
||||||
|
setPrompt(data[1]);
|
||||||
|
window.__CHAT_STATUS__ = 2;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
// input text
|
||||||
|
if (window.__CHAT_STATUS__ === 2 && event.keyCode === 9) {
|
||||||
|
// TAB
|
||||||
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
||||||
|
promptDom.innerHTML = '';
|
||||||
|
delete window.__CHAT_STATUS__;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ type in a space to complete the fill ------------------------------------
|
||||||
|
if (event.keyCode === 32) {
|
||||||
|
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
||||||
|
promptDom.innerHTML = '';
|
||||||
|
delete window.__CHAT_CMD_PROMPT__;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ send --------------------------------------------------------------------
|
||||||
|
if (event.keyCode === 13 && window.__CHAT_CMD_PROMPT__) {
|
||||||
|
// Enter
|
||||||
|
const data = searchInput.value.split('|->');
|
||||||
|
setPrompt(data[1]);
|
||||||
|
|
||||||
|
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
||||||
|
|
||||||
|
initDom();
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchInput.removeEventListener('keydown', cmdKeydown, { capture: true });
|
||||||
|
searchInput.addEventListener('keydown', cmdKeydown, { capture: true });
|
||||||
|
|
||||||
|
function cmdInput() {
|
||||||
|
if (searchInput.value === '') {
|
||||||
initDom();
|
initDom();
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.__CHAT_STATUS__ === 1 && event.keyCode === 9) {
|
if (window.__CHAT_STATUS__) return;
|
||||||
// TAB
|
|
||||||
const data = searchInput.value.split('|->');
|
const query = searchInput.value;
|
||||||
if (data[1]?.trim()) {
|
if (!query || !/^\//.test(query)) {
|
||||||
setPrompt(data[1]);
|
initDom();
|
||||||
window.__CHAT_STATUS__ = 2;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// all cmd result
|
||||||
|
if (query === '/') {
|
||||||
|
renderList(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = data.filter((i) => new RegExp(query.substring(1)).test(i.cmd));
|
||||||
|
if (result.length > 0) {
|
||||||
|
renderList(result);
|
||||||
|
} else {
|
||||||
|
initDom();
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
// input text
|
|
||||||
if (window.__CHAT_STATUS__ === 2 && event.keyCode === 9) {
|
|
||||||
// TAB
|
|
||||||
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
|
||||||
promptDom.innerHTML = '';
|
|
||||||
delete window.__CHAT_STATUS__;
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------ type in a space to complete the fill ------------------------------------
|
|
||||||
if (event.keyCode === 32) {
|
|
||||||
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
|
||||||
promptDom.innerHTML = '';
|
|
||||||
delete window.__CHAT_CMD_PROMPT__;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------ send --------------------------------------------------------------------
|
|
||||||
if (event.keyCode === 13 && window.__CHAT_CMD_PROMPT__) {
|
|
||||||
// Enter
|
|
||||||
const data = searchInput.value.split('|->');
|
|
||||||
setPrompt(data[1]);
|
|
||||||
|
|
||||||
searchInput.value = window.__CHAT_CMD_PROMPT__;
|
|
||||||
|
|
||||||
initDom();
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
searchInput.removeEventListener('input', cmdInput);
|
||||||
|
searchInput.addEventListener('input', cmdInput);
|
||||||
}
|
}
|
||||||
searchInput.removeEventListener('keydown', cmdKeydown, { capture: true });
|
}
|
||||||
searchInput.addEventListener('keydown', cmdKeydown, { capture: true });
|
|
||||||
|
|
||||||
function cmdInput() {
|
function initDom() {
|
||||||
if (searchInput.value === '') {
|
const promptDom = document.querySelector('.chat-prompt-cmd-list');
|
||||||
initDom();
|
if (promptDom) {
|
||||||
}
|
promptDom.innerHTML = '';
|
||||||
|
|
||||||
if (window.__CHAT_STATUS__) return;
|
|
||||||
|
|
||||||
const query = searchInput.value;
|
|
||||||
if (!query || !/^\//.test(query)) {
|
|
||||||
initDom();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// all cmd result
|
|
||||||
if (query === '/') {
|
|
||||||
renderList(data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = data.filter((i) => new RegExp(query.substring(1)).test(i.cmd));
|
|
||||||
if (result.length > 0) {
|
|
||||||
renderList(result);
|
|
||||||
} else {
|
|
||||||
initDom();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
searchInput.removeEventListener('input', cmdInput);
|
delete window.__CHAT_CMD_PROMPT__;
|
||||||
searchInput.addEventListener('input', cmdInput);
|
delete window.__CHAT_CMD__;
|
||||||
|
delete window.__CHAT_STATUS__;
|
||||||
|
delete window.__cmd_list;
|
||||||
|
delete window.__cmd_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initDom() {
|
|
||||||
const promptDom = document.querySelector('.chat-prompt-cmd-list');
|
|
||||||
if (promptDom) {
|
|
||||||
promptDom.innerHTML = '';
|
|
||||||
}
|
|
||||||
delete window.__CHAT_CMD_PROMPT__;
|
|
||||||
delete window.__CHAT_CMD__;
|
|
||||||
delete window.__CHAT_STATUS__;
|
|
||||||
delete window.__cmd_list;
|
|
||||||
delete window.__cmd_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
init();
|
cmdInit();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', cmdInit);
|
||||||
}
|
}
|
||||||
|
11
scripts/core.js
vendored
11
scripts/core.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/core.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/core.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var coreInit = (() => {
|
function coreInit() {
|
||||||
const uid = () => window.crypto.getRandomValues(new Uint32Array(1))[0];
|
const uid = () => window.crypto.getRandomValues(new Uint32Array(1))[0];
|
||||||
function transformCallback(callback = () => {}, once = false) {
|
function transformCallback(callback = () => {}, once = false) {
|
||||||
const identifier = uid();
|
const identifier = uid();
|
||||||
@ -21,6 +21,7 @@ var coreInit = (() => {
|
|||||||
});
|
});
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function invoke(cmd, args) {
|
async function invoke(cmd, args) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (!window.__TAURI_POST_MESSAGE__) reject('__TAURI_POST_MESSAGE__ does not exist!');
|
if (!window.__TAURI_POST_MESSAGE__) reject('__TAURI_POST_MESSAGE__ does not exist!');
|
||||||
@ -226,11 +227,11 @@ var coreInit = (() => {
|
|||||||
return { startLoading, stopLoading };
|
return { startLoading, stopLoading };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { init };
|
init();
|
||||||
})();
|
}
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
coreInit.init();
|
coreInit();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', coreInit.init);
|
document.addEventListener('DOMContentLoaded', coreInit);
|
||||||
}
|
}
|
||||||
|
6
scripts/dalle2.js
vendored
6
scripts/dalle2.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/dalle2.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/dalle2.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function init() {
|
function dalle2Init() {
|
||||||
document.addEventListener('click', (e) => {
|
document.addEventListener('click', (e) => {
|
||||||
const origin = e.target.closest('a');
|
const origin = e.target.closest('a');
|
||||||
if (!origin || !origin.target) return;
|
if (!origin || !origin.target) return;
|
||||||
@ -35,7 +35,7 @@ function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
init();
|
dalle2Init();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', dalle2Init);
|
||||||
}
|
}
|
||||||
|
10
scripts/export.js
vendored
10
scripts/export.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/export.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/export.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function init() {
|
async function exportInit() {
|
||||||
if (window.location.pathname === '/auth/login') return;
|
if (window.location.pathname === '/auth/login') return;
|
||||||
const buttonOuterHTMLFallback = `<button class="btn flex justify-center gap-2 btn-neutral">Try Again</button>`;
|
const buttonOuterHTMLFallback = `<button class="btn flex justify-center gap-2 btn-neutral">Try Again</button>`;
|
||||||
removeButtons();
|
removeButtons();
|
||||||
@ -303,7 +303,7 @@ async function init() {
|
|||||||
const hours = String(now.getHours()).padStart(2, '0');
|
const hours = String(now.getHours()).padStart(2, '0');
|
||||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||||
const formattedDateTime = `${year}_${month}_${day}_${hours}_${minutes}_${seconds}`;
|
const formattedDateTime = `${year}_${month}_${day}-${hours}${minutes}${seconds}`;
|
||||||
return formattedDateTime;
|
return formattedDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,10 +315,10 @@ async function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('resize', init);
|
window.addEventListener('resize', exportInit);
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
init();
|
exportInit();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', exportInit);
|
||||||
}
|
}
|
||||||
|
5
scripts/main.js
vendored
Normal file
5
scripts/main.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// *** ChatGPT User Script ***
|
||||||
|
// @github: https://github.com/lencx/ChatGPT
|
||||||
|
// @path: $HOME/.chatgpt/scripts/main.js
|
||||||
|
|
||||||
|
console.log('Hello, ChatGPT!');
|
@ -12,6 +12,10 @@
|
|||||||
"name": "cmd.js",
|
"name": "cmd.js",
|
||||||
"version": "0.1.0"
|
"version": "0.1.0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "chat.js",
|
||||||
|
"version": "0.1.0"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "core.js",
|
"name": "core.js",
|
||||||
"version": "0.1.0"
|
"version": "0.1.0"
|
||||||
|
6
scripts/popup.core.js
vendored
6
scripts/popup.core.js
vendored
@ -4,7 +4,7 @@
|
|||||||
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/popup.core.js
|
* @url https://github.com/lencx/ChatGPT/tree/main/scripts/popup.core.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function init() {
|
async function popupCoreInit() {
|
||||||
const chatConf = (await invoke('get_app_conf')) || {};
|
const chatConf = (await invoke('get_app_conf')) || {};
|
||||||
if (!chatConf.popup_search) return;
|
if (!chatConf.popup_search) return;
|
||||||
if (!window.FloatingUIDOM) return;
|
if (!window.FloatingUIDOM) return;
|
||||||
@ -77,7 +77,7 @@ async function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||||
init();
|
popupCoreInit();
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', popupCoreInit);
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,6 @@ use std::{collections::HashMap, fs, path::PathBuf, vec};
|
|||||||
use tauri::{api, command, AppHandle, Manager};
|
use tauri::{api, command, AppHandle, Manager};
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use super::fs_extra::Error;
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub fn get_chat_prompt_cmd() -> serde_json::Value {
|
pub fn get_chat_prompt_cmd() -> serde_json::Value {
|
||||||
let path = utils::app_root().join("chat.prompt.cmd.json");
|
let path = utils::app_root().join("chat.prompt.cmd.json");
|
||||||
@ -183,13 +181,11 @@ pub async fn sync_prompts(app: AppHandle, time: u64) -> Option<Vec<PromptRecord>
|
|||||||
},
|
},
|
||||||
act: i.act.clone(),
|
act: i.act.clone(),
|
||||||
prompt: i.prompt.clone(),
|
prompt: i.prompt.clone(),
|
||||||
tags: vec!["chatgpt-prompts".to_string()],
|
tags: vec!["awesome-chatgpt-prompts".to_string()],
|
||||||
enable: true,
|
enable: true,
|
||||||
})
|
})
|
||||||
.collect::<Vec<PromptRecord>>();
|
.collect::<Vec<PromptRecord>>();
|
||||||
|
|
||||||
let data2 = transformed_data;
|
|
||||||
|
|
||||||
let prompts = utils::app_root().join("chat.prompt.json");
|
let prompts = utils::app_root().join("chat.prompt.json");
|
||||||
let prompt_cmd = utils::app_root().join("chat.prompt.cmd.json");
|
let prompt_cmd = utils::app_root().join("chat.prompt.cmd.json");
|
||||||
let chatgpt_prompts = utils::app_root()
|
let chatgpt_prompts = utils::app_root()
|
||||||
@ -211,7 +207,7 @@ pub async fn sync_prompts(app: AppHandle, time: u64) -> Option<Vec<PromptRecord>
|
|||||||
// chatgpt_prompts.json
|
// chatgpt_prompts.json
|
||||||
fs::write(
|
fs::write(
|
||||||
chatgpt_prompts,
|
chatgpt_prompts,
|
||||||
serde_json::to_string_pretty(&data).unwrap(),
|
serde_json::to_string_pretty(&transformed_data).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let cmd_data = cmd_list();
|
let cmd_data = cmd_list();
|
||||||
@ -253,7 +249,7 @@ pub async fn sync_prompts(app: AppHandle, time: u64) -> Option<Vec<PromptRecord>
|
|||||||
window::cmd::window_reload(app.clone(), "core");
|
window::cmd::window_reload(app.clone(), "core");
|
||||||
window::cmd::window_reload(app, "tray");
|
window::cmd::window_reload(app, "tray");
|
||||||
|
|
||||||
return Some(data2);
|
return Some(transformed_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +93,6 @@ pub fn init() -> Menu {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
hide_dock_icon_menu.into(),
|
hide_dock_icon_menu.into(),
|
||||||
system_tray_menu.into(),
|
system_tray_menu.into(),
|
||||||
CustomMenuItem::new("inject_script", "Inject Script")
|
|
||||||
.accelerator("CmdOrCtrl+J")
|
|
||||||
.into(),
|
|
||||||
MenuItem::Separator.into(),
|
MenuItem::Separator.into(),
|
||||||
Submenu::new(
|
Submenu::new(
|
||||||
"Theme",
|
"Theme",
|
||||||
@ -219,7 +216,6 @@ pub fn init() -> Menu {
|
|||||||
pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
||||||
let win = Some(event.window()).unwrap();
|
let win = Some(event.window()).unwrap();
|
||||||
let app = win.app_handle();
|
let app = win.app_handle();
|
||||||
let script_path = utils::script_path().to_string_lossy().to_string();
|
|
||||||
let menu_id = event.menu_item_id();
|
let menu_id = event.menu_item_id();
|
||||||
let menu_handle = win.menu_handle();
|
let menu_handle = win.menu_handle();
|
||||||
|
|
||||||
@ -239,7 +235,6 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
// Preferences
|
// Preferences
|
||||||
"control_center" => window::cmd::control_window(app, "control".into()),
|
"control_center" => window::cmd::control_window(app, "control".into()),
|
||||||
"restart" => tauri::api::process::restart(&app.env()),
|
"restart" => tauri::api::process::restart(&app.env()),
|
||||||
"inject_script" => open(&app, &script_path),
|
|
||||||
"go_conf" => utils::open_file(utils::app_root()),
|
"go_conf" => utils::open_file(utils::app_root()),
|
||||||
"clear_conf" => utils::clear_conf(&app),
|
"clear_conf" => utils::clear_conf(&app),
|
||||||
"app_website" => window::cmd::wa_window(
|
"app_website" => window::cmd::wa_window(
|
||||||
|
@ -4,4 +4,5 @@ pub mod gpt;
|
|||||||
pub mod menu;
|
pub mod menu;
|
||||||
pub mod script;
|
pub mod script;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
|
pub mod template;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::utils::{app_root, exists};
|
use crate::utils::{app_root, create_file, exists};
|
||||||
use log::error;
|
use log::error;
|
||||||
use log::info;
|
use log::info;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
@ -6,10 +6,13 @@ use serde_json::{from_str, json, Value};
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
|
|
||||||
use crate::{conf::SCRIPTS_MANIFEST, window};
|
use crate::{conf::SCRIPTS_DIR, window};
|
||||||
|
|
||||||
pub async fn init_script(app: tauri::AppHandle) -> anyhow::Result<(), reqwest::Error> {
|
pub async fn init_script(app: tauri::AppHandle) -> anyhow::Result<(), reqwest::Error> {
|
||||||
let body = reqwest::get(SCRIPTS_MANIFEST).await?.text().await?;
|
let body = reqwest::get(format!("{}{}", SCRIPTS_DIR, "manifest.json"))
|
||||||
|
.await?
|
||||||
|
.text()
|
||||||
|
.await?;
|
||||||
|
|
||||||
if exist_scripts("manifest.json".into()) {
|
if exist_scripts("manifest.json".into()) {
|
||||||
let compare = compare_nested_json_objects(
|
let compare = compare_nested_json_objects(
|
||||||
@ -39,8 +42,16 @@ pub async fn init_script(app: tauri::AppHandle) -> anyhow::Result<(), reqwest::E
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_script(name: String) -> serde_json::Value {
|
pub fn parse_script(name: String) -> Option<serde_json::Value> {
|
||||||
let code = &fs::read_to_string(name).unwrap();
|
let script_file = app_root().join("scripts").join(name);
|
||||||
|
let code = match fs::read_to_string(&script_file) {
|
||||||
|
Ok(content) => content,
|
||||||
|
Err(_) => {
|
||||||
|
error!("parse_script_error: {}", script_file.display());
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// let code = &fs::read_to_string(name).unwrap();
|
||||||
let re_name = Regex::new(r"@name\s+(.*?)\n").unwrap();
|
let re_name = Regex::new(r"@name\s+(.*?)\n").unwrap();
|
||||||
let re_version = Regex::new(r"@version\s+(.*?)\n").unwrap();
|
let re_version = Regex::new(r"@version\s+(.*?)\n").unwrap();
|
||||||
let re_url = Regex::new(r"@url\s+(.*?)\n").unwrap();
|
let re_url = Regex::new(r"@url\s+(.*?)\n").unwrap();
|
||||||
@ -49,15 +60,15 @@ pub fn parse_script(name: String) -> serde_json::Value {
|
|||||||
let mut version = String::new();
|
let mut version = String::new();
|
||||||
let mut url = String::new();
|
let mut url = String::new();
|
||||||
|
|
||||||
if let Some(capture) = re_name.captures(code) {
|
if let Some(capture) = re_name.captures(&code) {
|
||||||
name = capture.get(1).unwrap().as_str().trim().to_owned();
|
name = capture.get(1).unwrap().as_str().trim().to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(capture) = re_version.captures(code) {
|
if let Some(capture) = re_version.captures(&code) {
|
||||||
version = capture.get(1).unwrap().as_str().trim().to_owned();
|
version = capture.get(1).unwrap().as_str().trim().to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(capture) = re_url.captures(code) {
|
if let Some(capture) = re_url.captures(&code) {
|
||||||
url = capture.get(1).unwrap().as_str().trim().to_owned();
|
url = capture.get(1).unwrap().as_str().trim().to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +78,7 @@ pub fn parse_script(name: String) -> serde_json::Value {
|
|||||||
"url": url,
|
"url": url,
|
||||||
});
|
});
|
||||||
|
|
||||||
json_data
|
Some(json_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exist_scripts(file: String) -> bool {
|
pub fn exist_scripts(file: String) -> bool {
|
||||||
@ -77,8 +88,15 @@ pub fn exist_scripts(file: String) -> bool {
|
|||||||
|
|
||||||
pub fn create_chatgpt_scripts(file: String, body: String) {
|
pub fn create_chatgpt_scripts(file: String, body: String) {
|
||||||
let script_file = app_root().join("scripts").join(file);
|
let script_file = app_root().join("scripts").join(file);
|
||||||
info!("script_file: {:?}", script_file);
|
match create_file(&script_file) {
|
||||||
fs::write(&script_file, body).unwrap();
|
Ok(_) => {
|
||||||
|
info!("script_file: {:?}", script_file);
|
||||||
|
fs::write(&script_file, body).unwrap();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("create_file, {}: {}", script_file.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare_nested_json_objects(json1: &str, json2: &str) -> bool {
|
fn compare_nested_json_objects(json1: &str, json2: &str) -> bool {
|
||||||
@ -121,3 +139,53 @@ pub fn compare_json_objects(obj1: &Value, obj2: &Value) -> bool {
|
|||||||
_ => obj1 == obj2,
|
_ => obj1 == obj2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod cmd {
|
||||||
|
use super::{create_chatgpt_scripts, parse_script};
|
||||||
|
use crate::conf::SCRIPTS_DIR;
|
||||||
|
use log::{error, info};
|
||||||
|
use tauri::Manager;
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_script_info(name: String) -> Option<serde_json::Value> {
|
||||||
|
parse_script(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn sync_scripts(app: tauri::AppHandle, name: String) -> bool {
|
||||||
|
let res = reqwest::get(format!("{}{}", SCRIPTS_DIR, name)).await;
|
||||||
|
|
||||||
|
info!("sync_scripts: {}", name);
|
||||||
|
let body = match res {
|
||||||
|
Ok(response) => match response.text().await {
|
||||||
|
Ok(text) => text,
|
||||||
|
Err(err) => {
|
||||||
|
error!("sync_scripts_result_error: {}", err);
|
||||||
|
if let Some(v) = app.get_window("core") {
|
||||||
|
tauri::api::dialog::message(
|
||||||
|
Some(&v),
|
||||||
|
"Sync Scripts Error",
|
||||||
|
format!("sync_scripts_result_error: {}", err),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
error!("sync_scripts_response_error: {}", err);
|
||||||
|
if let Some(v) = app.get_window("core") {
|
||||||
|
tauri::api::dialog::message(
|
||||||
|
Some(&v),
|
||||||
|
"Sync Scripts Error",
|
||||||
|
format!("sync_scripts_response_error: {}", err),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
create_chatgpt_scripts(name, body);
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
use crate::{app, conf::AppConf, utils};
|
use crate::{
|
||||||
|
app,
|
||||||
|
conf::AppConf,
|
||||||
|
utils::{self, load_script},
|
||||||
|
};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, GlobalShortcutManager, Manager};
|
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, GlobalShortcutManager, Manager};
|
||||||
use wry::application::accelerator::Accelerator;
|
use wry::application::accelerator::Accelerator;
|
||||||
@ -10,6 +14,8 @@ pub fn init(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let url = app_conf.main_origin.to_string();
|
let url = app_conf.main_origin.to_string();
|
||||||
let theme = AppConf::theme_mode();
|
let theme = AppConf::theme_mode();
|
||||||
|
|
||||||
|
app::template::Template::new(utils::app_root().join("scripts"));
|
||||||
|
|
||||||
let handle = app.app_handle();
|
let handle = app.app_handle();
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
app::script::init_script(handle)
|
app::script::init_script(handle)
|
||||||
@ -71,7 +77,7 @@ pub fn init(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.theme(Some(theme))
|
.theme(Some(theme))
|
||||||
.always_on_top(app_conf2.stay_on_top)
|
.always_on_top(app_conf2.stay_on_top)
|
||||||
.initialization_script(&utils::user_script())
|
.initialization_script(&utils::user_script())
|
||||||
.initialization_script(include_str!("../../../scripts/core.js"))
|
.initialization_script(&load_script("core.js"))
|
||||||
.user_agent(&app_conf2.ua_window);
|
.user_agent(&app_conf2.ua_window);
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
@ -89,11 +95,11 @@ pub fn init(app: &mut App) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.initialization_script(include_str!("../vendors/jspdf.js"))
|
.initialization_script(include_str!("../vendors/jspdf.js"))
|
||||||
.initialization_script(include_str!("../vendors/turndown.js"))
|
.initialization_script(include_str!("../vendors/turndown.js"))
|
||||||
.initialization_script(include_str!("../vendors/turndown-plugin-gfm.js"))
|
.initialization_script(include_str!("../vendors/turndown-plugin-gfm.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/popup.core.js"))
|
.initialization_script(&load_script("popup.core.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/export.js"))
|
.initialization_script(&load_script("export.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/markdown.export.js"))
|
.initialization_script(&load_script("markdown.export.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/cmd.js"))
|
.initialization_script(&load_script("cmd.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/chat.js"))
|
.initialization_script(&load_script("chat.js"))
|
||||||
}
|
}
|
||||||
|
|
||||||
main_win.build().unwrap();
|
main_win.build().unwrap();
|
||||||
|
110
src-tauri/src/app/template.rs
Normal file
110
src-tauri/src/app/template.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use log::{error, info};
|
||||||
|
use std::{
|
||||||
|
fs::{self, File},
|
||||||
|
io::Write,
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static SCRIPT_MAIN: &[u8] = include_bytes!("../../../scripts/main.js");
|
||||||
|
pub static SCRIPT_CORE: &[u8] = include_bytes!("../../../scripts/core.js");
|
||||||
|
pub static SCRIPT_CHAT: &[u8] = include_bytes!("../../../scripts/chat.js");
|
||||||
|
pub static SCRIPT_CMD: &[u8] = include_bytes!("../../../scripts/cmd.js");
|
||||||
|
pub static SCRIPT_DALLE2: &[u8] = include_bytes!("../../../scripts/dalle2.js");
|
||||||
|
pub static SCRIPT_EXPORT: &[u8] = include_bytes!("../../../scripts/export.js");
|
||||||
|
pub static SCRIPT_MD_EXPORT: &[u8] = include_bytes!("../../../scripts/markdown.export.js");
|
||||||
|
pub static SCRIPT_POPUP_CORE: &[u8] = include_bytes!("../../../scripts/popup.core.js");
|
||||||
|
pub static SCRIPT_MANIFEST: &[u8] = include_bytes!("../../../scripts/manifest.json");
|
||||||
|
pub static SCRIPT_README: &[u8] = include_bytes!("../../../scripts/README.md");
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Template {
|
||||||
|
pub main: Vec<u8>,
|
||||||
|
pub core: Vec<u8>,
|
||||||
|
pub chat: Vec<u8>,
|
||||||
|
pub cmd: Vec<u8>,
|
||||||
|
pub dalle2: Vec<u8>,
|
||||||
|
pub export: Vec<u8>,
|
||||||
|
pub markdown_export: Vec<u8>,
|
||||||
|
pub popup_core: Vec<u8>,
|
||||||
|
pub manifest: Vec<u8>,
|
||||||
|
pub readme: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Template {
|
||||||
|
pub fn new<P: AsRef<Path>>(template_dir: P) -> Self {
|
||||||
|
let template_dir = template_dir.as_ref();
|
||||||
|
let mut template = Template::default();
|
||||||
|
|
||||||
|
{
|
||||||
|
let files = vec![
|
||||||
|
(template_dir.join("main.js"), &mut template.main),
|
||||||
|
(template_dir.join("core.js"), &mut template.core),
|
||||||
|
(template_dir.join("chat.js"), &mut template.chat),
|
||||||
|
(template_dir.join("cmd.js"), &mut template.cmd),
|
||||||
|
(template_dir.join("dalle2.js"), &mut template.dalle2),
|
||||||
|
(template_dir.join("export.js"), &mut template.export),
|
||||||
|
(
|
||||||
|
template_dir.join("markdown.export.js"),
|
||||||
|
&mut template.markdown_export,
|
||||||
|
),
|
||||||
|
(template_dir.join("popup.core.js"), &mut template.popup_core),
|
||||||
|
(template_dir.join("README.md"), &mut template.readme),
|
||||||
|
(template_dir.join("manifest.json"), &mut template.manifest),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (filename, dest) in files {
|
||||||
|
if !filename.exists() {
|
||||||
|
match create_dir(&filename) {
|
||||||
|
Ok(_) => {
|
||||||
|
if let Err(e) = write_file_contents(&filename, dest) {
|
||||||
|
error!("write_script, {}: {}", filename.display(), e);
|
||||||
|
} else {
|
||||||
|
info!("write_script: {}", filename.display());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("create_file, {}: {}", filename.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Template {
|
||||||
|
fn default() -> Template {
|
||||||
|
Template {
|
||||||
|
main: Vec::from(SCRIPT_MAIN),
|
||||||
|
core: Vec::from(SCRIPT_CORE),
|
||||||
|
chat: Vec::from(SCRIPT_CHAT),
|
||||||
|
cmd: Vec::from(SCRIPT_CMD),
|
||||||
|
dalle2: Vec::from(SCRIPT_DALLE2),
|
||||||
|
export: Vec::from(SCRIPT_EXPORT),
|
||||||
|
markdown_export: Vec::from(SCRIPT_MD_EXPORT),
|
||||||
|
popup_core: Vec::from(SCRIPT_POPUP_CORE),
|
||||||
|
manifest: Vec::from(SCRIPT_MANIFEST),
|
||||||
|
readme: Vec::from(SCRIPT_README),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_dir<P: AsRef<Path>>(filename: P) -> Result<()> {
|
||||||
|
let filename = filename.as_ref();
|
||||||
|
if let Some(parent) = filename.parent() {
|
||||||
|
if !parent.exists() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_file_contents<P: AsRef<Path>>(filename: P, data: &[u8]) -> Result<()> {
|
||||||
|
let filename = filename.as_ref();
|
||||||
|
let mut file = File::create(filename)?;
|
||||||
|
file.write_all(data)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
use crate::{conf::AppConf, utils};
|
use crate::{
|
||||||
|
conf::AppConf,
|
||||||
|
utils::{self, load_script},
|
||||||
|
};
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use tauri::{utils::config::WindowUrl, window::WindowBuilder, Manager};
|
use tauri::{utils::config::WindowUrl, window::WindowBuilder, Manager};
|
||||||
@ -23,16 +26,16 @@ pub fn tray_window(handle: &tauri::AppHandle) {
|
|||||||
.always_on_top(true)
|
.always_on_top(true)
|
||||||
.theme(Some(theme))
|
.theme(Some(theme))
|
||||||
.initialization_script(&utils::user_script())
|
.initialization_script(&utils::user_script())
|
||||||
.initialization_script(include_str!("../../../scripts/core.js"))
|
.initialization_script(&load_script("core.js"))
|
||||||
.user_agent(&app_conf.ua_tray);
|
.user_agent(&app_conf.ua_tray);
|
||||||
|
|
||||||
if app_conf.tray_origin == "https://chat.openai.com" && !app_conf.tray_dashboard {
|
if app_conf.tray_origin == "https://chat.openai.com" && !app_conf.tray_dashboard {
|
||||||
tray_win = tray_win
|
tray_win = tray_win
|
||||||
.initialization_script(include_str!("../vendors/floating-ui-core.js"))
|
.initialization_script(include_str!("../vendors/floating-ui-core.js"))
|
||||||
.initialization_script(include_str!("../vendors/floating-ui-dom.js"))
|
.initialization_script(include_str!("../vendors/floating-ui-dom.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/cmd.js"))
|
.initialization_script(&load_script("cmd.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/chat.js"))
|
.initialization_script(&load_script("chat.js"))
|
||||||
.initialization_script(include_str!("../../../scripts/popup.core.js"))
|
.initialization_script(&load_script("popup.core.js"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tray_win.build().unwrap().hide().unwrap();
|
tray_win.build().unwrap().hide().unwrap();
|
||||||
@ -78,9 +81,9 @@ pub fn dalle2_window(
|
|||||||
.inner_size(800.0, 600.0)
|
.inner_size(800.0, 600.0)
|
||||||
.always_on_top(false)
|
.always_on_top(false)
|
||||||
.theme(Some(theme))
|
.theme(Some(theme))
|
||||||
.initialization_script(include_str!("../../../scripts/core.js"))
|
.initialization_script(&load_script("core.js"))
|
||||||
|
.initialization_script(&load_script("dalle2.js"))
|
||||||
.initialization_script(&query)
|
.initialization_script(&query)
|
||||||
.initialization_script(include_str!("../../../scripts/dalle2.js"))
|
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
});
|
});
|
||||||
@ -161,7 +164,7 @@ pub mod cmd {
|
|||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
tauri::WindowBuilder::new(&app, label, tauri::WindowUrl::App(url.parse().unwrap()))
|
tauri::WindowBuilder::new(&app, label, tauri::WindowUrl::App(url.parse().unwrap()))
|
||||||
.initialization_script(&script.unwrap_or_default())
|
.initialization_script(&script.unwrap_or_default())
|
||||||
.initialization_script(include_str!("../../../scripts/core.js"))
|
.initialization_script(&load_script("core.js"))
|
||||||
.title(title)
|
.title(title)
|
||||||
.inner_size(960.0, 700.0)
|
.inner_size(960.0, 700.0)
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
|
@ -15,8 +15,7 @@ pub const UPDATE_LOG_URL: &str = "https://github.com/lencx/ChatGPT/blob/main/UPD
|
|||||||
// pub const BUY_COFFEE: &str = "https://www.buymeacoffee.com/lencx";
|
// pub const BUY_COFFEE: &str = "https://www.buymeacoffee.com/lencx";
|
||||||
pub const GITHUB_PROMPTS_CSV_URL: &str =
|
pub const GITHUB_PROMPTS_CSV_URL: &str =
|
||||||
"https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv";
|
"https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv";
|
||||||
pub const SCRIPTS_MANIFEST: &str =
|
pub const SCRIPTS_DIR: &str = "https://raw.githubusercontent.com/lencx/ChatGPT/main/scripts/";
|
||||||
"https://raw.githubusercontent.com/lencx/ChatGPT/main/scripts/manifest.json";
|
|
||||||
|
|
||||||
pub const APP_CONF_PATH: &str = "chat.conf.json";
|
pub const APP_CONF_PATH: &str = "chat.conf.json";
|
||||||
pub const CHATGPT_URL: &str = "https://chat.openai.com";
|
pub const CHATGPT_URL: &str = "https://chat.openai.com";
|
||||||
|
@ -7,7 +7,7 @@ mod app;
|
|||||||
mod conf;
|
mod conf;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use app::{cmd, fs_extra, gpt, menu, setup, window};
|
use app::{cmd, fs_extra, gpt, menu, script, setup, window};
|
||||||
use conf::AppConf;
|
use conf::AppConf;
|
||||||
use tauri_plugin_autostart::MacosLauncher;
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
use tauri_plugin_log::{
|
use tauri_plugin_log::{
|
||||||
@ -76,6 +76,8 @@ async fn main() {
|
|||||||
conf::cmd::form_confirm,
|
conf::cmd::form_confirm,
|
||||||
conf::cmd::form_cancel,
|
conf::cmd::form_cancel,
|
||||||
conf::cmd::form_msg,
|
conf::cmd::form_msg,
|
||||||
|
script::cmd::sync_scripts,
|
||||||
|
script::cmd::get_script_info,
|
||||||
window::cmd::wa_window,
|
window::cmd::wa_window,
|
||||||
window::cmd::control_window,
|
window::cmd::control_window,
|
||||||
window::cmd::window_reload,
|
window::cmd::window_reload,
|
||||||
|
@ -4,7 +4,7 @@ use regex::Regex;
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fs::{self, File},
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::Command,
|
||||||
};
|
};
|
||||||
@ -25,11 +25,15 @@ pub fn exists(path: &Path) -> bool {
|
|||||||
Path::new(path).exists()
|
Path::new(path).exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_file(path: &Path) -> Result<File> {
|
pub fn create_file<P: AsRef<Path>>(filename: P) -> Result<()> {
|
||||||
if let Some(p) = path.parent() {
|
let filename = filename.as_ref();
|
||||||
fs::create_dir_all(p)?
|
if let Some(parent) = filename.parent() {
|
||||||
|
if !parent.exists() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
File::create(path).map_err(Into::into)
|
fs::File::create(filename)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_chatgpt_prompts() {
|
pub fn create_chatgpt_prompts() {
|
||||||
@ -42,31 +46,20 @@ pub fn create_chatgpt_prompts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn script_path() -> PathBuf {
|
|
||||||
let script_file = app_root().join("main.js");
|
|
||||||
if !exists(&script_file) {
|
|
||||||
create_file(&script_file).unwrap();
|
|
||||||
fs::write(
|
|
||||||
&script_file,
|
|
||||||
format!(
|
|
||||||
"// *** ChatGPT User Script ***\n// @github: https://github.com/lencx/ChatGPT \n// @path: {}\n\nconsole.log('🤩 Hello ChatGPT!!!');",
|
|
||||||
&script_file.to_string_lossy()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
script_file
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn user_script() -> String {
|
pub fn user_script() -> String {
|
||||||
let user_script_content = fs::read_to_string(script_path()).unwrap_or_else(|_| "".to_string());
|
let user_script_file = app_root().join("scripts").join("main.js");
|
||||||
|
let user_script_content = fs::read_to_string(user_script_file).unwrap_or_else(|_| "".to_string());
|
||||||
format!(
|
format!(
|
||||||
"window.addEventListener('DOMContentLoaded', function() {{\n{}\n}})",
|
"window.addEventListener('DOMContentLoaded', function() {{\n{}\n}})",
|
||||||
user_script_content
|
user_script_content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_script(filename: &str) -> String {
|
||||||
|
let script_file = app_root().join("scripts").join(filename);
|
||||||
|
fs::read_to_string(script_file).unwrap_or_else(|_| "".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_file(path: PathBuf) {
|
pub fn open_file(path: PathBuf) {
|
||||||
let pathname = convert_path(path.to_str().unwrap());
|
let pathname = convert_path(path.to_str().unwrap());
|
||||||
info!("open_file: {}", pathname);
|
info!("open_file: {}", pathname);
|
||||||
|
3
src/components/FilePath/index.tsx
vendored
3
src/components/FilePath/index.tsx
vendored
@ -16,7 +16,8 @@ const FilePath: FC<FilePathProps> = ({ className, label = 'PATH', paths = '', ur
|
|||||||
const [filePath, setPath] = useState('');
|
const [filePath, setPath] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!path && !url) return;
|
if (!(paths || url)) return;
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
if (url) {
|
if (url) {
|
||||||
setPath(url);
|
setPath(url);
|
||||||
|
1
src/hooks/useColumns.tsx
vendored
1
src/hooks/useColumns.tsx
vendored
@ -74,6 +74,7 @@ export const EditRow: FC<EditRowProps> = ({ rowKey, row, actions }) => {
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
{...DISABLE_AUTO_COMPLETE}
|
{...DISABLE_AUTO_COMPLETE}
|
||||||
onPressEnter={handleSave}
|
onPressEnter={handleSave}
|
||||||
|
onBlur={handleSave}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="rowedit" onClick={handleEdit}>
|
<div className="rowedit" onClick={handleEdit}>
|
||||||
|
22
src/main.scss
vendored
22
src/main.scss
vendored
@ -114,3 +114,25 @@ body,
|
|||||||
cursor: pointer;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6
src/routes.tsx
vendored
6
src/routes.tsx
vendored
@ -14,6 +14,7 @@ import type { MenuProps } from 'antd';
|
|||||||
import Settings from '@/view/settings';
|
import Settings from '@/view/settings';
|
||||||
import About from '@/view/about';
|
import About from '@/view/about';
|
||||||
import Scripts from '@/view/scripts';
|
import Scripts from '@/view/scripts';
|
||||||
|
import ScriptsEditor from '@/view/scripts/Editor';
|
||||||
import UserCustom from '@/view/prompts/UserCustom';
|
import UserCustom from '@/view/prompts/UserCustom';
|
||||||
import SyncPrompts from '@/view/prompts/SyncPrompts';
|
import SyncPrompts from '@/view/prompts/SyncPrompts';
|
||||||
import SyncCustom from '@/view/prompts/SyncCustom';
|
import SyncCustom from '@/view/prompts/SyncCustom';
|
||||||
@ -103,6 +104,11 @@ export const routes: Array<ChatRouteObject> = [
|
|||||||
icon: <CodeOutlined />,
|
icon: <CodeOutlined />,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/scripts/:id',
|
||||||
|
element: <ScriptsEditor />,
|
||||||
|
hideMenu: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
element: <About />,
|
element: <About />,
|
||||||
|
4
src/utils.ts
vendored
4
src/utils.ts
vendored
@ -23,6 +23,10 @@ export const chatRoot = async () => {
|
|||||||
return join(await homeDir(), '.chatgpt');
|
return join(await homeDir(), '.chatgpt');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const scriptRoot = async () => {
|
||||||
|
return join(await chatRoot(), 'scripts');
|
||||||
|
};
|
||||||
|
|
||||||
export const chatPromptPath = async (): Promise<string> => {
|
export const chatPromptPath = async (): Promise<string> => {
|
||||||
return join(await chatRoot(), CHAT_PROMPT_JSON);
|
return join(await chatRoot(), CHAT_PROMPT_JSON);
|
||||||
};
|
};
|
||||||
|
16
src/view/markdown/index.scss
vendored
16
src/view/markdown/index.scss
vendored
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
3
src/view/markdown/index.tsx
vendored
3
src/view/markdown/index.tsx
vendored
@ -8,7 +8,6 @@ import { fs, shell } from '@tauri-apps/api';
|
|||||||
import useInit from '@/hooks/useInit';
|
import useInit from '@/hooks/useInit';
|
||||||
import SplitIcon from '@/icons/SplitIcon';
|
import SplitIcon from '@/icons/SplitIcon';
|
||||||
import { getPath } from '@/view/notes/config';
|
import { getPath } from '@/view/notes/config';
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
const modeMap: any = {
|
const modeMap: any = {
|
||||||
0: 'split',
|
0: 'split',
|
||||||
@ -41,7 +40,7 @@ export default function Markdown() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="md-task">
|
<div className="editor-task">
|
||||||
<Breadcrumb separator="">
|
<Breadcrumb separator="">
|
||||||
<Breadcrumb.Item onClick={() => history.go(-1)}>
|
<Breadcrumb.Item onClick={() => history.go(-1)}>
|
||||||
<ArrowLeftOutlined />
|
<ArrowLeftOutlined />
|
||||||
|
2
src/view/notes/config.tsx
vendored
2
src/view/notes/config.tsx
vendored
@ -67,5 +67,5 @@ const RenderPath = ({ row }: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getPath = async (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`);
|
||||||
};
|
};
|
||||||
|
7
src/view/prompts/SyncPrompts/config.tsx
vendored
7
src/view/prompts/SyncPrompts/config.tsx
vendored
@ -7,7 +7,6 @@ export const syncColumns = () => [
|
|||||||
title: '/{cmd}',
|
title: '/{cmd}',
|
||||||
dataIndex: 'cmd',
|
dataIndex: 'cmd',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
// width: 120,
|
|
||||||
key: 'cmd',
|
key: 'cmd',
|
||||||
render: (_: string, row: Record<string, string>) => (
|
render: (_: string, row: Record<string, string>) => (
|
||||||
<Tag color="#2a2a2a">/{genCmd(row.act)}</Tag>
|
<Tag color="#2a2a2a">/{genCmd(row.act)}</Tag>
|
||||||
@ -17,20 +16,17 @@ export const syncColumns = () => [
|
|||||||
title: 'Act',
|
title: 'Act',
|
||||||
dataIndex: 'act',
|
dataIndex: 'act',
|
||||||
key: 'act',
|
key: 'act',
|
||||||
// width: 200,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tags',
|
title: 'Tags',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
key: 'tags',
|
key: 'tags',
|
||||||
// width: 150,
|
render: () => <Tag>built-in</Tag>,
|
||||||
render: () => <Tag>chatgpt-prompts</Tag>,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Enable',
|
title: 'Enable',
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enable',
|
||||||
key: 'enable',
|
key: 'enable',
|
||||||
// width: 80,
|
|
||||||
render: (v: boolean = false, row: Record<string, any>, action: Record<string, any>) => (
|
render: (v: boolean = false, row: Record<string, any>, action: Record<string, any>) => (
|
||||||
<Switch checked={v} onChange={(v) => action.setRecord({ ...row, enable: v }, 'enable')} />
|
<Switch checked={v} onChange={(v) => action.setRecord({ ...row, enable: v }, 'enable')} />
|
||||||
),
|
),
|
||||||
@ -40,7 +36,6 @@ export const syncColumns = () => [
|
|||||||
title: 'Prompt',
|
title: 'Prompt',
|
||||||
dataIndex: 'prompt',
|
dataIndex: 'prompt',
|
||||||
key: 'prompt',
|
key: 'prompt',
|
||||||
// width: 300,
|
|
||||||
render: (v: string) => <span className="chat-prompts-val">{v}</span>,
|
render: (v: string) => <span className="chat-prompts-val">{v}</span>,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
5
src/view/prompts/SyncPrompts/index.tsx
vendored
5
src/view/prompts/SyncPrompts/index.tsx
vendored
@ -12,7 +12,8 @@ import { fmtDate, chatRoot } from '@/utils';
|
|||||||
import { syncColumns } from './config';
|
import { syncColumns } 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';
|
||||||
|
const promptsURL = 'https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv';
|
||||||
|
|
||||||
export default function SyncPrompts() {
|
export default function SyncPrompts() {
|
||||||
const { rowSelection, selectedRowIDs } = useTableRowSelection();
|
const { rowSelection, selectedRowIDs } = useTableRowSelection();
|
||||||
@ -83,7 +84,7 @@ export default function SyncPrompts() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="chat-table-tip">
|
<div className="chat-table-tip">
|
||||||
<div className="chat-sync-path">
|
<div className="chat-sync-path">
|
||||||
<FilePath url={promptsURL} content="f/awesome-chatgpt-prompts/prompts.csv" />
|
<FilePath label="URL" url={promptsURL} content="f/awesome-chatgpt-prompts/prompts.csv" />
|
||||||
<FilePath label="CACHE" paths="cache_prompts/chatgpt_prompts.json" />
|
<FilePath label="CACHE" paths="cache_prompts/chatgpt_prompts.json" />
|
||||||
</div>
|
</div>
|
||||||
{lastUpdated && (
|
{lastUpdated && (
|
||||||
|
5
src/view/prompts/SyncRecord/config.tsx
vendored
5
src/view/prompts/SyncRecord/config.tsx
vendored
@ -7,7 +7,6 @@ export const syncColumns = () => [
|
|||||||
title: '/{cmd}',
|
title: '/{cmd}',
|
||||||
dataIndex: 'cmd',
|
dataIndex: 'cmd',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
// width: 120,
|
|
||||||
key: 'cmd',
|
key: 'cmd',
|
||||||
render: (_: string, row: Record<string, string>) => (
|
render: (_: string, row: Record<string, string>) => (
|
||||||
<Tag color="#2a2a2a">/{row.cmd ? row.cmd : genCmd(row.act)}</Tag>
|
<Tag color="#2a2a2a">/{row.cmd ? row.cmd : genCmd(row.act)}</Tag>
|
||||||
@ -17,13 +16,11 @@ export const syncColumns = () => [
|
|||||||
title: 'Act',
|
title: 'Act',
|
||||||
dataIndex: 'act',
|
dataIndex: 'act',
|
||||||
key: 'act',
|
key: 'act',
|
||||||
// width: 200,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Tags',
|
title: 'Tags',
|
||||||
dataIndex: 'tags',
|
dataIndex: 'tags',
|
||||||
key: 'tags',
|
key: 'tags',
|
||||||
// width: 150,
|
|
||||||
render: (v: string[]) => (
|
render: (v: string[]) => (
|
||||||
<span className="chat-prompts-tags">
|
<span className="chat-prompts-tags">
|
||||||
{v?.map((i) => (
|
{v?.map((i) => (
|
||||||
@ -36,7 +33,6 @@ export const syncColumns = () => [
|
|||||||
title: 'Enable',
|
title: 'Enable',
|
||||||
dataIndex: 'enable',
|
dataIndex: 'enable',
|
||||||
key: 'enable',
|
key: 'enable',
|
||||||
// width: 80,
|
|
||||||
render: (v: boolean = false, row: Record<string, any>, action: Record<string, any>) => (
|
render: (v: boolean = false, row: Record<string, any>, action: Record<string, any>) => (
|
||||||
<Switch checked={v} onChange={(v) => action.setRecord({ ...row, enable: v }, 'enable')} />
|
<Switch checked={v} onChange={(v) => action.setRecord({ ...row, enable: v }, 'enable')} />
|
||||||
),
|
),
|
||||||
@ -46,7 +42,6 @@ export const syncColumns = () => [
|
|||||||
title: 'Prompt',
|
title: 'Prompt',
|
||||||
dataIndex: 'prompt',
|
dataIndex: 'prompt',
|
||||||
key: 'prompt',
|
key: 'prompt',
|
||||||
// width: 300,
|
|
||||||
render: (v: string) => <span className="chat-prompts-val">{v}</span>,
|
render: (v: string) => <span className="chat-prompts-val">{v}</span>,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
2
src/view/prompts/SyncRecord/index.tsx
vendored
2
src/view/prompts/SyncRecord/index.tsx
vendored
@ -73,7 +73,7 @@ export default function SyncRecord() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="chat-table-tip">
|
<div className="chat-table-tip">
|
||||||
<div className="chat-sync-path">
|
<div className="chat-sync-path">
|
||||||
<FilePath url={filePath} />
|
<FilePath label="URL" url={filePath} />
|
||||||
<FilePath label="CACHE" paths={`cache_prompts/${state?.id}.json`} />
|
<FilePath label="CACHE" paths={`cache_prompts/${state?.id}.json`} />
|
||||||
</div>
|
</div>
|
||||||
{state?.last_updated && (
|
{state?.last_updated && (
|
||||||
|
12
src/view/prompts/UserCustom/Form.tsx
vendored
12
src/view/prompts/UserCustom/Form.tsx
vendored
@ -45,12 +45,6 @@ const UserCustomForm: ForwardRefRenderFunction<FormProps, UserCustomFormProps> =
|
|||||||
>
|
>
|
||||||
<Input placeholder="Please enter the Act" {...DISABLE_AUTO_COMPLETE} />
|
<Input placeholder="Please enter the Act" {...DISABLE_AUTO_COMPLETE} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="Tags" name="tags">
|
|
||||||
<Tags value={record?.tags} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="Enable" name="enable" valuePropName="checked">
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="Prompt"
|
label="Prompt"
|
||||||
name="prompt"
|
name="prompt"
|
||||||
@ -58,6 +52,12 @@ const UserCustomForm: ForwardRefRenderFunction<FormProps, UserCustomFormProps> =
|
|||||||
>
|
>
|
||||||
<Input.TextArea rows={4} placeholder="Please enter a prompt" {...DISABLE_AUTO_COMPLETE} />
|
<Input.TextArea rows={4} placeholder="Please enter a prompt" {...DISABLE_AUTO_COMPLETE} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label="Enable" name="enable" valuePropName="checked">
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="Tags" name="tags">
|
||||||
|
<Tags value={record?.tags} />
|
||||||
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
74
src/view/scripts/Editor.tsx
vendored
74
src/view/scripts/Editor.tsx
vendored
@ -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 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 {
|
import useInit from '@/hooks/useInit';
|
||||||
value?: string;
|
import { getPath } from './config';
|
||||||
|
|
||||||
|
interface ScriptEditorProps {
|
||||||
onChange?: (v: string) => void;
|
onChange?: (v: string) => void;
|
||||||
mode?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScriptEditor: FC<MarkdownEditorProps> = ({
|
const ScriptEditor: FC<ScriptEditorProps> = ({ onChange }) => {
|
||||||
value = 'console.log',
|
const [filePath, setFilePath] = useState('');
|
||||||
onChange,
|
const [source, setSource] = useState('// write your script here\n');
|
||||||
mode = 'split',
|
const location = useLocation();
|
||||||
}) => {
|
const state = location?.state;
|
||||||
const [content, setContent] = useState(value);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useInit(async () => {
|
||||||
setContent(value);
|
const file = await getPath(state);
|
||||||
onChange && onChange(value);
|
setFilePath(file);
|
||||||
}, [value]);
|
setSource(await fs.readTextFile(file));
|
||||||
|
});
|
||||||
|
|
||||||
const handleEdit = (e: any) => {
|
const handleEdit = (e: any) => {
|
||||||
setContent(e);
|
setSource(e);
|
||||||
onChange && onChange(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 (
|
return (
|
||||||
<div className="script-editor">
|
<div className="script-editor">
|
||||||
<Editor language="js" value={content} onChange={handleEdit} />
|
<Breadcrumb className="editor-task" separator="">
|
||||||
|
<Breadcrumb.Item onClick={() => history.go(-1)}>
|
||||||
|
<ArrowLeftOutlined />
|
||||||
|
</Breadcrumb.Item>
|
||||||
|
<Popconfirm
|
||||||
|
placement="topRight"
|
||||||
|
title="Are you sure you want to save the changes? It is a risky operation, but you can restore it through the sync button."
|
||||||
|
onConfirm={handleSave}
|
||||||
|
onCancel={handleReset}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
overlayStyle={{ width: 300 }}
|
||||||
|
>
|
||||||
|
<Tag className="editor-btn" color="#108ee9">
|
||||||
|
Save
|
||||||
|
</Tag>
|
||||||
|
</Popconfirm>
|
||||||
|
<Breadcrumb.Item onClick={() => shell.open(filePath)}>{filePath}</Breadcrumb.Item>
|
||||||
|
</Breadcrumb>
|
||||||
|
<Editor height="80vh" language="javascript" value={source} onChange={handleEdit} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
97
src/view/scripts/Head.tsx
vendored
97
src/view/scripts/Head.tsx
vendored
@ -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 (
|
|
||||||
<>
|
|
||||||
<span>
|
|
||||||
<Tag color="orange">{version}</Tag>
|
|
||||||
</span>
|
|
||||||
{editing ? (
|
|
||||||
<span>
|
|
||||||
<Tag className="action-btn" onClick={handleCancel} color="default">
|
|
||||||
Cancel
|
|
||||||
</Tag>
|
|
||||||
<Tag className="action-btn" onClick={handleSave} color="geekblue-inverse">
|
|
||||||
Save
|
|
||||||
</Tag>
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<Tag className="action-btn" title="Script Edit" onClick={handleEdit} color="blue-inverse">
|
|
||||||
<EditOutlined />
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
<Tag className="action-btn" title="Script Sync" onClick={handleSync} color="orange-inverse">
|
|
||||||
<FileSyncOutlined />
|
|
||||||
</Tag>
|
|
||||||
<span>
|
|
||||||
<Tag className="file-path" color="blue" onClick={handleGoFile}>
|
|
||||||
Path: {filePath}
|
|
||||||
</Tag>
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<Tag className="file-path" color="green" onClick={handleURL}>
|
|
||||||
URL: lencx/ChatGPT/scripts/{name}
|
|
||||||
</Tag>
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
71
src/view/scripts/config.tsx
vendored
71
src/view/scripts/config.tsx
vendored
@ -1,25 +1,37 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Tag, Space, Popconfirm } from 'antd';
|
import { Tag, Space, Popconfirm } from 'antd';
|
||||||
|
import { ArrowRightOutlined } from '@ant-design/icons';
|
||||||
import { path, shell } from '@tauri-apps/api';
|
import { path, shell } from '@tauri-apps/api';
|
||||||
|
|
||||||
import useInit from '@/hooks/useInit';
|
import useInit from '@/hooks/useInit';
|
||||||
import { fmtDate, chatRoot } from '@/utils';
|
import { fmtDate, chatRoot } from '@/utils';
|
||||||
|
|
||||||
export const scriptColumns = () => [
|
export const scriptColumns = ({ scriptsMap }: any) => [
|
||||||
{
|
{
|
||||||
title: 'File Name',
|
title: 'File Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
width: 120,
|
fixed: 'left',
|
||||||
render: (v: string) => <Tag>{v}</Tag>,
|
width: 160,
|
||||||
|
render: (v: string) => <Tag color={v === 'main.js' ? 'green' : 'default'}>{v}</Tag>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Version',
|
title: 'Version',
|
||||||
dataIndex: 'version',
|
width: 200,
|
||||||
key: 'version',
|
render: (_: string, row: any) => {
|
||||||
width: 120,
|
const next = scriptsMap?.[row.name]?.next_version;
|
||||||
render: (v: string) => <Tag>{v}</Tag>,
|
const curr = scriptsMap?.[row.name]?.curr_version;
|
||||||
|
return (
|
||||||
|
row.name !== 'main.js' && (
|
||||||
|
<Space>
|
||||||
|
{curr && <Tag style={{ marginRight: 0 }}>{curr}</Tag>}
|
||||||
|
{next && next !== curr && <ArrowRightOutlined style={{ color: '#989898' }} />}
|
||||||
|
{next && next !== curr && <Tag color="green-inverse">{next}</Tag>}
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Path',
|
title: 'Path',
|
||||||
@ -28,6 +40,14 @@ export const scriptColumns = () => [
|
|||||||
width: 200,
|
width: 200,
|
||||||
render: (_: string, row: any) => <RenderPath row={row} />,
|
render: (_: string, row: any) => <RenderPath row={row} />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Remote File',
|
||||||
|
width: 200,
|
||||||
|
render: (_: string, row: any) => {
|
||||||
|
const uri = `https://raw.githubusercontent.com/lencx/ChatGPT/main/scripts/${row.name}`;
|
||||||
|
return <a onClick={() => shell.open(uri)}>{uri}</a>;
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Created',
|
title: 'Created',
|
||||||
dataIndex: 'created',
|
dataIndex: 'created',
|
||||||
@ -38,28 +58,41 @@ export const scriptColumns = () => [
|
|||||||
{
|
{
|
||||||
title: 'Action',
|
title: 'Action',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 160,
|
width: 100,
|
||||||
render: (_: any, row: any, actions: any) => {
|
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 (
|
return (
|
||||||
<Space>
|
<Space>
|
||||||
<Link to={`/md/${row.id}`} state={row}>
|
<Link
|
||||||
|
to={`/scripts/${row.id}`}
|
||||||
|
state={row}
|
||||||
|
style={{ color: !isExternal ? '#ff4d4f' : '' }}
|
||||||
|
>
|
||||||
Edit
|
Edit
|
||||||
</Link>
|
</Link>
|
||||||
<Popconfirm
|
{!isExternal && next && next !== curr && (
|
||||||
title="Are you sure you want to synchronize? It will overwrite all previous modifications made to this file."
|
<Popconfirm
|
||||||
onConfirm={() => actions.setRecord(row, 'sync')}
|
placement="topLeft"
|
||||||
okText="Yes"
|
title="Are you sure you want to synchronize? It will overwrite all previous modifications made to this file."
|
||||||
cancelText="No"
|
onConfirm={() => actions.setRecord(row, 'sync')}
|
||||||
>
|
okText="Yes"
|
||||||
<a>Sync</a>
|
cancelText="No"
|
||||||
</Popconfirm>
|
overlayStyle={{ width: 300 }}
|
||||||
|
>
|
||||||
|
<a>Sync</a>
|
||||||
|
</Popconfirm>
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const RenderPath = ({ row }: any) => {
|
export const RenderPath = ({ row }: any) => {
|
||||||
const [filePath, setFilePath] = useState('');
|
const [filePath, setFilePath] = useState('');
|
||||||
useInit(async () => {
|
useInit(async () => {
|
||||||
setFilePath(await getPath(row));
|
setFilePath(await getPath(row));
|
||||||
@ -68,5 +101,5 @@ const RenderPath = ({ row }: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getPath = async (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}`);
|
||||||
};
|
};
|
||||||
|
10
src/view/scripts/index.scss
vendored
10
src/view/scripts/index.scss
vendored
@ -1,10 +0,0 @@
|
|||||||
.chatgpt-script {
|
|
||||||
.ant-collapse-header {
|
|
||||||
user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.script-editor {
|
|
||||||
height: 300px;
|
|
||||||
}
|
|
85
src/view/scripts/index.tsx
vendored
85
src/view/scripts/index.tsx
vendored
@ -1,17 +1,15 @@
|
|||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Table, Tag } from 'antd';
|
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 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 { scriptColumns } from './config';
|
||||||
import ScriptHead, { type ScriptInfo } from './Head';
|
|
||||||
import ScriptEditor from './Editor';
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
// const { Panel } = Collapse;
|
|
||||||
|
|
||||||
const SCRIPTS = [
|
const SCRIPTS = [
|
||||||
|
'main.js',
|
||||||
'core.js',
|
'core.js',
|
||||||
'chat.js',
|
'chat.js',
|
||||||
'cmd.js',
|
'cmd.js',
|
||||||
@ -22,51 +20,54 @@ const SCRIPTS = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function 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<string, any> = {};
|
||||||
|
|
||||||
const handleActiveKeyChange = (key: any) => {
|
for (const script of scripts) {
|
||||||
setActiveKey(key);
|
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 = {
|
useInit(handleInit);
|
||||||
onEdit(data: ScriptInfo) {
|
|
||||||
setActiveKey(data.name);
|
useEffect(() => {
|
||||||
},
|
if (!opInfo.opType) return;
|
||||||
activeKey,
|
(async () => {
|
||||||
};
|
if (opInfo.opType === 'sync') {
|
||||||
|
const isOk = await invoke('sync_scripts', { name: opInfo?.opRecord?.name });
|
||||||
|
if (isOk) {
|
||||||
|
await handleInit();
|
||||||
|
opInfo.resetRecord();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [opInfo.opType]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="chatgpt-script">
|
<div className="chatgpt-script">
|
||||||
<Table
|
<Table
|
||||||
|
rowKey="name"
|
||||||
|
scroll={{ x: 800 }}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={SCRIPTS.map((i) => ({ name: i }))}
|
dataSource={SCRIPTS.map((i) => ({ name: i }))}
|
||||||
{...TABLE_PAGINATION}
|
{...TABLE_PAGINATION}
|
||||||
|
pagination={false}
|
||||||
/>
|
/>
|
||||||
{/* <Tabs
|
|
||||||
items={SCRIPTS.map((i) => {
|
|
||||||
return {
|
|
||||||
label: <Tag>{i}</Tag>,
|
|
||||||
key: i,
|
|
||||||
children: <ScriptEditor />,
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
/> */}
|
|
||||||
{/* <Collapse
|
|
||||||
accordion
|
|
||||||
collapsible="icon"
|
|
||||||
activeKey={activeKey}
|
|
||||||
onChange={handleActiveKeyChange}
|
|
||||||
>
|
|
||||||
{SCRIPTS.map((i) => {
|
|
||||||
return (
|
|
||||||
<Panel header={<ScriptHead name={i} {...panelHeadProps} />} key={i}>
|
|
||||||
<ScriptEditor />
|
|
||||||
</Panel>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Collapse> */}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user