mirror of
https://github.com/FranP-code/ChatGPT.git
synced 2025-10-13 00:13:25 +00:00
Merge pull request #32 from lencx/dev
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1 +1,3 @@
|
|||||||
*.js linguist-vendored
|
*.js linguist-vendored
|
||||||
|
*.tsx linguist-vendored
|
||||||
|
*.scss linguist-vendored
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -75,7 +75,7 @@ jobs:
|
|||||||
${{ runner.os }}-yarn-
|
${{ runner.os }}-yarn-
|
||||||
|
|
||||||
- name: Install app dependencies and build it
|
- name: Install app dependencies and build it
|
||||||
run: yarn
|
run: yarn && yarn build:fe
|
||||||
|
|
||||||
- uses: tauri-apps/tauri-action@v0.3
|
- uses: tauri-apps/tauri-action@v0.3
|
||||||
env:
|
env:
|
||||||
|
|||||||
29
.gitignore
vendored
29
.gitignore
vendored
@@ -1,9 +1,32 @@
|
|||||||
.DS_Store
|
|
||||||
*.lock
|
|
||||||
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
node_modules/
|
node_modules/
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
*.lock
|
||||||
|
|
||||||
|
# rust
|
||||||
target/
|
target/
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
- [ChatGPT Export and Share](https://github.com/liady/ChatGPT-pdf) - A Chrome extension for downloading your ChatGPT history to PNG, PDF or creating a sharable link
|
- [ChatGPT Export and Share](https://github.com/liady/ChatGPT-pdf) - A Chrome extension for downloading your ChatGPT history to PNG, PDF or creating a sharable link
|
||||||
- [ChatGPT for Google](https://github.com/wong2/chat-gpt-google-extension) - A browser extension to display ChatGPT response alongside Google Search results
|
- [ChatGPT for Google](https://github.com/wong2/chat-gpt-google-extension) - A browser extension to display ChatGPT response alongside Google Search results
|
||||||
- [ChatGPT Extension](https://github.com/kazuki-sf/ChatGPT_Extension) - ChatGPT Extension is a really simple Chrome Extension (manifest v3) that you can access OpenAI's ChatGPT from anywhere on the web.
|
- [ChatGPT Extension](https://github.com/kazuki-sf/ChatGPT_Extension) - ChatGPT Extension is a really simple Chrome Extension (manifest v3) that you can access OpenAI's ChatGPT from anywhere on the web.
|
||||||
|
- [ChatGPT-Google](https://github.com/ZohaibAhmed/ChatGPT-Google) - Chrome Extension that Integrates ChatGPT (Unofficial) into Google Search
|
||||||
|
|
||||||
`VSCode`
|
`VSCode`
|
||||||
|
|
||||||
@@ -18,3 +19,8 @@
|
|||||||
`Bot`
|
`Bot`
|
||||||
|
|
||||||
- [ChatGPT Telegram Bot](https://github.com/altryne/chatGPT-telegram-bot) - This is a very early attempt at having chatGPT work within a telegram bot
|
- [ChatGPT Telegram Bot](https://github.com/altryne/chatGPT-telegram-bot) - This is a very early attempt at having chatGPT work within a telegram bot
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
- [commitgpt](https://github.com/RomanHotsiy/commitgpt) - Automatically generate commit messages using ChatGPT
|
||||||
|
- [ShareGPT](https://sharegpt.com/) - ShareGPT: Share your wildest ChatGPT conversations with one click.
|
||||||
|
|||||||
22
README-ZH.md
22
README-ZH.md
@@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
**最新版:**
|
**最新版:**
|
||||||
|
|
||||||
- `Mac`: [ChatGPT_0.2.1_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/ChatGPT_0.2.1_x64.dmg)
|
- `Mac`: [ChatGPT_v0.3.0_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/vv0.3.0/ChatGPT_v0.3.0_x64.dmg)
|
||||||
- `Linux`: [chat-gpt_0.2.1_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/chat-gpt_0.2.1_amd64.deb)
|
- `Linux`: [chat-gpt_v0.3.0_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/vv0.3.0/chat-gpt_v0.3.0_amd64.deb)
|
||||||
- `Windows`: [ChatGPT_0.2.1_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/ChatGPT_0.2.1_x64_en-US.msi)
|
- `Windows`: [ChatGPT_v0.3.0_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/vv0.3.0/ChatGPT_v0.3.0_x64_en-US.msi)
|
||||||
|
|
||||||
[其他版本...](https://github.com/lencx/ChatGPT/releases)
|
[其他版本...](https://github.com/lencx/ChatGPT/releases)
|
||||||
|
|
||||||
@@ -60,9 +60,12 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
- `Theme` - `Light`, `Dark` (仅支持 macOS 和 Windows)
|
- `Theme` - `Light`, `Dark` (仅支持 macOS 和 Windows)
|
||||||
- `Always On Top`: 窗口置顶
|
- `Always On Top`: 窗口置顶
|
||||||
- `Titlebar`: 是否显示 `Titlebar`,仅 macOS 支持
|
- `Titlebar`: 是否显示 `Titlebar`,仅 macOS 支持
|
||||||
- `User Agent` ([#17](https://github.com/lencx/ChatGPT/issues/17)): 自定义 `user agent` 防止网站安全检测,默认值为空。
|
|
||||||
- `Inject Script`: 用于修改网站的用户自定义脚本
|
- `Inject Script`: 用于修改网站的用户自定义脚本
|
||||||
- `Switch Origin` ([#14](https://github.com/lencx/ChatGPT/issues/14)): 切换网站源地址,默认为 `https://chat.openai.com`。需要注意的是镜像网站的 UI 需要和原网站一致,否则可能会导致某些功能不工作
|
- `Control Center`: ChatGPT 应用的控制中心,它将为应用提供无限的可能
|
||||||
|
- 设置 `Theme`,`Always on Top`,`Titlebar` 等
|
||||||
|
- `User Agent` ([#17](https://github.com/lencx/ChatGPT/issues/17)): 自定义 `user agent` 防止网站安全检测,默认值为空
|
||||||
|
- `Switch Origin` ([#14](https://github.com/lencx/ChatGPT/issues/14)): 切换网站源地址,默认为 `https://chat.openai.com`。需要注意的是镜像网站的 UI 需要和原网站一致,否则可能会导致某些功能不工作
|
||||||
|
- `Go to Config`: 打开 ChatGPT 配置目录 (`path: ~/.chatgpt/*`)
|
||||||
- `Clear Config`: 清除 ChatGPT 配置数据 (`path: ~/.chatgpt/*`), 这是危险操作,请提前备份数据
|
- `Clear Config`: 清除 ChatGPT 配置数据 (`path: ~/.chatgpt/*`), 这是危险操作,请提前备份数据
|
||||||
- `Restart ChatGPT`: 重启应用。如果注入脚本编辑完成,或者应用可卡死可以通过此菜单重新启动应用
|
- `Restart ChatGPT`: 重启应用。如果注入脚本编辑完成,或者应用可卡死可以通过此菜单重新启动应用
|
||||||
- `Awesome ChatGPT`: 一个很棒的 ChatGPT 推荐列表
|
- `Awesome ChatGPT`: 一个很棒的 ChatGPT 推荐列表
|
||||||
@@ -75,9 +78,10 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
|
|
||||||
## 👀 预览
|
## 👀 预览
|
||||||
|
|
||||||
<img width="320" src="./assets/install.png" alt="install"> <img width="320" src="./assets/chat.png" alt="chat">
|
<img width="320" src="./assets/install.png" alt="install"> <img width="320" src="./assets/control-center.png" alt="control center">
|
||||||
<img width="320" src="./assets/export.png" alt="export"> <img width="320" src="./assets/tray.png" alt="tray">
|
<img width="320" src="./assets/export.png" alt="export"> <img width="320" src="./assets/tray.png" alt="tray">
|
||||||
<img width="320" src="./assets/chat-ua.png" alt="user agent"> <img width="320" src="./assets/auto-update.png" alt="auto update">
|
<img width="320" src="./assets/tray-login.png" alt="tray login"> <img width="320" src="./assets/auto-update.png" alt="auto update">
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -95,6 +99,10 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
|
|
||||||
如果升级应用后无法打开,请尝试清除配置,它位于此目录 `~/.chatgpt/*`。
|
如果升级应用后无法打开,请尝试清除配置,它位于此目录 `~/.chatgpt/*`。
|
||||||
|
|
||||||
|
### 主窗口已经登录,但是系统托盘窗口显示未登录
|
||||||
|
|
||||||
|
可通过菜单项里的 `Restart ChatGPT` 重启应用来修复这个问题(`Menu -> Preferences -> Restart ChatGPT`)。
|
||||||
|
|
||||||
### 它是否安全?
|
### 它是否安全?
|
||||||
|
|
||||||
它是安全的,仅仅只是对 [OpenAI ChatGPT](https://chat.openai.com) 网站的包装,注入了一些额外功能(均在本地,未发起网络请求),如果存疑,可以检查源代码。
|
它是安全的,仅仅只是对 [OpenAI ChatGPT](https://chat.openai.com) 网站的包装,注入了一些额外功能(均在本地,未发起网络请求),如果存疑,可以检查源代码。
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
**Latest:**
|
**Latest:**
|
||||||
|
|
||||||
- `Mac`: [ChatGPT_0.2.1_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/ChatGPT_0.2.1_x64.dmg)
|
- `Mac`: [ChatGPT_vv0.3.0_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/vvv0.3.0/ChatGPT_vv0.3.0_x64.dmg)
|
||||||
- `Linux`: [chat-gpt_0.2.1_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/chat-gpt_0.2.1_amd64.deb)
|
- `Linux`: [chat-gpt_vv0.3.0_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/vvv0.3.0/chat-gpt_vv0.3.0_amd64.deb)
|
||||||
- `Windows`: [ChatGPT_0.2.1_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.2.1/ChatGPT_0.2.1_x64_en-US.msi)
|
- `Windows`: [ChatGPT_vv0.3.0_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/vvv0.3.0/ChatGPT_vv0.3.0_x64_en-US.msi)
|
||||||
|
|
||||||
[Other version...](https://github.com/lencx/ChatGPT/releases)
|
[Other version...](https://github.com/lencx/ChatGPT/releases)
|
||||||
|
|
||||||
@@ -60,9 +60,12 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
- `Theme` - `Light`, `Dark` (Only macOS and Windows are supported).
|
- `Theme` - `Light`, `Dark` (Only macOS and Windows are supported).
|
||||||
- `Always on Top`: The window is always on top of other windows.
|
- `Always on Top`: The window is always on top of other windows.
|
||||||
- `Titlebar`: Whether to display the titlebar, supported by macOS only.
|
- `Titlebar`: Whether to display the titlebar, supported by macOS only.
|
||||||
- `User Agent` ([#17](https://github.com/lencx/ChatGPT/issues/17)): Custom `user agent`, which may be required in some scenarios. The default value is the empty string.
|
|
||||||
- `Inject Script`: Using scripts to modify pages.
|
- `Inject Script`: Using scripts to modify pages.
|
||||||
- `Switch Origin` ([#14](https://github.com/lencx/ChatGPT/issues/14)): Switch the site source address, the default is `https://chat.openai.com`, please make sure the mirror site UI is the same as the original address. Otherwise, some functions may not be available.
|
- `Control Center`: The control center of ChatGPT application, it will give unlimited imagination to the application.
|
||||||
|
- `Theme`, `Always on Top`, `Titlebar`, ...
|
||||||
|
- `User Agent` ([#17](https://github.com/lencx/ChatGPT/issues/17)): Custom `user agent`, which may be required in some scenarios. The default value is the empty string.
|
||||||
|
- `Switch Origin` ([#14](https://github.com/lencx/ChatGPT/issues/14)): Switch the site source address, the default is `https://chat.openai.com`, please make sure the mirror site UI is the same as the original address. Otherwise, some functions may not be available.
|
||||||
|
- `Go to Config`: Open the configuration file directory (`path: ~/.chatgpt/*`).
|
||||||
- `Clear Config`: Clear the configuration file (`path: ~/.chatgpt/*`), dangerous operation, please backup the data in advance.
|
- `Clear Config`: Clear the configuration file (`path: ~/.chatgpt/*`), dangerous operation, please backup the data in advance.
|
||||||
- `Restart ChatGPT`: Restart the application, for example: the program is stuck or the injection script can take effect by restarting the application after editing.
|
- `Restart ChatGPT`: Restart the application, for example: the program is stuck or the injection script can take effect by restarting the application after editing.
|
||||||
- `Awesome ChatGPT`: Recommended Related Resources.
|
- `Awesome ChatGPT`: Recommended Related Resources.
|
||||||
@@ -81,9 +84,9 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
|
|
||||||
## 👀 Preview
|
## 👀 Preview
|
||||||
|
|
||||||
<img width="320" src="./assets/install.png" alt="install"> <img width="320" src="./assets/chat.png" alt="chat">
|
<img width="320" src="./assets/install.png" alt="install"> <img width="320" src="./assets/control-center.png" alt="control center">
|
||||||
<img width="320" src="./assets/export.png" alt="export"> <img width="320" src="./assets/tray.png" alt="tray">
|
<img width="320" src="./assets/export.png" alt="export"> <img width="320" src="./assets/tray.png" alt="tray">
|
||||||
<img width="320" src="./assets/chat-ua.png" alt="user agent"> <img width="320" src="./assets/auto-update.png" alt="auto update">
|
<img width="320" src="./assets/tray-login.png" alt="tray login"> <img width="320" src="./assets/auto-update.png" alt="auto update">
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -95,6 +98,10 @@ cask "popcorn-time", args: { "no-quarantine": true }
|
|||||||
|
|
||||||
If you cannot open the application after the upgrade, please try to clear the configuration file, which is in the `~/.chatgpt/*` directory.
|
If you cannot open the application after the upgrade, please try to clear the configuration file, which is in the `~/.chatgpt/*` directory.
|
||||||
|
|
||||||
|
### Out of sync login status between multiple windows
|
||||||
|
|
||||||
|
If you have already logged in in the main window, but the system tray window shows that you are not logged in, you can fix it by restarting the application (`Menu -> Preferences -> Restart ChatGPT`).
|
||||||
|
|
||||||
### Is it safe?
|
### Is it safe?
|
||||||
|
|
||||||
It's safe, just a wrapper for [OpenAI ChatGPT](https://chat.openai.com) website, no other data transfer exists (you can check the source code).
|
It's safe, just a wrapper for [OpenAI ChatGPT](https://chat.openai.com) website, no other data transfer exists (you can check the source code).
|
||||||
|
|||||||
@@ -1,5 +1,18 @@
|
|||||||
# UPDATE LOG
|
# UPDATE LOG
|
||||||
|
|
||||||
|
## v0.3.0
|
||||||
|
|
||||||
|
fix: can't open ChatGPT
|
||||||
|
|
||||||
|
feat: menu enhancement
|
||||||
|
- the control center of ChatGPT application
|
||||||
|
- open the configuration file directory
|
||||||
|
|
||||||
|
## v0.2.2
|
||||||
|
|
||||||
|
feat:
|
||||||
|
- menu: go to config
|
||||||
|
|
||||||
## v0.2.1
|
## v0.2.1
|
||||||
|
|
||||||
feat: menu optimization
|
feat: menu optimization
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 230 KiB After Width: | Height: | Size: 773 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 391 KiB |
BIN
assets/chat.png
BIN
assets/chat.png
Binary file not shown.
|
Before Width: | Height: | Size: 653 KiB |
BIN
assets/control-center.png
Normal file
BIN
assets/control-center.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 500 KiB |
BIN
assets/tray-login.png
Normal file
BIN
assets/tray-login.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 989 KiB |
0
dist/.gitkeep
vendored
0
dist/.gitkeep
vendored
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>ChatGPT</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
23
package.json
23
package.json
@@ -2,6 +2,8 @@
|
|||||||
"name": "chatgpt",
|
"name": "chatgpt",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev:fe": "vite",
|
||||||
|
"build:fe": "tsc && vite build",
|
||||||
"dev": "yarn tauri dev",
|
"dev": "yarn tauri dev",
|
||||||
"build": "yarn tauri build",
|
"build": "yarn tauri build",
|
||||||
"updater": "tr updater",
|
"updater": "tr updater",
|
||||||
@@ -27,8 +29,25 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/lencx/ChatGPT"
|
"url": "https://github.com/lencx/ChatGPT"
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "^1.2.0",
|
||||||
|
"antd": "^5.0.6",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.4.5"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^1.2.1",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
"@tauri-release/cli": "^0.2.3"
|
"@tauri-release/cli": "^0.2.3",
|
||||||
|
"@types/lodash": "^4.14.191",
|
||||||
|
"@types/node": "^18.7.10",
|
||||||
|
"@types/react": "^18.0.15",
|
||||||
|
"@types/react-dom": "^18.0.6",
|
||||||
|
"@vitejs/plugin-react": "^3.0.0",
|
||||||
|
"sass": "^1.56.2",
|
||||||
|
"typescript": "^4.9.4",
|
||||||
|
"vite": "^4.0.0",
|
||||||
|
"vite-tsconfig-paths": "^4.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
scripts/download.js
vendored
11
scripts/download.js
vendored
@@ -2,8 +2,8 @@ const fs = require('fs');
|
|||||||
|
|
||||||
const argv = process.argv.slice(2);
|
const argv = process.argv.slice(2);
|
||||||
|
|
||||||
async function init() {
|
async function rewrite(filename) {
|
||||||
const content = fs.readFileSync('README.md', 'utf8').split('\n');
|
const content = fs.readFileSync(filename, 'utf8').split('\n');
|
||||||
const startRe = /<!-- download start -->/;
|
const startRe = /<!-- download start -->/;
|
||||||
const endRe = /<!-- download end -->/;
|
const endRe = /<!-- download end -->/;
|
||||||
|
|
||||||
@@ -20,7 +20,12 @@ async function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync('README.md', content.join('\n'), 'utf8');
|
fs.writeFileSync(filename, content.join('\n'), 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
rewrite('README.md');
|
||||||
|
rewrite('README-ZH.md');
|
||||||
}
|
}
|
||||||
|
|
||||||
init().catch(console.error);
|
init().catch(console.error);
|
||||||
@@ -35,9 +35,8 @@ pub fn get_chat_conf() -> ChatConfJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub fn form_confirm(app: AppHandle, data: serde_json::Value) {
|
pub fn form_confirm(_app: AppHandle, data: serde_json::Value) {
|
||||||
ChatConfJson::amend(&serde_json::json!(data)).unwrap();
|
ChatConfJson::amend(&serde_json::json!(data), None).unwrap();
|
||||||
tauri::api::process::restart(&app.env());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::window,
|
|
||||||
conf::{self, ChatConfJson},
|
conf::{self, ChatConfJson},
|
||||||
utils,
|
utils,
|
||||||
};
|
};
|
||||||
@@ -26,7 +25,7 @@ pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
|
|||||||
.add_native_item(MenuItem::Quit),
|
.add_native_item(MenuItem::Quit),
|
||||||
);
|
);
|
||||||
|
|
||||||
let always_on_top = CustomMenuItem::new("always_on_top".to_string(), "Always On Top")
|
let always_on_top = CustomMenuItem::new("always_on_top".to_string(), "Always on Top")
|
||||||
.accelerator("CmdOrCtrl+T");
|
.accelerator("CmdOrCtrl+T");
|
||||||
let titlebar =
|
let titlebar =
|
||||||
CustomMenuItem::new("titlebar".to_string(), "Titlebar").accelerator("CmdOrCtrl+B");
|
CustomMenuItem::new("titlebar".to_string(), "Titlebar").accelerator("CmdOrCtrl+B");
|
||||||
@@ -67,27 +66,25 @@ pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
titlebar_menu.into(),
|
titlebar_menu.into(),
|
||||||
MenuItem::Separator.into(),
|
MenuItem::Separator.into(),
|
||||||
// fix: Checking if the site connection is secure
|
|
||||||
// @link: https://github.com/lencx/ChatGPT/issues/17
|
|
||||||
CustomMenuItem::new("user_agent".to_string(), "User Agent")
|
|
||||||
.accelerator("CmdOrCtrl+U")
|
|
||||||
.into(),
|
|
||||||
CustomMenuItem::new("switch_origin".to_string(), "Switch Origin")
|
|
||||||
.accelerator("CmdOrCtrl+O")
|
|
||||||
.into(),
|
|
||||||
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
|
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
|
||||||
.accelerator("CmdOrCtrl+J")
|
.accelerator("CmdOrCtrl+J")
|
||||||
.into(),
|
.into(),
|
||||||
|
CustomMenuItem::new("control_center".to_string(), "Control Center")
|
||||||
|
.accelerator("CmdOrCtrl+Shift+P")
|
||||||
|
.into(),
|
||||||
MenuItem::Separator.into(),
|
MenuItem::Separator.into(),
|
||||||
|
CustomMenuItem::new("go_conf".to_string(), "Go to Config")
|
||||||
|
.accelerator("CmdOrCtrl+Shift+G")
|
||||||
|
.into(),
|
||||||
CustomMenuItem::new("clear_conf".to_string(), "Clear Config")
|
CustomMenuItem::new("clear_conf".to_string(), "Clear Config")
|
||||||
.accelerator("CmdOrCtrl+D")
|
.accelerator("CmdOrCtrl+Shift+D")
|
||||||
.into(),
|
.into(),
|
||||||
CustomMenuItem::new("restart".to_string(), "Restart ChatGPT")
|
CustomMenuItem::new("restart".to_string(), "Restart ChatGPT")
|
||||||
.accelerator("CmdOrCtrl+Shift+R")
|
.accelerator("CmdOrCtrl+Shift+R")
|
||||||
.into(),
|
.into(),
|
||||||
MenuItem::Separator.into(),
|
MenuItem::Separator.into(),
|
||||||
CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
|
CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
|
||||||
.accelerator("CmdOrCtrl+Z")
|
.accelerator("CmdOrCtrl+Shift+A")
|
||||||
.into(),
|
.into(),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
@@ -162,15 +159,19 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
|
|
||||||
match menu_id {
|
match menu_id {
|
||||||
// Preferences
|
// Preferences
|
||||||
|
"control_center" => app.get_window("main").unwrap().show().unwrap(),
|
||||||
"restart" => tauri::api::process::restart(&app.env()),
|
"restart" => tauri::api::process::restart(&app.env()),
|
||||||
"inject_script" => open(&app, script_path),
|
"inject_script" => open(&app, script_path),
|
||||||
|
"go_conf" => utils::open_file(utils::chat_root()),
|
||||||
"clear_conf" => utils::clear_conf(&app),
|
"clear_conf" => utils::clear_conf(&app),
|
||||||
"switch_origin" => window::origin_window(&app),
|
|
||||||
"user_agent" => window::ua_window(&app),
|
|
||||||
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
|
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
|
||||||
"titlebar" => {
|
"titlebar" => {
|
||||||
let chat_conf = conf::ChatConfJson::get_chat_conf();
|
let chat_conf = conf::ChatConfJson::get_chat_conf();
|
||||||
ChatConfJson::amend(&serde_json::json!({ "titlebar": !chat_conf.titlebar })).unwrap();
|
ChatConfJson::amend(
|
||||||
|
&serde_json::json!({ "titlebar": !chat_conf.titlebar }),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
tauri::api::process::restart(&app.env());
|
tauri::api::process::restart(&app.env());
|
||||||
}
|
}
|
||||||
"theme_light" | "theme_dark" => {
|
"theme_light" | "theme_dark" => {
|
||||||
@@ -179,8 +180,7 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
} else {
|
} else {
|
||||||
"Light"
|
"Light"
|
||||||
};
|
};
|
||||||
ChatConfJson::amend(&serde_json::json!({ "theme": theme })).unwrap();
|
ChatConfJson::amend(&serde_json::json!({ "theme": theme }), Some(app)).unwrap();
|
||||||
tauri::api::process::restart(&app.env());
|
|
||||||
}
|
}
|
||||||
"always_on_top" => {
|
"always_on_top" => {
|
||||||
let mut always_on_top = state.always_on_top.lock().unwrap();
|
let mut always_on_top = state.always_on_top.lock().unwrap();
|
||||||
@@ -190,7 +190,11 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
.set_selected(*always_on_top)
|
.set_selected(*always_on_top)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
win.set_always_on_top(*always_on_top).unwrap();
|
win.set_always_on_top(*always_on_top).unwrap();
|
||||||
ChatConfJson::amend(&serde_json::json!({ "always_on_top": *always_on_top })).unwrap();
|
ChatConfJson::amend(
|
||||||
|
&serde_json::json!({ "always_on_top": *always_on_top }),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
// View
|
// View
|
||||||
"reload" => win.eval("window.location.reload()").unwrap(),
|
"reload" => win.eval("window.location.reload()").unwrap(),
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>
|
|||||||
.initialization_script(include_str!("../assets/jspdf.js"))
|
.initialization_script(include_str!("../assets/jspdf.js"))
|
||||||
.initialization_script(include_str!("../assets/core.js"))
|
.initialization_script(include_str!("../assets/core.js"))
|
||||||
.initialization_script(include_str!("../assets/export.js"))
|
.initialization_script(include_str!("../assets/export.js"))
|
||||||
.user_agent(&chat_conf.ua_pc)
|
.user_agent(&chat_conf.ua_window)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
@@ -37,7 +37,7 @@ pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>
|
|||||||
.initialization_script(include_str!("../assets/jspdf.js"))
|
.initialization_script(include_str!("../assets/jspdf.js"))
|
||||||
.initialization_script(include_str!("../assets/core.js"))
|
.initialization_script(include_str!("../assets/core.js"))
|
||||||
.initialization_script(include_str!("../assets/export.js"))
|
.initialization_script(include_str!("../assets/export.js"))
|
||||||
.user_agent(&chat_conf.ua_pc)
|
.user_agent(&chat_conf.ua_window)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -17,37 +17,9 @@ pub fn mini_window(handle: &tauri::AppHandle) {
|
|||||||
.initialization_script(include_str!("../assets/jspdf.js"))
|
.initialization_script(include_str!("../assets/jspdf.js"))
|
||||||
.initialization_script(include_str!("../assets/core.js"))
|
.initialization_script(include_str!("../assets/core.js"))
|
||||||
.initialization_script(include_str!("../assets/export.js"))
|
.initialization_script(include_str!("../assets/export.js"))
|
||||||
.user_agent(&chat_conf.ua_phone)
|
.user_agent(&chat_conf.ua_tray)
|
||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.hide()
|
.hide()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn origin_window(handle: &tauri::AppHandle) {
|
|
||||||
let chat_conf = conf::ChatConfJson::get_chat_conf();
|
|
||||||
WindowBuilder::new(handle, "origin", WindowUrl::App(chat_conf.origin.into()))
|
|
||||||
.resizable(false)
|
|
||||||
.fullscreen(false)
|
|
||||||
.inner_size(400.0, 300.0)
|
|
||||||
.always_on_top(true)
|
|
||||||
.decorations(false)
|
|
||||||
.initialization_script(include_str!("../assets/core.js"))
|
|
||||||
.initialization_script(include_str!("../assets/origin.js"))
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ua_window(handle: &tauri::AppHandle) {
|
|
||||||
let chat_conf = conf::ChatConfJson::get_chat_conf();
|
|
||||||
WindowBuilder::new(handle, "ua", WindowUrl::App(chat_conf.origin.into()))
|
|
||||||
.resizable(false)
|
|
||||||
.fullscreen(false)
|
|
||||||
.inner_size(540.0, 480.0)
|
|
||||||
.always_on_top(true)
|
|
||||||
.decorations(false)
|
|
||||||
.initialization_script(include_str!("../assets/core.js"))
|
|
||||||
.initialization_script(include_str!("../assets/ua.js"))
|
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|||||||
1
src-tauri/src/assets/core.js
vendored
1
src-tauri/src/assets/core.js
vendored
@@ -1,4 +1,5 @@
|
|||||||
// *** Core Script - IPC ***
|
// *** Core Script - IPC ***
|
||||||
|
|
||||||
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();
|
||||||
|
|||||||
20
src-tauri/src/assets/export.js
vendored
20
src-tauri/src/assets/export.js
vendored
@@ -1,5 +1,5 @@
|
|||||||
// *** Core Script - Export ***
|
// *** Core Script - Export ***
|
||||||
// @ref: https://github.com/liady/ChatGPT-pdf/blob/main/src/content_script.js
|
// @ref: https://github.com/liady/ChatGPT-pdf
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const chatConf = await invoke('get_chat_conf') || {};
|
const chatConf = await invoke('get_chat_conf') || {};
|
||||||
@@ -78,22 +78,9 @@ function downloadThread({ as = Format.PNG } = {}) {
|
|||||||
const pixelRatio = window.devicePixelRatio;
|
const pixelRatio = window.devicePixelRatio;
|
||||||
const minRatio = as === Format.PDF ? 2 : 2.5;
|
const minRatio = as === Format.PDF ? 2 : 2.5;
|
||||||
window.devicePixelRatio = Math.max(pixelRatio, minRatio);
|
window.devicePixelRatio = Math.max(pixelRatio, minRatio);
|
||||||
|
|
||||||
html2canvas(elements.thread, {
|
html2canvas(elements.thread, {
|
||||||
letterRendering: true,
|
letterRendering: true,
|
||||||
onclone: function (cloneDoc) {
|
|
||||||
//Make small fix of position to all the text containers
|
|
||||||
let listOfTexts = cloneDoc.getElementsByClassName("min-h-[20px]");
|
|
||||||
Array.from(listOfTexts).forEach((text) => {
|
|
||||||
text.style.position = "relative";
|
|
||||||
text.style.top = "-8px";
|
|
||||||
});
|
|
||||||
|
|
||||||
//Delete copy button from code blocks
|
|
||||||
let listOfCopyBtns = cloneDoc.querySelectorAll("button.flex");
|
|
||||||
Array.from(listOfCopyBtns).forEach(
|
|
||||||
(btn) => (btn.style.visibility = "hidden")
|
|
||||||
);
|
|
||||||
},
|
|
||||||
}).then(async function (canvas) {
|
}).then(async function (canvas) {
|
||||||
elements.restoreLocation();
|
elements.restoreLocation();
|
||||||
window.devicePixelRatio = pixelRatio;
|
window.devicePixelRatio = pixelRatio;
|
||||||
@@ -166,6 +153,8 @@ class Elements {
|
|||||||
img.setAttribute("srcset_old", srcset);
|
img.setAttribute("srcset_old", srcset);
|
||||||
img.setAttribute("srcset", "");
|
img.setAttribute("srcset", "");
|
||||||
});
|
});
|
||||||
|
//Fix to the text shifting down when generating the canvas
|
||||||
|
document.body.style.lineHeight = "0.5";
|
||||||
}
|
}
|
||||||
restoreLocation() {
|
restoreLocation() {
|
||||||
this.hiddens.forEach((el) => {
|
this.hiddens.forEach((el) => {
|
||||||
@@ -182,6 +171,7 @@ class Elements {
|
|||||||
img.setAttribute("srcset", srcset);
|
img.setAttribute("srcset", srcset);
|
||||||
img.setAttribute("srcset_old", "");
|
img.setAttribute("srcset_old", "");
|
||||||
});
|
});
|
||||||
|
document.body.style.lineHeight = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
77
src-tauri/src/assets/origin.js
vendored
77
src-tauri/src/assets/origin.js
vendored
@@ -1,77 +0,0 @@
|
|||||||
function init() {
|
|
||||||
document.body.innerHTML = `<style>
|
|
||||||
body {
|
|
||||||
height: 100vh;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-family: Söhne,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
input {
|
|
||||||
all: unset;
|
|
||||||
width: 280px;
|
|
||||||
height: 30px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 0 5px;
|
|
||||||
border: solid 2px #d8d8d8;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 5px !important;
|
|
||||||
color: #4a4a4a;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
all: unset;
|
|
||||||
height: 30px;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 0 10px;
|
|
||||||
line-height: 30px;
|
|
||||||
margin: 0 5px;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#cancel {
|
|
||||||
background-color: #999;
|
|
||||||
}
|
|
||||||
#confirm {
|
|
||||||
background-color: #10a37f;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<h3>Switch Origin</h3>
|
|
||||||
<input id="input" type="text" autocapitalize="off" autocomplete="off" spellcheck="false" autofocus placeholder="https://chat.openai.com" />
|
|
||||||
<div class="btns">
|
|
||||||
<button id="cancel">Cancel</button>
|
|
||||||
<button id="confirm">Confirm</button>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
const srcipt = document.createElement('script');
|
|
||||||
srcipt.innerHTML = `const input = document.getElementById('input');
|
|
||||||
const cancelBtn = document.getElementById('cancel');
|
|
||||||
const confirmBtn = document.getElementById('confirm');
|
|
||||||
cancelBtn.addEventListener('click', () => {
|
|
||||||
window.invoke('form_cancel', { label: 'origin', title: 'Switch Origin', msg: 'Are you sure you want to cancel editing?' });
|
|
||||||
})
|
|
||||||
confirmBtn.addEventListener('click', () => {
|
|
||||||
if (/^https?:\\/\\//.test(input.value)) {
|
|
||||||
window.invoke('form_confirm', { data: { origin: input.value } });
|
|
||||||
} else {
|
|
||||||
window.invoke('form_msg', { label: 'origin', title: 'Switch Origin', msg: 'Invalid URL!' });
|
|
||||||
}
|
|
||||||
})`;
|
|
||||||
document.head.appendChild(srcipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// run init
|
|
||||||
if (
|
|
||||||
document.readyState === "complete" ||
|
|
||||||
document.readyState === "interactive"
|
|
||||||
) {
|
|
||||||
init();
|
|
||||||
} else {
|
|
||||||
document.addEventListener("DOMContentLoaded", init);
|
|
||||||
}
|
|
||||||
89
src-tauri/src/assets/ua.js
vendored
89
src-tauri/src/assets/ua.js
vendored
@@ -1,89 +0,0 @@
|
|||||||
function init() {
|
|
||||||
document.body.innerHTML = `<style>
|
|
||||||
body {
|
|
||||||
height: 100vh;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-family: Söhne,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,Helvetica Neue,Arial,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
textarea {
|
|
||||||
all: unset;
|
|
||||||
width: 300px;
|
|
||||||
height: 60px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 10px;
|
|
||||||
border: solid 2px #d8d8d8;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 5px !important;
|
|
||||||
color: #4a4a4a;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
all: unset;
|
|
||||||
height: 30px;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 0 10px;
|
|
||||||
line-height: 30px;
|
|
||||||
margin: 0 5px;
|
|
||||||
color: #fff;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
#cancel {
|
|
||||||
background-color: #999;
|
|
||||||
}
|
|
||||||
#confirm {
|
|
||||||
background-color: #10a37f;
|
|
||||||
}
|
|
||||||
.item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
width: 120px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<h3>User Agent</h3>
|
|
||||||
<div class="item">
|
|
||||||
<label>Main Window (PC)</label>
|
|
||||||
<textarea id="ua_pc" type="text" autocapitalize="off" autocomplete="off" spellcheck="false" autofocus placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ..."></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<label>Tray Window (Phone)</label>
|
|
||||||
<textarea id="ua_phone" type="text" autocapitalize="off" autocomplete="off" spellcheck="false" autofocus placeholder="Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS ..."></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="btns">
|
|
||||||
<button id="cancel">Cancel</button>
|
|
||||||
<button id="confirm">Confirm</button>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
const srcipt = document.createElement('script');
|
|
||||||
srcipt.innerHTML = `const ua_pc = document.getElementById('ua_pc');
|
|
||||||
const ua_phone = document.getElementById('ua_phone');
|
|
||||||
const cancelBtn = document.getElementById('cancel');
|
|
||||||
const confirmBtn = document.getElementById('confirm');
|
|
||||||
cancelBtn.addEventListener('click', () => {
|
|
||||||
window.invoke('form_cancel', { label: 'ua', title: 'User Agent', msg: 'Are you sure you want to cancel editing?' });
|
|
||||||
})
|
|
||||||
confirmBtn.addEventListener('click', () => {
|
|
||||||
window.invoke('form_confirm', { data: { ua_pc: ua_pc.value, ua_phone: ua_phone.value } });
|
|
||||||
})`;
|
|
||||||
document.head.appendChild(srcipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// run init
|
|
||||||
if (
|
|
||||||
document.readyState === "complete" ||
|
|
||||||
document.readyState === "interactive"
|
|
||||||
) {
|
|
||||||
init();
|
|
||||||
} else {
|
|
||||||
document.addEventListener("DOMContentLoaded", init);
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ use crate::utils::{chat_root, create_file, exists};
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{collections::BTreeMap, fs, path::PathBuf, sync::Mutex};
|
use std::{collections::BTreeMap, fs, path::PathBuf, sync::Mutex};
|
||||||
use tauri::Theme;
|
use tauri::{Manager, Theme};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use tauri::TitleBarStyle;
|
use tauri::TitleBarStyle;
|
||||||
@@ -19,8 +19,8 @@ pub const DEFAULT_CHAT_CONF: &str = r#"{
|
|||||||
"titlebar": true,
|
"titlebar": true,
|
||||||
"default_origin": "https://chat.openai.com",
|
"default_origin": "https://chat.openai.com",
|
||||||
"origin": "https://chat.openai.com",
|
"origin": "https://chat.openai.com",
|
||||||
"ua_pc": "",
|
"ua_window": "",
|
||||||
"ua_phone": ""
|
"ua_tray": ""
|
||||||
}"#;
|
}"#;
|
||||||
pub const DEFAULT_CHAT_CONF_MAC: &str = r#"{
|
pub const DEFAULT_CHAT_CONF_MAC: &str = r#"{
|
||||||
"always_on_top": false,
|
"always_on_top": false,
|
||||||
@@ -28,8 +28,8 @@ pub const DEFAULT_CHAT_CONF_MAC: &str = r#"{
|
|||||||
"titlebar": false,
|
"titlebar": false,
|
||||||
"default_origin": "https://chat.openai.com",
|
"default_origin": "https://chat.openai.com",
|
||||||
"origin": "https://chat.openai.com",
|
"origin": "https://chat.openai.com",
|
||||||
"ua_pc": "",
|
"ua_window": "",
|
||||||
"ua_phone": ""
|
"ua_tray": ""
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
pub struct ChatState {
|
pub struct ChatState {
|
||||||
@@ -51,8 +51,8 @@ pub struct ChatConfJson {
|
|||||||
pub theme: String,
|
pub theme: String,
|
||||||
pub default_origin: String,
|
pub default_origin: String,
|
||||||
pub origin: String,
|
pub origin: String,
|
||||||
pub ua_pc: String,
|
pub ua_window: String,
|
||||||
pub ua_phone: String,
|
pub ua_tray: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChatConfJson {
|
impl ChatConfJson {
|
||||||
@@ -60,15 +60,30 @@ impl ChatConfJson {
|
|||||||
/// path: ~/.chatgpt/chat.conf.json
|
/// path: ~/.chatgpt/chat.conf.json
|
||||||
pub fn init() -> PathBuf {
|
pub fn init() -> PathBuf {
|
||||||
let conf_file = ChatConfJson::conf_path();
|
let conf_file = ChatConfJson::conf_path();
|
||||||
|
let content = if cfg!(target_os = "macos") {
|
||||||
|
DEFAULT_CHAT_CONF_MAC
|
||||||
|
} else {
|
||||||
|
DEFAULT_CHAT_CONF
|
||||||
|
};
|
||||||
|
|
||||||
if !exists(&conf_file) {
|
if !exists(&conf_file) {
|
||||||
create_file(&conf_file).unwrap();
|
create_file(&conf_file).unwrap();
|
||||||
|
fs::write(&conf_file, content).unwrap();
|
||||||
#[cfg(target_os = "macos")]
|
return conf_file;
|
||||||
fs::write(&conf_file, DEFAULT_CHAT_CONF_MAC).unwrap();
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "macos"))]
|
|
||||||
fs::write(&conf_file, DEFAULT_CHAT_CONF).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let conf_file = ChatConfJson::conf_path();
|
||||||
|
let file_content = fs::read_to_string(&conf_file).unwrap();
|
||||||
|
match serde_json::from_str(&file_content) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(err) => {
|
||||||
|
if err.to_string() == "invalid type: map, expected unit at line 1 column 0" {
|
||||||
|
return conf_file;
|
||||||
|
}
|
||||||
|
fs::write(&conf_file, content).unwrap();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
conf_file
|
conf_file
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,15 +92,31 @@ impl ChatConfJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_chat_conf() -> Self {
|
pub fn get_chat_conf() -> Self {
|
||||||
let config_file = fs::read_to_string(ChatConfJson::conf_path())
|
let conf_file = ChatConfJson::conf_path();
|
||||||
.unwrap_or_else(|_| DEFAULT_CHAT_CONF.to_string());
|
let file_content = fs::read_to_string(&conf_file).unwrap();
|
||||||
let config: Value =
|
let content = if cfg!(target_os = "macos") {
|
||||||
serde_json::from_str(&config_file).expect("failed to parse chat.conf.json");
|
DEFAULT_CHAT_CONF_MAC
|
||||||
serde_json::from_value(config).unwrap_or_else(|_| ChatConfJson::chat_conf_default())
|
} else {
|
||||||
|
DEFAULT_CHAT_CONF
|
||||||
|
};
|
||||||
|
|
||||||
|
match serde_json::from_value(match serde_json::from_str(&file_content) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
fs::write(&conf_file, content).unwrap();
|
||||||
|
serde_json::from_str(content).unwrap()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => {
|
||||||
|
fs::write(&conf_file, content).unwrap();
|
||||||
|
serde_json::from_value(serde_json::from_str(content).unwrap()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://users.rust-lang.org/t/updating-object-fields-given-dynamic-json/39049/3
|
// https://users.rust-lang.org/t/updating-object-fields-given-dynamic-json/39049/3
|
||||||
pub fn amend(new_rules: &Value) -> Result<()> {
|
pub fn amend(new_rules: &Value, app: Option<tauri::AppHandle>) -> Result<()> {
|
||||||
let config = ChatConfJson::get_chat_conf();
|
let config = ChatConfJson::get_chat_conf();
|
||||||
let config: Value = serde_json::to_value(&config)?;
|
let config: Value = serde_json::to_value(&config)?;
|
||||||
let mut config: BTreeMap<String, Value> = serde_json::from_value(config)?;
|
let mut config: BTreeMap<String, Value> = serde_json::from_value(config)?;
|
||||||
@@ -99,6 +130,20 @@ impl ChatConfJson {
|
|||||||
ChatConfJson::conf_path(),
|
ChatConfJson::conf_path(),
|
||||||
serde_json::to_string_pretty(&config)?,
|
serde_json::to_string_pretty(&config)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
if let Some(handle) = app {
|
||||||
|
tauri::api::process::restart(&handle.env());
|
||||||
|
// tauri::api::dialog::ask(
|
||||||
|
// handle.get_window("core").as_ref(),
|
||||||
|
// "ChatGPT Restart",
|
||||||
|
// "Whether to restart immediately?",
|
||||||
|
// move |is_restart| {
|
||||||
|
// if is_restart {
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +165,4 @@ impl ChatConfJson {
|
|||||||
TitleBarStyle::Overlay
|
TitleBarStyle::Overlay
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chat_conf_default() -> Self {
|
|
||||||
serde_json::from_value(serde_json::json!(DEFAULT_CHAT_CONF)).unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,15 @@ fn main() {
|
|||||||
.on_window_event(|event| {
|
.on_window_event(|event| {
|
||||||
// https://github.com/tauri-apps/tauri/discussions/2684
|
// https://github.com/tauri-apps/tauri/discussions/2684
|
||||||
if let tauri::WindowEvent::CloseRequested { api, .. } = event.event() {
|
if let tauri::WindowEvent::CloseRequested { api, .. } = event.event() {
|
||||||
// TODO: https://github.com/tauri-apps/tauri/issues/3084
|
let win = event.window();
|
||||||
// event.window().hide().unwrap();
|
if win.label() == "main" {
|
||||||
// https://github.com/tauri-apps/tao/pull/517
|
win.hide().unwrap();
|
||||||
event.window().minimize().unwrap();
|
} else {
|
||||||
|
// TODO: https://github.com/tauri-apps/tauri/issues/3084
|
||||||
|
// event.window().hide().unwrap();
|
||||||
|
// https://github.com/tauri-apps/tao/pull/517
|
||||||
|
event.window().minimize().unwrap();
|
||||||
|
}
|
||||||
api.prevent_close();
|
api.prevent_close();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "",
|
"beforeDevCommand": "npm run dev:fe",
|
||||||
"beforeBuildCommand": "",
|
"beforeBuildCommand": "npm run build:fe",
|
||||||
"devPath": "../dist",
|
"devPath": "http://localhost:1420",
|
||||||
"distDir": "../dist"
|
"distDir": "../dist"
|
||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "ChatGPT",
|
"productName": "ChatGPT",
|
||||||
"version": "0.2.1"
|
"version": "0.3.0"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
@@ -63,6 +63,16 @@
|
|||||||
"https://lencx.github.io/ChatGPT/install.json"
|
"https://lencx.github.io/ChatGPT/install.json"
|
||||||
],
|
],
|
||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEIxMjY4OUI5MTVFNjBEMDUKUldRRkRlWVZ1WWttc1NGWEE0RFNSb0RqdnhsekRJZTkwK2hVLzhBZTZnaHExSEZ1ZEdzWkpXTHkK"
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEIxMjY4OUI5MTVFNjBEMDUKUldRRkRlWVZ1WWttc1NGWEE0RFNSb0RqdnhsekRJZTkwK2hVLzhBZTZnaHExSEZ1ZEdzWkpXTHkK"
|
||||||
}
|
},
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"label": "main",
|
||||||
|
"url": "index.html",
|
||||||
|
"title": "ChatGPT",
|
||||||
|
"visible": false,
|
||||||
|
"width": 800,
|
||||||
|
"height": 600
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
24
src/layout/index.scss
vendored
Normal file
24
src/layout/index.scss
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.chat-logo {
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-menu {
|
||||||
|
.ant-menu-item {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-layout-footer {
|
||||||
|
color: #666 !important;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
36
src/layout/index.tsx
vendored
Normal file
36
src/layout/index.tsx
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { FC, useState } from 'react';
|
||||||
|
import { Layout, Menu } from 'antd';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import Routes, { menuItems } from '@/routes';
|
||||||
|
|
||||||
|
import './index.scss';
|
||||||
|
|
||||||
|
const { Content, Footer, Sider } = Layout;
|
||||||
|
|
||||||
|
interface ChatLayoutProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChatLayout: FC<ChatLayoutProps> = ({ children }) => {
|
||||||
|
const [collapsed, setCollapsed] = useState(false);
|
||||||
|
const go = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout style={{ minHeight: '100vh' }}>
|
||||||
|
<Sider theme="light" collapsible collapsed={collapsed} onCollapse={(value) => setCollapsed(value)}>
|
||||||
|
<div className="chat-logo"><img src="/logo.png" /></div>
|
||||||
|
<Menu defaultSelectedKeys={['/']} mode="vertical" items={menuItems} onClick={(i) => go(i.key)} />
|
||||||
|
</Sider>
|
||||||
|
<Layout className="chat-layout">
|
||||||
|
<Content className="chat-container">
|
||||||
|
<Routes />
|
||||||
|
</Content>
|
||||||
|
<Footer style={{ textAlign: 'center' }}>
|
||||||
|
<a href="https://github.com/lencx/chatgpt" target="_blank">ChatGPT Desktop Application</a> ©2022 Created by lencx</Footer>
|
||||||
|
</Layout>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ChatLayout;
|
||||||
20
src/main.scss
vendored
Normal file
20
src/main.scss
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
:root {
|
||||||
|
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color: #2a2a2a;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
16
src/main.tsx
vendored
Normal file
16
src/main.tsx
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { StrictMode, Suspense } from 'react';
|
||||||
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
|
import Layout from '@/layout';
|
||||||
|
import './main.scss';
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
|
<StrictMode>
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<BrowserRouter>
|
||||||
|
<Layout/>
|
||||||
|
</BrowserRouter>
|
||||||
|
</Suspense>
|
||||||
|
</StrictMode>
|
||||||
|
);
|
||||||
44
src/routes.tsx
vendored
Normal file
44
src/routes.tsx
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { useRoutes } from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
DesktopOutlined,
|
||||||
|
BulbOutlined
|
||||||
|
} from '@ant-design/icons';
|
||||||
|
import type { RouteObject } from 'react-router-dom';
|
||||||
|
import type { MenuProps } from 'antd';
|
||||||
|
|
||||||
|
import General from '@view/General';
|
||||||
|
import ChatGPTPrompts from '@view/ChatGPTPrompts';
|
||||||
|
|
||||||
|
export type ChatRouteObject = {
|
||||||
|
label: string;
|
||||||
|
icon?: React.ReactNode,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const routes: Array<RouteObject & { meta: ChatRouteObject }> = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
element: <General />,
|
||||||
|
meta: {
|
||||||
|
label: 'General',
|
||||||
|
icon: <DesktopOutlined />,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/chatgpt-prompts',
|
||||||
|
element: <ChatGPTPrompts />,
|
||||||
|
meta: {
|
||||||
|
label: 'ChatGPT Prompts',
|
||||||
|
icon: <BulbOutlined />,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
type MenuItem = Required<MenuProps>['items'][number];
|
||||||
|
export const menuItems: MenuItem[] = routes.map(i => ({
|
||||||
|
...i.meta,
|
||||||
|
key: i.path || '',
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return useRoutes(routes);
|
||||||
|
};
|
||||||
7
src/view/ChatGPTPrompts.tsx
vendored
Normal file
7
src/view/ChatGPTPrompts.tsx
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export default function Dashboard() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
TODO: ChatGPT Prompts
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
102
src/view/General.tsx
vendored
Normal file
102
src/view/General.tsx
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { Form, Radio, Switch, Input, Button, Space, message, Tooltip } from 'antd';
|
||||||
|
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||||
|
import { invoke } from '@tauri-apps/api';
|
||||||
|
import { platform } from '@tauri-apps/api/os';
|
||||||
|
import { ask } from '@tauri-apps/api/dialog';
|
||||||
|
import { relaunch } from '@tauri-apps/api/process';
|
||||||
|
import { clone, omit, isEqual } from 'lodash';
|
||||||
|
|
||||||
|
const OriginLabel = ({ url }: { url: string }) => {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
Switch Origin <Tooltip title={`Default: ${url}`}><QuestionCircleOutlined /></Tooltip>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const disableAuto = {
|
||||||
|
autoCapitalize: 'off',
|
||||||
|
autoComplete: 'off',
|
||||||
|
spellCheck: false
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function General() {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [platformInfo, setPlatform] = useState<string>('');
|
||||||
|
const [chatConf, setChatConf] = useState<any>(null);
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
setPlatform(await platform());
|
||||||
|
const chatData = await invoke('get_chat_conf');
|
||||||
|
setChatConf(chatData);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
init();
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.setFieldsValue(clone(chatConf));
|
||||||
|
}, [chatConf])
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
form.setFieldsValue(chatConf);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFinish = async (values: any) => {
|
||||||
|
if (!isEqual(omit(chatConf, ['default_origin']), values)) {
|
||||||
|
await invoke('form_confirm', { data: values, label: 'main' });
|
||||||
|
const isOk = await ask(`Configuration saved successfully, whether to restart?`, {
|
||||||
|
title: 'ChatGPT Preferences'
|
||||||
|
});
|
||||||
|
if (isOk) {
|
||||||
|
relaunch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.success('Configuration saved successfully');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
style={{ maxWidth: 500 }}
|
||||||
|
onFinish={onFinish}
|
||||||
|
labelCol={{ span: 8 }}
|
||||||
|
wrapperCol={{ span: 15, offset: 1 }}
|
||||||
|
>
|
||||||
|
<Form.Item label="Theme" name="theme">
|
||||||
|
<Radio.Group>
|
||||||
|
<Radio value="Light">Light</Radio>
|
||||||
|
<Radio value="Dark">Dark</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="Always on Top" name="always_on_top" valuePropName="checked">
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
{platformInfo === 'darwin' && (
|
||||||
|
<Form.Item label="Titlebar" name="titlebar" valuePropName="checked">
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
<Form.Item label={<OriginLabel url={chatConf?.default_origin} />} name="origin">
|
||||||
|
<Input placeholder="https://chat.openai.com" {...disableAuto} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="User Agent (Window)" name="ua_window">
|
||||||
|
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...disableAuto} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="User Agent (SystemTray)" name="ua_tray">
|
||||||
|
<Input.TextArea autoSize={{ minRows: 4, maxRows: 4 }} {...disableAuto} placeholder="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item>
|
||||||
|
<Space size={20}>
|
||||||
|
<Button onClick={onCancel}>Cancel</Button>
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
Submit
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
}
|
||||||
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"],
|
||||||
|
"@view/*": ["src/view/*"],
|
||||||
|
"@comps/*": ["src/components/*"],
|
||||||
|
"@layout/*": ["src/layout/*"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
9
tsconfig.node.json
Normal file
9
tsconfig.node.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
28
vite.config.ts
Normal file
28
vite.config.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { defineConfig } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import tsconfigPaths from "vite-tsconfig-paths";
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [tsconfigPaths(), react()],
|
||||||
|
|
||||||
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
|
// prevent vite from obscuring rust errors
|
||||||
|
clearScreen: false,
|
||||||
|
// tauri expects a fixed port, fail if that port is not available
|
||||||
|
server: {
|
||||||
|
port: 1420,
|
||||||
|
strictPort: true,
|
||||||
|
},
|
||||||
|
// to make use of `TAURI_DEBUG` and other env variables
|
||||||
|
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
||||||
|
envPrefix: ["VITE_", "TAURI_"],
|
||||||
|
build: {
|
||||||
|
// Tauri supports es2021
|
||||||
|
target: ["es2021", "chrome100", "safari13"],
|
||||||
|
// don't minify for debug builds
|
||||||
|
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
|
||||||
|
// produce sourcemaps for debug builds
|
||||||
|
sourcemap: !!process.env.TAURI_DEBUG,
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user