Skip to content

Commit

Permalink
Merge pull request lencx#15 from lencx/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
lencx authored Dec 11, 2022
2 parents 0871608 + 55e17e1 commit 325dbb3
Show file tree
Hide file tree
Showing 16 changed files with 368 additions and 86 deletions.
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

**Latest:**

- `Mac`: [ChatGPT_0.1.7_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.1.7/ChatGPT_0.1.7_x64.dmg)
- `Linux`: [chat-gpt_0.1.7_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.1.7/chat-gpt_0.1.7_amd64.deb)
- `Windows`: [ChatGPT_0.1.7_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.1.7/ChatGPT_0.1.7_x64_en-US.msi)
- `Mac`: [ChatGPT_0.1.8_x64.dmg](https://github.com/lencx/ChatGPT/releases/download/v0.1.8/ChatGPT_0.1.8_x64.dmg)
- `Linux`: [chat-gpt_0.1.8_amd64.deb](https://github.com/lencx/ChatGPT/releases/download/v0.1.8/chat-gpt_0.1.8_amd64.deb)
- `Windows`: [ChatGPT_0.1.8_x64_en-US.msi](https://github.com/lencx/ChatGPT/releases/download/v0.1.8/ChatGPT_0.1.8_x64_en-US.msi)

[Other version...](https://github.com/lencx/ChatGPT/releases)

Expand Down Expand Up @@ -52,6 +52,23 @@ cask "popcorn-time", args: { "no-quarantine": true }
- tray window
- shortcut

### Menu

- **ChatGPT**
- `Restart ChatGPT`: After editing the injection script file, you can restart the application through this menu item to make the script take effect.
- **Preferences**
- `Theme` - `Light`, `Dark` (Only macOS and Windows are supported).
- `Always On Top`: Window is always on top of other windows.
- `Titlebar`: Only supports macOS.
- `Switch Origin` ([#14](https://github.com/lencx/ChatGPT/issues/14)): Modify website address, the default is `https://chat.openai.com`. Please ensure that the mirror address is consistent with the UI of the original URL, otherwise the export function will fail.
- `Inject Script`: User scripts that can modify web pages.
- `Awesome ChatGPT`: Related resources recommended.
- **Edit** - `Undo`, `Redo`, `Cut`, `Copy`, `SelectAll`, ...
- **View** - `Go Back`, `Go Forward`, `Scroll to Top of Screen`, `Scroll to Bottom of Screen`, `Refresh the Screen`, ...
- **Help**
- `Report Bug`: Defects and Suggestions Feedback.
- `Toggle Developer Tools`: Developer tools for debugging web pages.

## Preview

<img width="320" src="./assets/install.png" alt="install"> <img width="320" src="./assets/chat.png" alt="chat">
Expand Down
6 changes: 6 additions & 0 deletions UPDATE_LOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# UPDATE LOG

## v0.1.8

feat:
- menu enhancement: theme, titlebar
- modify website address

## v0.1.7

feat: tray window
Expand Down
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@
},
"license": "MIT",
"author": "lencx <[email protected]>",
"keywords": ["chatgpt", "app", "desktop", "tauri", "macos", "linux", "windows"],
"keywords": [
"chatgpt",
"app",
"desktop",
"tauri",
"macos",
"linux",
"windows"
],
"homepage": "https://github.com/lencx/ChatGPT",
"bugs": "https://github.com/lencx/ChatGPT/issues",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ rust-version = "1.57"
tauri-build = {version = "1.2.1", features = [] }

[dependencies]
anyhow = "1.0.66"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2.1", features = ["api-all", "devtools", "system-tray", "updater"] }
tauri = { version = "1.2.2", features = ["api-all", "devtools", "system-tray", "updater"] }
tauri-plugin-positioner = { version = "1.0.4", features = ["system-tray"] }
anyhow = "1.0.66"

[features]
# by default Tauri runs in production mode
Expand Down
Binary file added src-tauri/icons/tray-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 33 additions & 1 deletion src-tauri/src/app/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::utils;
use crate::{conf::ChatConfJson, utils};
use std::fs;
use tauri::{api, command, AppHandle, Manager};

Expand Down Expand Up @@ -28,3 +28,35 @@ pub fn download(_app: AppHandle, name: String, blob: Vec<u8>) {
pub fn open_link(app: AppHandle, url: String) {
api::shell::open(&app.shell_scope(), url, None).unwrap();
}

#[command]
pub fn get_chat_conf() -> ChatConfJson {
ChatConfJson::get_chat_conf()
}

#[command]
pub fn form_confirm(app: AppHandle, data: serde_json::Value) {
ChatConfJson::amend(&serde_json::json!(data)).unwrap();
tauri::api::process::restart(&app.env());
}

#[command]
pub fn form_cancel(app: AppHandle, label: &str, title: &str, msg: &str) {
let win = app.app_handle().get_window(label).unwrap();
tauri::api::dialog::ask(
app.app_handle().get_window(label).as_ref(),
title,
msg,
move |is_cancel| {
if is_cancel {
win.close().unwrap();
}
},
);
}

#[command]
pub fn form_msg(app: AppHandle, label: &str, title: &str, msg: &str) {
let win = app.app_handle().get_window(label);
tauri::api::dialog::message(win.as_ref(), title, msg);
}
96 changes: 79 additions & 17 deletions src-tauri/src/app/menu.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
use crate::{conf, utils};
use crate::{
app::window,
conf::{self, ChatConfJson},
utils,
};
use tauri::{
utils::assets::EmbeddedAssets, AboutMetadata, AppHandle, Context, CustomMenuItem, Manager,
Menu, MenuItem, Submenu, SystemTray, SystemTrayEvent, SystemTrayMenu, WindowMenuEvent,
};
use tauri_plugin_positioner::{on_tray_event, Position, WindowExt};

// --- Menu
pub fn init(chat_conf: &conf::ChatConfJson, context: &Context<EmbeddedAssets>) -> Menu {
pub fn init(context: &Context<EmbeddedAssets>) -> Menu {
let chat_conf = ChatConfJson::get_chat_conf();
let name = &context.package_info().name;
let app_menu = Submenu::new(
name,
Menu::new()
.add_native_item(MenuItem::About(name.into(), AboutMetadata::default()))
.add_native_item(MenuItem::Separator)
.add_item(
CustomMenuItem::new("restart".to_string(), "Restart ChatGPT")
.accelerator("CmdOrCtrl+Shift+R"),
)
.add_native_item(MenuItem::Services)
.add_native_item(MenuItem::Separator)
.add_native_item(MenuItem::Hide)
.add_native_item(MenuItem::HideOthers)
Expand All @@ -23,24 +33,55 @@ pub fn init(chat_conf: &conf::ChatConfJson, context: &Context<EmbeddedAssets>) -

let always_on_top = CustomMenuItem::new("always_on_top".to_string(), "Always On Top")
.accelerator("CmdOrCtrl+T");
let titlebar =
CustomMenuItem::new("titlebar".to_string(), "Titlebar").accelerator("CmdOrCtrl+B");
let theme_light = CustomMenuItem::new("theme_light".to_string(), "Light");
let theme_dark = CustomMenuItem::new("theme_dark".to_string(), "Dark");
let is_dark = chat_conf.theme == "Dark";

let always_on_top_menu = if chat_conf.always_on_top {
always_on_top.selected()
} else {
always_on_top
};
let titlebar_menu = if chat_conf.titlebar {
titlebar.selected()
} else {
titlebar
};

let preferences_menu = Submenu::new(
"Preferences",
Menu::new()
.add_item(
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
.accelerator("CmdOrCtrl+J"),
Menu::with_items([
Submenu::new(
"Theme",
Menu::new()
.add_item(if is_dark {
theme_light
} else {
theme_light.selected()
})
.add_item(if is_dark {
theme_dark.selected()
} else {
theme_dark
}),
)
.add_item(if chat_conf.always_on_top {
always_on_top.selected()
} else {
always_on_top
})
.add_native_item(MenuItem::Separator)
.add_item(
CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
.accelerator("CmdOrCtrl+Z"),
),
.into(),
always_on_top_menu.into(),
#[cfg(target_os = "macos")]
titlebar_menu.into(),
CustomMenuItem::new("switch_origin".to_string(), "Switch Origin")
.accelerator("CmdOrCtrl+O")
.into(),
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
.accelerator("CmdOrCtrl+J")
.into(),
MenuItem::Separator.into(),
CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
.accelerator("CmdOrCtrl+Z")
.into(),
]),
);

let edit_menu = Submenu::new(
Expand Down Expand Up @@ -73,6 +114,7 @@ pub fn init(chat_conf: &conf::ChatConfJson, context: &Context<EmbeddedAssets>) -
CustomMenuItem::new("scroll_bottom".to_string(), "Scroll to Bottom of Screen")
.accelerator("CmdOrCtrl+Down"),
)
.add_native_item(MenuItem::Zoom)
.add_native_item(MenuItem::Separator)
.add_item(
CustomMenuItem::new("reload".to_string(), "Refresh the Screen")
Expand Down Expand Up @@ -110,9 +152,29 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
let menu_handle = core_window.menu_handle();

match menu_id {
// App
"restart" => tauri::api::process::restart(&app.env()),
// Preferences
"inject_script" => open(&app, script_path),
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
"switch_origin" => {
window::origin_window(&app);
// app.get_window("origin").unwrap().show();
}
"titlebar" => {
let chat_conf = conf::ChatConfJson::get_chat_conf();
ChatConfJson::amend(&serde_json::json!({ "titlebar": !chat_conf.titlebar })).unwrap();
tauri::api::process::restart(&app.env());
}
"theme_light" | "theme_dark" => {
let theme = if menu_id == "theme_dark" {
"Dark"
} else {
"Light"
};
ChatConfJson::amend(&serde_json::json!({ "theme": theme })).unwrap();
tauri::api::process::restart(&app.env());
}
"always_on_top" => {
let mut always_on_top = state.always_on_top.lock().unwrap();
*always_on_top = !*always_on_top;
Expand All @@ -121,7 +183,7 @@ pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
.set_selected(*always_on_top)
.unwrap();
win.set_always_on_top(*always_on_top).unwrap();
conf::ChatConfJson::update_chat_conf(*always_on_top);
ChatConfJson::amend(&serde_json::json!({ "always_on_top": *always_on_top })).unwrap();
}
// View
"reload" => win.eval("window.location.reload()").unwrap(),
Expand Down
27 changes: 14 additions & 13 deletions src-tauri/src/app/setup.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::{app::window, conf, utils};
use crate::{
app::window,
conf::{ChatConfJson, USER_AGENT},
utils,
};
use tauri::{utils::config::WindowUrl, window::WindowBuilder, App, Manager};

#[cfg(target_os = "macos")]
use tauri::TitleBarStyle;

pub fn init(
app: &mut App,
chat_conf: conf::ChatConfJson,
) -> std::result::Result<(), Box<dyn std::error::Error>> {
let conf = utils::get_tauri_conf().unwrap();
let url = conf.build.dev_path.to_string();
pub fn init(app: &mut App) -> std::result::Result<(), Box<dyn std::error::Error>> {
let chat_conf = ChatConfJson::get_chat_conf();
let url = chat_conf.origin.to_string();
let theme = ChatConfJson::theme();
window::mini_window(&app.app_handle());

#[cfg(target_os = "macos")]
Expand All @@ -18,14 +17,15 @@ pub fn init(
.fullscreen(false)
.inner_size(800.0, 600.0)
.hidden_title(true)
.title_bar_style(TitleBarStyle::Overlay)
.theme(theme)
.always_on_top(chat_conf.always_on_top)
.title_bar_style(ChatConfJson::titlebar())
.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"))
.user_agent(conf::USER_AGENT)
.user_agent(USER_AGENT)
.build()?;

#[cfg(not(target_os = "macos"))]
Expand All @@ -34,13 +34,14 @@ pub fn init(
.resizable(true)
.fullscreen(false)
.inner_size(800.0, 600.0)
.theme(theme)
.always_on_top(chat_conf.always_on_top)
.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"))
.user_agent(conf::USER_AGENT)
.user_agent(USER_AGENT)
.build()?;

Ok(())
Expand Down
24 changes: 20 additions & 4 deletions src-tauri/src/app/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,40 @@ use crate::{conf, utils};
use tauri::{utils::config::WindowUrl, window::WindowBuilder};

pub fn mini_window(handle: &tauri::AppHandle) {
let conf = utils::get_tauri_conf().unwrap();
let url = conf.build.dev_path.to_string();
let chat_conf = conf::ChatConfJson::get_chat_conf();
let theme = conf::ChatConfJson::theme();

WindowBuilder::new(handle, "mini", WindowUrl::App(url.into()))
WindowBuilder::new(handle, "mini", WindowUrl::App(chat_conf.origin.into()))
.resizable(false)
.fullscreen(false)
.inner_size(360.0, 540.0)
.decorations(false)
.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"))
.user_agent(conf::PHONE_USER_AGENT)
.menu(tauri::Menu::new())
.build()
.unwrap()
.hide()
.unwrap();
}

pub fn origin_window(handle: &tauri::AppHandle) {
let chat_conf = conf::ChatConfJson::get_chat_conf();
// tauri://localhost/origin
// let url = chat_conf.origin;
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();
}
5 changes: 3 additions & 2 deletions src-tauri/src/assets/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ async function init() {
}

const _platform = await platform();
if (/darwin/.test(_platform)) {
const chatConf = await invoke('get_chat_conf') || {};
if (/darwin/.test(_platform) && !chatConf.titlebar) {
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);
Expand All @@ -70,7 +71,7 @@ async function init() {
document.addEventListener("click", (e) => {
const origin = e.target.closest("a");
if (origin && origin.href && origin.target !== '_self') {
origin.target = "_self";
invoke('open_link', { url: origin.href });
}
});

Expand Down
Loading

0 comments on commit 325dbb3

Please sign in to comment.