mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcd350584e | ||
|
|
050045f644 | ||
|
|
7e9440b45e | ||
|
|
cd9c0ac742 | ||
|
|
2d018c4967 | ||
|
|
f4d3cc6c8e | ||
|
|
cd6cece45e | ||
|
|
54b5b63f0e | ||
|
|
680f1b01ad | ||
|
|
078b0296f5 | ||
|
|
c956758a4a | ||
|
|
477120ef3b | ||
|
|
0ee95630ef | ||
|
|
fb0319a977 | ||
|
|
ea1a78abf5 | ||
|
|
3428e11b85 | ||
|
|
0e0771d0ec | ||
|
|
d78e2ad0b3 | ||
|
|
ae31da0b29 | ||
|
|
39febe759e | ||
|
|
06ee907199 | ||
|
|
f8c1ca5c56 | ||
|
|
6da58269bd | ||
|
|
4bf6c61bee | ||
|
|
a07c85a9cc | ||
|
|
95a9f12b68 | ||
|
|
252b0f3e15 | ||
|
|
ed268b32b3 | ||
|
|
e2319f2fda | ||
|
|
9ec69631f3 | ||
|
|
83437ffea7 | ||
|
|
be9846dc22 | ||
|
|
f071e0d6bc | ||
|
|
62a176d20c | ||
|
|
2f8ff36638 | ||
|
|
fe236e3c66 | ||
|
|
0b0b832130 |
34
.github/workflows/release.yml
vendored
34
.github/workflows/release.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
outputs:
|
||||
RELEASE_UPLOAD_ID: ${{ steps.create_release.outputs.id }}
|
||||
|
||||
@@ -36,34 +36,32 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: [macos-latest, ubuntu-latest, windows-latest]
|
||||
platform: [macos-latest, ubuntu-20.04, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v1
|
||||
- uses: actions/checkout@v3
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
# Rust cache
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
node-version: 16
|
||||
|
||||
- name: install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
- name: install dependencies (ubuntu only)
|
||||
if: matrix.platform == 'ubuntu-latest'
|
||||
if: matrix.platform == 'ubuntu-20.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
- name: Install app dependencies and build it
|
||||
run: yarn && yarn build:fe
|
||||
|
||||
- name: fix tray icon
|
||||
if: matrix.platform != 'macos-latest'
|
||||
run: |
|
||||
yarn fix:tray
|
||||
|
||||
- uses: tauri-apps/tauri-action@v0.3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -74,7 +72,7 @@ jobs:
|
||||
releaseId: ${{ needs.create-release.outputs.RELEASE_UPLOAD_ID }}
|
||||
|
||||
updater:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
needs: [create-release, build-tauri]
|
||||
|
||||
steps:
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
**最新版:**
|
||||
|
||||
- `Mac`: [ChatGPT_0.6.6_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/ChatGPT_0.6.6_x64.dmg)
|
||||
- `Linux`: [chat-gpt_0.6.6_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/chat-gpt_0.6.6_amd64.deb)
|
||||
- `Windows`: [ChatGPT_0.6.6_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/ChatGPT_0.6.6_x64_en-US.msi)
|
||||
- `Mac`: [ChatGPT_0.7.1_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/ChatGPT_0.7.1_x64.dmg)
|
||||
- `Linux`: [chat-gpt_0.7.1_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/chat-gpt_0.7.1_amd64.deb)
|
||||
- `Windows`: [ChatGPT_0.7.1_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/ChatGPT_0.7.1_x64_en-US.msi)
|
||||
|
||||
[其他版本...](https://github.com/lencx/ChatGPT/releases)
|
||||
|
||||
@@ -60,7 +60,7 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
||||
|
||||
数据导入完成后,可以重新启动应用来使配置生效(`Menu -> Preferences -> Restart ChatGPT`)。
|
||||
|
||||
在 ChatGPT 文本输入区域,键入 `/` 开头的字符,则会弹出指令提示,按下空格键,它会默认将命令关联的文本填充到输入区域(注意:如果包含多个指令提示,它只会选择第一个作为填充,你可以持续输入,直到第一个提示命令为你想要时,再按下空格键。或者使用鼠标来点击多条指令中的某一个)。填充完成后,你只需要按下回车键即可。斜杠命令下,使用 TAB 键修改 `{q}` 标签内容(仅支持单个修改 [#54](https://github.com/lencx/ChatGPT/issues/54))。
|
||||
在 ChatGPT 文本输入区域,键入 `/` 开头的字符,则会弹出指令提示,按下空格键,它会默认将命令关联的文本填充到输入区域(注意:如果包含多个指令提示,它只会选择第一个作为填充,你可以持续输入,直到第一个提示命令为你想要时,再按下空格键。或者使用鼠标来点击多条指令中的某一个)。填充完成后,你只需要按下回车键即可。斜杠命令下,使用 TAB 键修改 `{q}` 标签内容(仅支持单个修改 [#54](https://github.com/lencx/ChatGPT/issues/54))。使用键盘 `⇧` 和 `⇩`(上下键)来选择斜杠指令。
|
||||
|
||||

|
||||

|
||||
@@ -74,6 +74,7 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
||||
- 系统托盘悬浮窗
|
||||
- 应用菜单功能强大
|
||||
- 支持斜杠命令及其配置(可手动配置或从文件同步 [#55](https://github.com/lencx/ChatGPT/issues/55))
|
||||
- 进入应用的全局快捷键 (mac: `command+shift+o`, windows: `ctrl+shift+o`)
|
||||
|
||||
### 菜单项
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -24,9 +24,9 @@
|
||||
|
||||
**Latest:**
|
||||
|
||||
- `Mac`: [ChatGPT_0.6.6_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/ChatGPT_0.6.6_x64.dmg)
|
||||
- `Linux`: [chat-gpt_0.6.6_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/chat-gpt_0.6.6_amd64.deb)
|
||||
- `Windows`: [ChatGPT_0.6.6_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.6.6/ChatGPT_0.6.6_x64_en-US.msi)
|
||||
- `Mac`: [ChatGPT_0.7.1_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/ChatGPT_0.7.1_x64.dmg)
|
||||
- `Linux`: [chat-gpt_0.7.1_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/chat-gpt_0.7.1_amd64.deb)
|
||||
- `Windows`: [ChatGPT_0.7.1_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.7.1/ChatGPT_0.7.1_x64_en-US.msi)
|
||||
|
||||
[Other version...](https://github.com/lencx/ChatGPT/releases)
|
||||
|
||||
@@ -62,7 +62,7 @@ You can look at [awesome-chatgpt-prompts](https://github.com/f/awesome-chatgpt-p
|
||||
|
||||
After the data import is done, you can restart the app to make the configuration take effect (`Menu -> Preferences -> Restart ChatGPT`).
|
||||
|
||||
In the chatgpt text input area, type a character starting with `/` to bring up the command prompt, press the spacebar, and it will fill the input area with the text associated with the command by default (note: if it contains multiple command prompts, it will only select the first one as the fill, you can keep typing until the first prompted command is the one you want, then press the spacebar. Or use the mouse to click on one of the multiple commands). When the fill is complete, you simply press the Enter key. Under the slash command, use the tab key to modify the contents of the `{q}` tag (only single changes are supported [#54](https://github.com/lencx/ChatGPT/issues/54)).
|
||||
In the chatgpt text input area, type a character starting with `/` to bring up the command prompt, press the spacebar, and it will fill the input area with the text associated with the command by default (note: if it contains multiple command prompts, it will only select the first one as the fill, you can keep typing until the first prompted command is the one you want, then press the spacebar. Or use the mouse to click on one of the multiple commands). When the fill is complete, you simply press the Enter key. Under the slash command, use the tab key to modify the contents of the `{q}` tag (only single changes are supported [#54](https://github.com/lencx/ChatGPT/issues/54)). Use the keyboard `⇧` (arrow up) and `⇩` (arrow down) keys to select the slash command.
|
||||
|
||||

|
||||

|
||||
@@ -76,6 +76,7 @@ In the chatgpt text input area, type a character starting with `/` to bring up t
|
||||
- System tray hover window
|
||||
- Powerful menu items
|
||||
- Support for slash commands and their configuration (can be configured manually or synchronized from a file [#55](https://github.com/lencx/ChatGPT/issues/55))
|
||||
- Global shortcuts to the chatgpt app (mac: `command+shift+o`, windows: `ctrl+shift+o`)
|
||||
|
||||
### MenuItem
|
||||
|
||||
@@ -154,7 +155,7 @@ Currently, only json and csv are supported for synchronizing custom files, and t
|
||||
|
||||
## TODO
|
||||
|
||||
- Web access capability ([#20](https://github.com/lencx/ChatGPT/issues/20))
|
||||
<!-- - Web access capability ([#20](https://github.com/lencx/ChatGPT/issues/20)) -->
|
||||
- `Control Center` - Feature Enhancements
|
||||
- ...
|
||||
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
# UPDATE LOG
|
||||
|
||||
## v0.6.6
|
||||
## v0.7.1
|
||||
|
||||
fix: unable to synchronize
|
||||
fix:
|
||||
- some windows systems cannot start the application
|
||||
- windows and linux add about menu (show version information)
|
||||
- the tray icon is indistinguishable from the background in dark mode on window and linux
|
||||
|
||||
## v0.7.0
|
||||
|
||||
fix:
|
||||
- mac m1 copy/paste does not work on some system versions
|
||||
- optimize the save chat log button to a small icon, the tray window no longer provides a save chat log button (the buttons causes the input area to become larger and the content area to become smaller)
|
||||
|
||||
feat:
|
||||
- use the keyboard `⇧` (arrow up) and `⇩` (arrow down) keys to select the slash command
|
||||
- global shortcuts to the chatgpt app (mac: command+shift+o, windows: ctrl+shift+o)
|
||||
|
||||
## v0.6.10
|
||||
|
||||
fix: sync failure on windows
|
||||
|
||||
## v0.6.4
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cask "chatgpt" do
|
||||
version "0.1.7"
|
||||
sha256 "1320b30a67e2506f9b45ffd2a48243d6141171c231dd698994ae5156a637eb3f"
|
||||
version "0.6.10"
|
||||
sha256 "e85062565f826d32219c53b184d6df9c89441d4231cdfff775c2de8c50ac9906"
|
||||
|
||||
url "https://github.com/lencx/ChatGPT/releases/download/v#{version}/ChatGPT_#{version}_x64.dmg"
|
||||
name "ChatGPT"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
"build": "yarn tauri build",
|
||||
"updater": "tr updater",
|
||||
"release": "tr release --git",
|
||||
"fix:tray": "tr override --json.tauri_systemTray_iconPath=\"icons/tray-icon-light.png\" --json.tauri_systemTray_iconAsTemplate=false",
|
||||
"fix:tray:mac": "tr override --json.tauri_systemTray_iconPath=\"icons/tray-icon.png\" --json.tauri_systemTray_iconAsTemplate=true",
|
||||
"download": "node ./scripts/download.js",
|
||||
"tr": "tr",
|
||||
"tauri": "tauri"
|
||||
|
||||
@@ -17,7 +17,7 @@ tauri-build = {version = "1.2.1", features = [] }
|
||||
anyhow = "1.0.66"
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
|
||||
tauri = { version = "1.2.3", features = ["api-all", "devtools", "system-tray", "updater"] }
|
||||
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
|
||||
log = "0.4.17"
|
||||
csv = "1.1.6"
|
||||
@@ -45,4 +45,4 @@ custom-protocol = [ "tauri/custom-protocol" ]
|
||||
[profile.release]
|
||||
strip = true
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
opt-level = "s"
|
||||
|
||||
BIN
src-tauri/icons/tray-icon-light.png
Normal file
BIN
src-tauri/icons/tray-icon-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
@@ -1,4 +1,7 @@
|
||||
use crate::{conf::ChatConfJson, utils::{self, exists}};
|
||||
use crate::{
|
||||
conf::ChatConfJson,
|
||||
utils::{self, exists},
|
||||
};
|
||||
use std::{collections::HashMap, fs, path::PathBuf};
|
||||
use tauri::{api, command, AppHandle, Manager};
|
||||
|
||||
@@ -152,10 +155,15 @@ pub fn sync_prompts(app: AppHandle, data: String, time: u64) {
|
||||
let chatgpt_prompts = chat_root().join("cache_model").join("chatgpt_prompts.json");
|
||||
|
||||
if !exists(&model) {
|
||||
fs::write(&model, serde_json::json!({
|
||||
"name": "ChatGPT Model",
|
||||
"link": "https://github.com/lencx/ChatGPT"
|
||||
}).to_string()).unwrap();
|
||||
fs::write(
|
||||
&model,
|
||||
serde_json::json!({
|
||||
"name": "ChatGPT Model",
|
||||
"link": "https://github.com/lencx/ChatGPT"
|
||||
})
|
||||
.to_string(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// chatgpt_prompts.json
|
||||
|
||||
@@ -16,19 +16,23 @@ pub fn init() -> Menu {
|
||||
let name = "ChatGPT";
|
||||
let app_menu = Submenu::new(
|
||||
name,
|
||||
Menu::new()
|
||||
.add_native_item(MenuItem::About(name.into(), AboutMetadata::default()))
|
||||
.add_native_item(MenuItem::Services)
|
||||
.add_native_item(MenuItem::Separator)
|
||||
.add_native_item(MenuItem::Hide)
|
||||
.add_native_item(MenuItem::HideOthers)
|
||||
.add_native_item(MenuItem::ShowAll)
|
||||
.add_native_item(MenuItem::Separator)
|
||||
.add_native_item(MenuItem::Quit),
|
||||
);
|
||||
Menu::with_items([
|
||||
#[cfg(target_os = "macos")]
|
||||
MenuItem::About(name.into(), AboutMetadata::default()).into(),
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
CustomMenuItem::new("about".to_string(), "About ChatGPT")
|
||||
.into(),
|
||||
MenuItem::Services.into(),
|
||||
MenuItem::Hide.into(),
|
||||
MenuItem::HideOthers.into(),
|
||||
MenuItem::ShowAll.into(),
|
||||
MenuItem::Separator.into(),
|
||||
MenuItem::Quit.into(),
|
||||
]));
|
||||
|
||||
let stay_on_top =
|
||||
CustomMenuItem::new("stay_on_top".to_string(), "Stay On Top").accelerator("CmdOrCtrl+T");
|
||||
#[cfg(target_os = "macos")]
|
||||
let titlebar =
|
||||
CustomMenuItem::new("titlebar".to_string(), "Titlebar").accelerator("CmdOrCtrl+B");
|
||||
let theme_light = CustomMenuItem::new("theme_light".to_string(), "Light");
|
||||
@@ -40,6 +44,7 @@ pub fn init() -> Menu {
|
||||
} else {
|
||||
stay_on_top
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
let titlebar_menu = if chat_conf.titlebar {
|
||||
titlebar.selected()
|
||||
} else {
|
||||
@@ -175,6 +180,11 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
||||
let menu_handle = core_window.menu_handle();
|
||||
|
||||
match menu_id {
|
||||
// App
|
||||
"about" => {
|
||||
let tauri_conf = utils::get_tauri_conf().unwrap();
|
||||
tauri::api::dialog::message(app.get_window("core").as_ref(), "ChatGPT", format!("Version {}", tauri_conf.package.version.unwrap()));
|
||||
}
|
||||
// Preferences
|
||||
"control_center" => window::control_window(&app),
|
||||
"restart" => tauri::api::process::restart(&app.env()),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{app::window, conf::ChatConfJson, utils};
|
||||
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, Manager};
|
||||
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, GlobalShortcutManager, Manager};
|
||||
|
||||
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||
let chat_conf = ChatConfJson::get_chat_conf();
|
||||
@@ -11,6 +11,27 @@ pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>
|
||||
window::tray_window(&handle);
|
||||
});
|
||||
|
||||
{
|
||||
let handle = app.app_handle();
|
||||
let mut shortcut = app.global_shortcut_manager();
|
||||
let is_mini_key = shortcut.is_registered("CmdOrCtrl+Shift+O");
|
||||
|
||||
if !is_mini_key.unwrap() {
|
||||
shortcut
|
||||
.register("CmdOrCtrl+Shift+O", move || {
|
||||
if let Some(w) = handle.get_window("core") {
|
||||
if w.is_visible().unwrap() {
|
||||
w.hide().unwrap();
|
||||
} else {
|
||||
w.show().unwrap();
|
||||
w.set_focus().unwrap();
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
};
|
||||
}
|
||||
|
||||
if chat_conf.hide_dock_icon {
|
||||
#[cfg(target_os = "macos")]
|
||||
app.set_activation_policy(tauri::ActivationPolicy::Accessory);
|
||||
|
||||
@@ -16,10 +16,7 @@ pub fn tray_window(handle: &tauri::AppHandle) {
|
||||
.always_on_top(true)
|
||||
.theme(theme)
|
||||
.initialization_script(&utils::user_script())
|
||||
.initialization_script(include_str!("../assets/html2canvas.js"))
|
||||
.initialization_script(include_str!("../assets/jspdf.js"))
|
||||
.initialization_script(include_str!("../assets/core.js"))
|
||||
.initialization_script(include_str!("../assets/export.js"))
|
||||
.initialization_script(include_str!("../assets/cmd.js"))
|
||||
.user_agent(&chat_conf.ua_tray)
|
||||
.build()
|
||||
|
||||
89
src-tauri/src/assets/cmd.js
vendored
89
src-tauri/src/assets/cmd.js
vendored
@@ -28,6 +28,9 @@ function init() {
|
||||
.chat-model-cmd-list .cmd-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.chat-model-cmd-list .cmd-item.selected {
|
||||
background: #fea;
|
||||
}
|
||||
.chat-model-cmd-list .cmd-item b {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
@@ -46,7 +49,16 @@ function init() {
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
color: #888;
|
||||
}`;
|
||||
}
|
||||
.chatappico {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.chatappico.pdf {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
`;
|
||||
document.head.append(styleDom);
|
||||
|
||||
if (window.formInterval) {
|
||||
@@ -70,11 +82,24 @@ async function cmdTip() {
|
||||
|
||||
// fix: tray window
|
||||
if (__TAURI_METADATA__.__currentWindow.label === 'tray') {
|
||||
modelDom.style.bottom = '40px';
|
||||
modelDom.style.bottom = '54px';
|
||||
}
|
||||
|
||||
document.querySelector('form').appendChild(modelDom);
|
||||
const itemDom = (v) => `<div class="cmd-item" title="${v.prompt}" data-prompt="${encodeURIComponent(v.prompt)}"><b title="${v.cmd}">/${v.cmd}</b><i>${v.act}</i></div>`;
|
||||
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) => {
|
||||
modelDom.innerHTML = `<div>${v.map(itemDom).join('')}</div>`;
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = v[0]?.prompt.trim();
|
||||
window.__CHAT_MODEL_CMD__ = v[0]?.cmd.trim();
|
||||
window.__list = modelDom.querySelectorAll('.cmd-item');
|
||||
window.__index = 0;
|
||||
window.__list[window.__index].classList.add('selected');
|
||||
};
|
||||
const setPrompt = (v = '') => {
|
||||
if (v.trim()) {
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_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`.
|
||||
@@ -84,6 +109,35 @@ async function cmdTip() {
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------ Keyboard scrolling (ArrowUp | ArrowDown) --------------------------
|
||||
if (event.keyCode === 38 && window.__index > 0) { // ArrowUp
|
||||
window.__list[window.__index].classList.remove('selected');
|
||||
window.__index = window.__index - 1;
|
||||
window.__list[window.__index].classList.add('selected');
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = decodeURIComponent(window.__list[window.__index].getAttribute('data-prompt'));
|
||||
searchInput.value = `/${window.__list[window.__index].getAttribute('data-cmd')}`;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (event.keyCode === 40 && window.__index < window.__list.length - 1) { // ArrowDown
|
||||
window.__list[window.__index].classList.remove('selected');
|
||||
window.__index = window.__index + 1;
|
||||
window.__list[window.__index].classList.add('selected');
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = decodeURIComponent(window.__list[window.__index].getAttribute('data-prompt'));
|
||||
searchInput.value = `/${window.__list[window.__index].getAttribute('data-cmd')}`;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
const containerHeight = modelDom.offsetHeight;
|
||||
const itemHeight = window.__list[0].offsetHeight + 1;
|
||||
|
||||
const itemTop = window.__list[window.__index].offsetTop;
|
||||
const itemBottom = itemTop + itemHeight;
|
||||
if (itemTop < modelDom.scrollTop || itemBottom > modelDom.scrollTop + containerHeight) {
|
||||
modelDom.scrollTop = itemTop;
|
||||
}
|
||||
|
||||
// ------------------ TAB key replaces `{q}` tag content -------------------------------
|
||||
// feat: https://github.com/lencx/ChatGPT/issues/54
|
||||
if (event.keyCode === 9 && !window.__CHAT_MODEL_STATUS__) {
|
||||
const strGroup = window.__CHAT_MODEL_CMD_PROMPT__.match(/\{([^{}]*)\}/) || [];
|
||||
@@ -95,36 +149,37 @@ async function cmdTip() {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (window.__CHAT_MODEL_STATUS__ === 1 && event.keyCode === 9) {
|
||||
if (window.__CHAT_MODEL_STATUS__ === 1 && event.keyCode === 9) { // TAB
|
||||
const data = searchInput.value.split('|->');
|
||||
if (data[1]?.trim()) {
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_CMD_PROMPT__?.replace(/\{([^{}]*)\}/, `{${data[1]?.trim()}}`);
|
||||
setPrompt(data[1]);
|
||||
window.__CHAT_MODEL_STATUS__ = 2;
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// input text
|
||||
if (window.__CHAT_MODEL_STATUS__ === 2 && event.keyCode === 9) {
|
||||
if (window.__CHAT_MODEL_STATUS__ === 2 && event.keyCode === 9) { // TAB
|
||||
searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
modelDom.innerHTML = '';
|
||||
delete window.__CHAT_MODEL_STATUS__;
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// type in a space to complete the fill
|
||||
// ------------------ type in a space to complete the fill ------------------------------------
|
||||
if (event.keyCode === 32) {
|
||||
searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
modelDom.innerHTML = '';
|
||||
delete window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
}
|
||||
|
||||
// send
|
||||
if (event.keyCode === 13 && window.__CHAT_MODEL_CMD_PROMPT__) {
|
||||
console.log('«174» /src/assets/cmd.js ~> ', window.__CHAT_MODEL_CMD_PROMPT__);
|
||||
|
||||
|
||||
// ------------------ send --------------------------------------------------------------------
|
||||
if (event.keyCode === 13 && window.__CHAT_MODEL_CMD_PROMPT__) { // Enter
|
||||
const data = searchInput.value.split('|->');
|
||||
if (data[1]?.trim()) {
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = window.__CHAT_MODEL_CMD_PROMPT__?.replace(/\{([^{}]*)\}/, `{${data[1]?.trim()}}`);
|
||||
}
|
||||
setPrompt(data[1]);
|
||||
|
||||
searchInput.value = window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
modelDom.innerHTML = '';
|
||||
@@ -135,7 +190,7 @@ async function cmdTip() {
|
||||
}
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', (event) => {
|
||||
searchInput.addEventListener('input', () => {
|
||||
if (searchInput.value === '') {
|
||||
delete window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
delete window.__CHAT_MODEL_CMD__;
|
||||
@@ -152,17 +207,13 @@ async function cmdTip() {
|
||||
|
||||
// all cmd result
|
||||
if (query === '/') {
|
||||
modelDom.innerHTML = `<div>${data.map(itemDom).join('')}</div>`;
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = data[0]?.prompt.trim();
|
||||
window.__CHAT_MODEL_CMD__ = data[0]?.cmd.trim();
|
||||
renderList(data);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = data.filter(i => new RegExp(query.substring(1)).test(i.cmd));
|
||||
if (result.length > 0) {
|
||||
modelDom.innerHTML = `<div>${result.map(itemDom).join('')}</div>`;
|
||||
window.__CHAT_MODEL_CMD_PROMPT__ = result[0]?.prompt.trim();
|
||||
window.__CHAT_MODEL_CMD__ = result[0]?.cmd.trim();
|
||||
renderList(result);
|
||||
} else {
|
||||
modelDom.innerHTML = '';
|
||||
delete window.__CHAT_MODEL_CMD_PROMPT__;
|
||||
|
||||
2
src-tauri/src/assets/core.js
vendored
2
src-tauri/src/assets/core.js
vendored
@@ -91,8 +91,6 @@ async function init() {
|
||||
const res = await fetch('https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv');
|
||||
if (res.ok) {
|
||||
const data = await res.text();
|
||||
console.log('«94» /src/assets/core.js ~> ', data);
|
||||
|
||||
await invoke('sync_prompts', { data, time: Date.now() });
|
||||
} else {
|
||||
invoke('messageDialog', {
|
||||
|
||||
23
src-tauri/src/assets/export.js
vendored
23
src-tauri/src/assets/export.js
vendored
@@ -3,6 +3,7 @@
|
||||
|
||||
const buttonOuterHTMLFallback = `<button class="btn flex justify-center gap-2 btn-neutral" id="download-png-button">Try Again</button>`;
|
||||
async function init() {
|
||||
if (window.innerWidth < 767) return;
|
||||
const chatConf = await invoke('get_chat_conf') || {};
|
||||
if (window.buttonsInterval) {
|
||||
clearInterval(window.buttonsInterval);
|
||||
@@ -88,7 +89,9 @@ function addActionsButtons(actionsArea, TryAgainButton) {
|
||||
const downloadButton = TryAgainButton.cloneNode(true);
|
||||
downloadButton.id = "download-png-button";
|
||||
downloadButton.setAttribute("share-ext", "true");
|
||||
downloadButton.innerText = "Generate PNG";
|
||||
// downloadButton.innerText = "Generate PNG";
|
||||
downloadButton.title = "Generate PNG";
|
||||
downloadButton.innerHTML = setIcon('png');
|
||||
downloadButton.onclick = () => {
|
||||
downloadThread();
|
||||
};
|
||||
@@ -96,7 +99,9 @@ function addActionsButtons(actionsArea, TryAgainButton) {
|
||||
const downloadPdfButton = TryAgainButton.cloneNode(true);
|
||||
downloadPdfButton.id = "download-pdf-button";
|
||||
downloadButton.setAttribute("share-ext", "true");
|
||||
downloadPdfButton.innerText = "Download PDF";
|
||||
// downloadPdfButton.innerText = "Download PDF";
|
||||
downloadPdfButton.title = "Download PDF";
|
||||
downloadPdfButton.innerHTML = setIcon('pdf');
|
||||
downloadPdfButton.onclick = () => {
|
||||
downloadThread({ as: Format.PDF });
|
||||
};
|
||||
@@ -104,7 +109,9 @@ function addActionsButtons(actionsArea, TryAgainButton) {
|
||||
const exportHtml = TryAgainButton.cloneNode(true);
|
||||
exportHtml.id = "download-html-button";
|
||||
downloadButton.setAttribute("share-ext", "true");
|
||||
exportHtml.innerText = "Share Link";
|
||||
// exportHtml.innerText = "Share Link";
|
||||
exportHtml.title = "Share Link";
|
||||
exportHtml.innerHTML = setIcon('link');
|
||||
exportHtml.onclick = () => {
|
||||
sendRequest();
|
||||
};
|
||||
@@ -269,4 +276,12 @@ if (
|
||||
init();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
}
|
||||
}
|
||||
|
||||
function setIcon(type) {
|
||||
return {
|
||||
link: `<svg class="chatappico" viewBox="0 0 1024 1024"><path d="M1007.382 379.672L655.374 75.702C624.562 49.092 576 70.694 576 112.03v160.106C254.742 275.814 0 340.2 0 644.652c0 122.882 79.162 244.618 166.666 308.264 27.306 19.862 66.222-5.066 56.154-37.262C132.132 625.628 265.834 548.632 576 544.17V720c0 41.4 48.6 62.906 79.374 36.328l352.008-304c22.142-19.124 22.172-53.506 0-72.656z" p-id="8506" fill="#4a4a4a"></path></svg>`,
|
||||
png: `<svg class="chatappico" viewBox="0 0 1070 1024"><path d="M981.783273 0H85.224727C38.353455 0 0 35.374545 0 83.083636v844.893091c0 47.616 38.353455 86.574545 85.178182 86.574546h903.633454c46.917818 0 81.733818-38.958545 81.733819-86.574546V83.083636C1070.592 35.374545 1028.701091 0 981.783273 0zM335.825455 135.912727c74.193455 0 134.330182 60.974545 134.330181 136.285091 0 75.170909-60.136727 136.192-134.330181 136.192-74.286545 0-134.516364-61.021091-134.516364-136.192 0-75.264 60.229818-136.285091 134.516364-136.285091z m-161.512728 745.937455a41.890909 41.890909 0 0 1-27.648-10.379637 43.752727 43.752727 0 0 1-4.654545-61.067636l198.097454-255.162182a42.123636 42.123636 0 0 1 57.716364-6.702545l116.549818 128.139636 286.906182-352.814545c14.615273-18.711273 90.251636-106.775273 135.866182-6.935273 0.093091-0.093091 0.093091 112.965818 0.232727 247.761455 0.093091 140.8 0.093091 317.067636 0.093091 317.067636-1.024-0.093091-762.740364 0.093091-763.112727 0.093091z" fill="#4a4a4a"></path></svg>`,
|
||||
pdf: `<svg class="chatappico pdf" viewBox="0 0 1024 1024"><path d="M821.457602 118.382249H205.725895c-48.378584 0-87.959995 39.583368-87.959996 87.963909v615.731707c0 48.378584 39.581411 87.959995 87.959996 87.959996h615.733664c48.380541 0 87.961952-39.581411 87.961952-87.959996V206.346158c-0.001957-48.378584-39.583368-87.963909-87.963909-87.963909zM493.962468 457.544987c-10.112054 32.545237-21.72487 82.872662-38.806571 124.248336-8.806957 22.378397-8.380404 18.480717-15.001764 32.609808l5.71738-1.851007c58.760658-16.443827 99.901532-20.519564 138.162194-27.561607-7.67796-6.06371-14.350194-10.751884-19.631237-15.586807-26.287817-29.101504-35.464584-34.570387-70.440002-111.862636v0.003913z m288.36767 186.413594c-7.476424 8.356924-20.670227 13.191847-40.019704 13.191847-33.427694 0-63.808858-9.229597-107.79277-31.660824-75.648648 8.356924-156.097 17.214754-201.399704 31.729308-2.199293 0.876587-4.832967 1.759043-7.916674 3.077836-54.536215 93.237125-95.031389 132.767663-130.621199 131.19646-11.286054-0.49895-27.694661-7.044-32.973748-10.11988l-6.52157-6.196764-2.29517-4.353583c-3.07588-7.91863-3.954423-15.395054-2.197337-23.751977 4.838837-23.309771 29.907651-60.251638 82.686779-93.237126 8.356924-6.159587 27.430511-15.897917 45.020944-24.25484 13.311204-21.177004 19.45905-34.744531 36.341171-72.259702 19.102937-45.324228 36.505531-99.492589 47.500041-138.191543v-0.44025c-16.267727-53.219378-25.945401-89.310095-9.67376-147.80856 3.958337-16.71189 18.46702-33.864031 34.748444-33.864031h10.552304c10.115967 0 19.791684 3.520043 26.829814 10.552304 29.029107 29.031064 15.39114 103.824649 0.8805 162.323113-0.8805 2.63563-1.322707 4.832967-1.761 6.153717 17.59239 49.697378 45.400538 98.774492 73.108895 121.647926 11.436717 8.791304 22.638634 18.899444 36.71098 26.814161 19.791684-2.20125 37.517128-4.11487 55.547812-4.11487 54.540128 0 87.525615 9.67963 100.279169 30.351814 4.400543 7.034217 6.595923 15.389184 5.281043 24.1844-0.44025 10.996467-4.39663 21.112434-12.31526 29.031064z m-27.796407-36.748157c-4.394673-4.398587-17.024957-16.936907-78.601259-16.936907-3.073923 0-10.622744-0.784623-14.57521 3.612007 32.104987 14.072347 62.830525 24.757704 83.058545 24.757703 3.083707 0 5.72325-0.442207 8.356923-0.876586h1.759044c2.20125-0.8805 3.520043-1.324663 3.960293-5.71738-0.87463-1.324663-1.757087-3.083707-3.958336-4.838837z m-387.124553 63.041845c-9.237424 5.27713-16.71189 10.112054-21.112433 13.634053-31.226444 28.586901-51.018128 57.616008-53.217422 74.331812 19.789727-6.59788 45.737084-35.626987 74.329855-87.961952v-0.003913z m125.574957-297.822284l2.197336-1.761c3.079793-14.072347 5.232127-29.189554 7.87167-38.869184l1.318794-7.036174c4.39663-25.070771 2.71781-39.720334-4.76057-50.272637l-6.59788-2.20125a57.381208 57.381208 0 0 0-3.079794 5.27713c-7.474467 18.47289-7.063567 55.283661 3.0524 94.865072l-0.001956-0.001957z" fill="#4a4a4a"></path></svg>`
|
||||
}[type];
|
||||
}
|
||||
|
||||
@@ -8,19 +8,18 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
use tauri::Manager;
|
||||
// use tauri::utils::config::Config;
|
||||
use tauri::{Manager, utils::config::Config};
|
||||
|
||||
pub fn chat_root() -> PathBuf {
|
||||
tauri::api::path::home_dir().unwrap().join(".chatgpt")
|
||||
}
|
||||
|
||||
// pub fn get_tauri_conf() -> Option<Config> {
|
||||
// let config_file = include_str!("../tauri.conf.json");
|
||||
// let config: Config =
|
||||
// serde_json::from_str(config_file).expect("failed to parse tauri.conf.json");
|
||||
// Some(config)
|
||||
// }
|
||||
pub fn get_tauri_conf() -> Option<Config> {
|
||||
let config_file = include_str!("../tauri.conf.json");
|
||||
let config: Config =
|
||||
serde_json::from_str(config_file).expect("failed to parse tauri.conf.json");
|
||||
Some(config)
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> bool {
|
||||
Path::new(path).exists()
|
||||
|
||||
@@ -7,11 +7,14 @@
|
||||
},
|
||||
"package": {
|
||||
"productName": "ChatGPT",
|
||||
"version": "0.6.6"
|
||||
"version": "0.7.1"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": true,
|
||||
"globalShortcut": {
|
||||
"all": true
|
||||
},
|
||||
"http": {
|
||||
"all": true,
|
||||
"scope": [
|
||||
@@ -22,9 +25,7 @@
|
||||
"fs": {
|
||||
"all": true,
|
||||
"scope": [
|
||||
"*",
|
||||
"$HOME/.chatgpt/*",
|
||||
"$HOME/.chatgpt/cache_sync/*"
|
||||
"$HOME/.chatgpt/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
14
src/utils.ts
vendored
14
src/utils.ts
vendored
@@ -1,4 +1,4 @@
|
||||
import { readTextFile, writeTextFile, exists, createDir, BaseDirectory } from '@tauri-apps/api/fs';
|
||||
import { readTextFile, writeTextFile, exists, createDir } from '@tauri-apps/api/fs';
|
||||
import { homeDir, join, dirname } from '@tauri-apps/api/path';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@@ -28,7 +28,11 @@ type readJSONOpts = { defaultVal?: Record<string, any>, isRoot?: boolean, isList
|
||||
export const readJSON = async (path: string, opts: readJSONOpts = {}) => {
|
||||
const { defaultVal = {}, isRoot = false, isList = false } = opts;
|
||||
const root = await chatRoot();
|
||||
const file = await join(isRoot ? '' : root, path);
|
||||
let file = path;
|
||||
|
||||
if (!isRoot) {
|
||||
file = await join(root, path);
|
||||
}
|
||||
|
||||
if (!await exists(file)) {
|
||||
if (await dirname(file) !== root) {
|
||||
@@ -52,7 +56,11 @@ type writeJSONOpts = { dir?: string, isRoot?: boolean };
|
||||
export const writeJSON = async (path: string, data: Record<string, any>, opts: writeJSONOpts = {}) => {
|
||||
const { isRoot = false } = opts;
|
||||
const root = await chatRoot();
|
||||
const file = await join(isRoot ? '' : root, path);
|
||||
let file = path;
|
||||
|
||||
if (!isRoot) {
|
||||
file = await join(root, path);
|
||||
}
|
||||
|
||||
if (isRoot && !await exists(await dirname(file))) {
|
||||
await createDir(await dirname(file), { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user