Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3402e35177 | ||
|
|
46ac5df90a | ||
|
|
76755efa2d | ||
|
|
1b47208d08 | ||
|
|
4438352acc | ||
|
|
fec14cd6a4 | ||
|
|
50e46f4064 | ||
|
|
dd51ffbf1d | ||
|
|
7a682d0177 | ||
|
|
4239775127 | ||
|
|
89cea44f8b | ||
|
|
ee4b14daf1 | ||
|
|
08ea541130 |
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 && yarn build
|
run: yarn
|
||||||
|
|
||||||
- uses: tauri-apps/tauri-action@v0.3
|
- uses: tauri-apps/tauri-action@v0.3
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -5,17 +5,22 @@
|
|||||||
|
|
||||||
> ChatGPT Desktop Application
|
> ChatGPT Desktop Application
|
||||||
|
|
||||||
|
[🚀 Download ChatGPT](https://github.com/lencx/ChatGPT/releases)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- multi-platform: `macOS` `Linux` `Windows`
|
- multi-platform: `macOS` `Linux` `Windows`
|
||||||
- inject script
|
- inject script
|
||||||
- auto updater
|
- auto updater
|
||||||
- hotkey
|
- app menu
|
||||||
|
- system tray
|
||||||
|
- shortcut
|
||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
|
|
||||||
<img width="600" src="./assets/install.png" alt="install">
|
<img width="600" src="./assets/install.png" alt="install">
|
||||||
<img width="600" src="./assets/chat.png" alt="chat">
|
<img width="600" src="./assets/chat.png" alt="chat">
|
||||||
|
<img width="600" src="./assets/auto-update.png" alt="auto update">
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
# UPDATE LOG
|
# UPDATE LOG
|
||||||
|
|
||||||
|
## v0.1.5
|
||||||
|
|
||||||
|
fix: mac can't use shortcut keys
|
||||||
|
|
||||||
|
## v0.1.4
|
||||||
|
|
||||||
|
feat:
|
||||||
|
- beautify icons
|
||||||
|
- add system tray menu
|
||||||
|
|
||||||
|
## v0.1.3
|
||||||
|
|
||||||
|
fix: only mac supports `TitleBarStyle`
|
||||||
|
|
||||||
|
## v0.1.2
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
|
## v0.1.1
|
||||||
|
|
||||||
|
initialization
|
||||||
|
|
||||||
## v0.1.0
|
## v0.1.0
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|||||||
BIN
assets/auto-update.png
Normal file
|
After Width: | Height: | Size: 230 KiB |
BIN
assets/chat.png
|
Before Width: | Height: | Size: 754 KiB After Width: | Height: | Size: 726 KiB |
|
Before Width: | Height: | Size: 218 KiB After Width: | Height: | Size: 192 KiB |
BIN
logo.png
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 22 KiB |
@@ -26,3 +26,10 @@ default = [ "custom-protocol" ]
|
|||||||
# this feature is used used for production builds where `devPath` points to the filesystem
|
# this feature is used used for production builds where `devPath` points to the filesystem
|
||||||
# DO NOT remove this
|
# DO NOT remove this
|
||||||
custom-protocol = [ "tauri/custom-protocol" ]
|
custom-protocol = [ "tauri/custom-protocol" ]
|
||||||
|
|
||||||
|
# fix: mac v1.2.0 can not copy/paste
|
||||||
|
# https://github.com/tauri-apps/tauri/issues/5669
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
|
opt-level = "z"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 104 KiB |
@@ -1,7 +1,8 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
use tauri::{
|
use tauri::{
|
||||||
utils::assets::EmbeddedAssets, AboutMetadata, AppHandle, Context, CustomMenuItem, Manager,
|
utils::assets::EmbeddedAssets, AboutMetadata, AppHandle, Context, CustomMenuItem, Manager,
|
||||||
Menu, MenuItem, Submenu, SystemTrayEvent, WindowMenuEvent,
|
Menu, MenuItem, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem,
|
||||||
|
WindowMenuEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Menu
|
// --- Menu
|
||||||
@@ -82,56 +83,35 @@ pub fn init(context: &Context<EmbeddedAssets>) -> 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 issues_url = "https://github.com/lencx/ChatGPT/issues".to_string();
|
||||||
|
|
||||||
match event.menu_item_id() {
|
match event.menu_item_id() {
|
||||||
// App
|
// App
|
||||||
"inject_script" => {
|
"inject_script" => inject_script(&app, script_path),
|
||||||
tauri::api::shell::open(
|
|
||||||
&app.shell_scope(),
|
|
||||||
utils::script_path().to_string_lossy(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
// View
|
// View
|
||||||
"go_back" => {
|
"reload" => win.eval("window.location.reload()").unwrap(),
|
||||||
win.eval("window.history.go(-1)").unwrap();
|
"go_back" => win.eval("window.history.go(-1)").unwrap(),
|
||||||
}
|
"go_forward" => win.eval("window.history.go(1)").unwrap(),
|
||||||
"go_forward" => {
|
"scroll_top" => win
|
||||||
win.eval("window.history.go(1)").unwrap();
|
.eval(
|
||||||
}
|
|
||||||
"scroll_top" => {
|
|
||||||
win.eval(
|
|
||||||
r#"window.scroll({
|
r#"window.scroll({
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
behavior: "smooth"
|
behavior: "smooth"
|
||||||
})"#,
|
})"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
}
|
"scroll_bottom" => win
|
||||||
"scroll_bottom" => {
|
.eval(
|
||||||
win.eval(
|
|
||||||
r#"window.scroll({
|
r#"window.scroll({
|
||||||
top: document.body.scrollHeight,
|
top: document.body.scrollHeight,
|
||||||
left: 0,
|
left: 0,
|
||||||
behavior: "smooth",
|
behavior: "smooth"})"#,
|
||||||
})"#,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap(),
|
||||||
}
|
|
||||||
"reload" => {
|
|
||||||
win.eval("window.location.reload()").unwrap();
|
|
||||||
}
|
|
||||||
// Help
|
// Help
|
||||||
"report_bug" => {
|
"report_bug" => inject_script(&app, issues_url),
|
||||||
tauri::api::shell::open(
|
|
||||||
&app.shell_scope(),
|
|
||||||
"https://github.com/lencx/ChatGPT/issues",
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
"dev_tools" => {
|
"dev_tools" => {
|
||||||
win.open_devtools();
|
win.open_devtools();
|
||||||
win.close_devtools();
|
win.close_devtools();
|
||||||
@@ -140,20 +120,37 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- SystemTray Menu
|
||||||
|
pub fn tray_menu() -> SystemTray {
|
||||||
|
SystemTray::new().with_menu(
|
||||||
|
SystemTrayMenu::new()
|
||||||
|
.add_item(CustomMenuItem::new("show".to_string(), "Show ChatGPT"))
|
||||||
|
.add_item(CustomMenuItem::new("hide".to_string(), "Hide ChatGPT"))
|
||||||
|
.add_item(CustomMenuItem::new(
|
||||||
|
"inject_script".to_string(),
|
||||||
|
"Inject Script",
|
||||||
|
))
|
||||||
|
.add_native_item(SystemTrayMenuItem::Separator)
|
||||||
|
.add_item(CustomMenuItem::new("quit".to_string(), "Quit ChatGPT")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// --- SystemTray Event
|
// --- SystemTray Event
|
||||||
pub fn tray_handler(app: &AppHandle, event: SystemTrayEvent) {
|
pub fn tray_handler(app: &AppHandle, event: SystemTrayEvent) {
|
||||||
if let SystemTrayEvent::LeftClick {
|
let script_path = utils::script_path().to_string_lossy().to_string();
|
||||||
position: _,
|
let win = app.get_window("core").unwrap();
|
||||||
size: _,
|
|
||||||
..
|
if let SystemTrayEvent::MenuItemClick { id, .. } = event {
|
||||||
} = event
|
match id.as_str() {
|
||||||
{
|
"quit" => std::process::exit(0),
|
||||||
let win = app.get_window("core").unwrap();
|
"show" => win.show().unwrap(),
|
||||||
if win.is_visible().unwrap() {
|
"hide" => win.hide().unwrap(),
|
||||||
win.hide().unwrap();
|
"inject_script" => inject_script(app, script_path),
|
||||||
} else {
|
_ => (),
|
||||||
win.show().unwrap();
|
|
||||||
win.set_focus().unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inject_script(app: &AppHandle, path: String) {
|
||||||
|
tauri::api::shell::open(&app.shell_scope(), path, None).unwrap();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
use crate::utils;
|
use crate::utils;
|
||||||
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, TitleBarStyle};
|
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use tauri::TitleBarStyle;
|
||||||
|
|
||||||
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
let conf = utils::get_tauri_conf().unwrap();
|
let conf = utils::get_tauri_conf().unwrap();
|
||||||
let url = conf.build.dev_path.to_string();
|
let url = conf.build.dev_path.to_string();
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
WindowBuilder::new(app, "core", WindowUrl::App(url.into()))
|
WindowBuilder::new(app, "core", WindowUrl::App(url.into()))
|
||||||
.resizable(true)
|
.resizable(true)
|
||||||
.fullscreen(false)
|
.fullscreen(false)
|
||||||
@@ -16,5 +20,16 @@ pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>
|
|||||||
.user_agent("5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
|
.user_agent("5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
WindowBuilder::new(app, "core", WindowUrl::App(url.into()))
|
||||||
|
.resizable(true)
|
||||||
|
.fullscreen(false)
|
||||||
|
.initialization_script(include_str!("../core.js"))
|
||||||
|
.initialization_script(&utils::user_script())
|
||||||
|
.inner_size(800.0, 600.0)
|
||||||
|
.title("ChatGPT")
|
||||||
|
.user_agent("5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
|
||||||
|
.build()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,16 +36,26 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const topStyleDom = document.createElement("style");
|
async function platform() {
|
||||||
topStyleDom.innerHTML = `#chatgpt-app-window-top{position:fixed;top:0;z-index:999999999;width:100%;height:24px;background:transparent;cursor:grab;cursor:-webkit-grab;user-select:none;-webkit-user-select:none;}#chatgpt-app-window-top:active {cursor:grabbing;cursor:-webkit-grabbing;}`;
|
return invoke('platform', {
|
||||||
document.head.appendChild(topStyleDom);
|
__tauriModule: 'Os',
|
||||||
const topDom = document.createElement("div");
|
message: { cmd: 'platform' }
|
||||||
topDom.id = "chatgpt-app-window-top";
|
});
|
||||||
document.body.appendChild(topDom);
|
}
|
||||||
|
|
||||||
topDom.addEventListener("mousedown", () => invoke("drag_window"));
|
const _platform = await platform();
|
||||||
topDom.addEventListener("touchstart", () => invoke("drag_window"));
|
if (/darwin/.test(_platform)) {
|
||||||
topDom.addEventListener("dblclick", () => invoke("fullscreen"));
|
const topStyleDom = document.createElement("style");
|
||||||
|
topStyleDom.innerHTML = `#chatgpt-app-window-top{position:fixed;top:0;z-index:999999999;width:100%;height:24px;background:transparent;cursor:grab;cursor:-webkit-grab;user-select:none;-webkit-user-select:none;}#chatgpt-app-window-top:active {cursor:grabbing;cursor:-webkit-grabbing;}`;
|
||||||
|
document.head.appendChild(topStyleDom);
|
||||||
|
const topDom = document.createElement("div");
|
||||||
|
topDom.id = "chatgpt-app-window-top";
|
||||||
|
document.body.appendChild(topDom);
|
||||||
|
|
||||||
|
topDom.addEventListener("mousedown", () => invoke("drag_window"));
|
||||||
|
topDom.addEventListener("touchstart", () => invoke("drag_window"));
|
||||||
|
topDom.addEventListener("dblclick", () => invoke("fullscreen"));
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener("click", (e) => {
|
document.addEventListener("click", (e) => {
|
||||||
const origin = e.target.closest("a");
|
const origin = e.target.closest("a");
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ mod app;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use app::{cmd, menu, setup};
|
use app::{cmd, menu, setup};
|
||||||
use tauri::SystemTray;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let context = tauri::generate_context!();
|
let context = tauri::generate_context!();
|
||||||
@@ -16,7 +15,7 @@ fn main() {
|
|||||||
.invoke_handler(tauri::generate_handler![cmd::drag_window, cmd::fullscreen])
|
.invoke_handler(tauri::generate_handler![cmd::drag_window, cmd::fullscreen])
|
||||||
.setup(setup::init)
|
.setup(setup::init)
|
||||||
.menu(menu::init(&context))
|
.menu(menu::init(&context))
|
||||||
.system_tray(SystemTray::new())
|
.system_tray(menu::tray_menu())
|
||||||
.on_menu_event(menu::menu_handler)
|
.on_menu_event(menu::menu_handler)
|
||||||
.on_system_tray_event(menu::tray_handler)
|
.on_system_tray_event(menu::tray_handler)
|
||||||
.run(context)
|
.run(context)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "ChatGPT",
|
"productName": "ChatGPT",
|
||||||
"version": "0.1.0"
|
"version": "0.1.5"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||