Files
ChatGPT/src-tauri/src/app/menu.rs
2022-12-22 08:59:58 +08:00

330 lines
12 KiB
Rust

use crate::{
conf::{self, ChatConfJson},
utils,
};
use tauri::{
AboutMetadata, AppHandle, CustomMenuItem, Manager, Menu, MenuItem, Submenu, SystemTray,
SystemTrayEvent, SystemTrayMenu, SystemTrayMenuItem, WindowMenuEvent,
};
use tauri_plugin_positioner::{on_tray_event, Position, WindowExt};
// --- Menu
pub fn init() -> Menu {
let chat_conf = ChatConfJson::get_chat_conf();
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),
);
let stay_on_top =
CustomMenuItem::new("stay_on_top".to_string(), "Stay 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 stay_on_top_menu = if chat_conf.stay_on_top {
stay_on_top.selected()
} else {
stay_on_top
};
let titlebar_menu = if chat_conf.titlebar {
titlebar.selected()
} else {
titlebar
};
let preferences_menu = Submenu::new(
"Preferences",
Menu::with_items([
CustomMenuItem::new("control_center".to_string(), "Control Center")
.accelerator("CmdOrCtrl+Shift+P")
.into(),
MenuItem::Separator.into(),
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
}),
)
.into(),
stay_on_top_menu.into(),
#[cfg(target_os = "macos")]
titlebar_menu.into(),
#[cfg(target_os = "macos")]
CustomMenuItem::new("hide_dock_icon".to_string(), "Hide Dock Icon").into(),
CustomMenuItem::new("inject_script".to_string(), "Inject Script")
.accelerator("CmdOrCtrl+J")
.into(),
MenuItem::Separator.into(),
CustomMenuItem::new("sync_prompts".to_string(), "Sync Prompts").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")
.accelerator("CmdOrCtrl+Shift+D")
.into(),
CustomMenuItem::new("restart".to_string(), "Restart ChatGPT")
.accelerator("CmdOrCtrl+Shift+R")
.into(),
MenuItem::Separator.into(),
CustomMenuItem::new("awesome".to_string(), "Awesome ChatGPT")
.accelerator("CmdOrCtrl+Shift+A")
.into(),
]),
);
let edit_menu = Submenu::new(
"Edit",
Menu::new()
.add_native_item(MenuItem::Undo)
.add_native_item(MenuItem::Redo)
.add_native_item(MenuItem::Separator)
.add_native_item(MenuItem::Cut)
.add_native_item(MenuItem::Copy)
.add_native_item(MenuItem::Paste)
.add_native_item(MenuItem::SelectAll),
);
let view_menu = Submenu::new(
"View",
Menu::new()
.add_item(
CustomMenuItem::new("go_back".to_string(), "Go Back").accelerator("CmdOrCtrl+Left"),
)
.add_item(
CustomMenuItem::new("go_forward".to_string(), "Go Forward")
.accelerator("CmdOrCtrl+Right"),
)
.add_item(
CustomMenuItem::new("scroll_top".to_string(), "Scroll to Top of Screen")
.accelerator("CmdOrCtrl+Up"),
)
.add_item(
CustomMenuItem::new("scroll_bottom".to_string(), "Scroll to Bottom of Screen")
.accelerator("CmdOrCtrl+Down"),
)
.add_native_item(MenuItem::Separator)
.add_item(
CustomMenuItem::new("reload".to_string(), "Refresh the Screen")
.accelerator("CmdOrCtrl+R"),
),
);
let window_menu = Submenu::new(
"Window",
Menu::new()
.add_native_item(MenuItem::Minimize)
.add_native_item(MenuItem::Zoom),
);
let help_menu = Submenu::new(
"Help",
Menu::new()
.add_item(CustomMenuItem::new(
"chatgpt_log".to_string(),
"ChatGPT Log",
))
.add_item(CustomMenuItem::new("update_log".to_string(), "Update Log"))
.add_item(CustomMenuItem::new("report_bug".to_string(), "Report Bug"))
.add_item(
CustomMenuItem::new("dev_tools".to_string(), "Toggle Developer Tools")
.accelerator("CmdOrCtrl+Shift+I"),
),
);
Menu::new()
.add_submenu(app_menu)
.add_submenu(preferences_menu)
.add_submenu(edit_menu)
.add_submenu(view_menu)
.add_submenu(window_menu)
.add_submenu(help_menu)
}
// --- Menu Event
pub fn menu_handler(event: WindowMenuEvent<tauri::Wry>) {
let win = Some(event.window()).unwrap();
let app = win.app_handle();
let state: tauri::State<conf::ChatState> = app.state();
let script_path = utils::script_path().to_string_lossy().to_string();
let menu_id = event.menu_item_id();
let core_window = app.get_window("core").unwrap();
let menu_handle = core_window.menu_handle();
match menu_id {
// Preferences
"control_center" => app.get_window("main").unwrap().show().unwrap(),
"restart" => tauri::api::process::restart(&app.env()),
"inject_script" => open(&app, script_path),
"go_conf" => utils::open_file(utils::chat_root()),
"clear_conf" => utils::clear_conf(&app),
"awesome" => open(&app, conf::AWESOME_URL.to_string()),
"sync_prompts" => {
tauri::api::dialog::ask(
app.get_window("main").as_ref(),
"Sync Prompts",
"Data sync will enable all prompts, are you sure you want to sync?",
move |is_restart| {
if is_restart {
app.get_window("main")
.unwrap()
.eval("window.__sync_prompts && window.__sync_prompts()")
.unwrap()
}
},
);
}
"hide_dock_icon" => {
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app)).unwrap()
}
"titlebar" => {
let chat_conf = conf::ChatConfJson::get_chat_conf();
ChatConfJson::amend(
&serde_json::json!({ "titlebar": !chat_conf.titlebar }),
None,
)
.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 }), Some(app)).unwrap();
}
"stay_on_top" => {
let mut stay_on_top = state.stay_on_top.lock().unwrap();
*stay_on_top = !*stay_on_top;
menu_handle
.get_item(menu_id)
.set_selected(*stay_on_top)
.unwrap();
win.set_always_on_top(*stay_on_top).unwrap();
ChatConfJson::amend(&serde_json::json!({ "stay_on_top": *stay_on_top }), None).unwrap();
}
// View
"reload" => win.eval("window.location.reload()").unwrap(),
"go_back" => win.eval("window.history.go(-1)").unwrap(),
"go_forward" => win.eval("window.history.go(1)").unwrap(),
"scroll_top" => win
.eval(
r#"window.scroll({
top: 0,
left: 0,
behavior: "smooth"
})"#,
)
.unwrap(),
"scroll_bottom" => win
.eval(
r#"window.scroll({
top: document.body.scrollHeight,
left: 0,
behavior: "smooth"})"#,
)
.unwrap(),
// Help
"chatgpt_log" => utils::open_file(utils::chat_root().join("chatgpt.log")),
"update_log" => open(&app, conf::UPDATE_LOG_URL.to_string()),
"report_bug" => open(&app, conf::ISSUES_URL.to_string()),
"dev_tools" => {
win.open_devtools();
win.close_devtools();
}
_ => (),
}
}
// --- SystemTray Menu
pub fn tray_menu() -> SystemTray {
SystemTray::new().with_menu(
SystemTrayMenu::new()
.add_item(CustomMenuItem::new(
"control_center".to_string(),
"Control Center",
))
.add_item(CustomMenuItem::new(
"show_dock_icon".to_string(),
"Show Dock Icon",
))
.add_item(CustomMenuItem::new(
"hide_dock_icon".to_string(),
"Hide Dock Icon",
))
.add_native_item(SystemTrayMenuItem::Separator)
.add_item(CustomMenuItem::new("quit".to_string(), "Quit ChatGPT")),
)
}
// --- SystemTray Event
pub fn tray_handler(handle: &AppHandle, event: SystemTrayEvent) {
on_tray_event(handle, &event);
let app = handle.clone();
match event {
SystemTrayEvent::LeftClick { .. } => {
let chat_conf = conf::ChatConfJson::get_chat_conf();
if !chat_conf.hide_dock_icon {
let core_win = handle.get_window("core").unwrap();
core_win.minimize().unwrap();
}
let tray_win = handle.get_window("tray").unwrap();
tray_win.move_window(Position::TrayCenter).unwrap();
if tray_win.is_visible().unwrap() {
tray_win.hide().unwrap();
} else {
tray_win.show().unwrap();
}
}
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
"control_center" => app.get_window("main").unwrap().show().unwrap(),
"restart" => tauri::api::process::restart(&handle.env()),
"show_dock_icon" => {
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": false }), Some(app))
.unwrap();
}
"hide_dock_icon" => {
let chat_conf = conf::ChatConfJson::get_chat_conf();
if !chat_conf.hide_dock_icon {
ChatConfJson::amend(&serde_json::json!({ "hide_dock_icon": true }), Some(app))
.unwrap();
}
}
"quit" => std::process::exit(0),
_ => (),
},
_ => (),
}
}
pub fn open(app: &AppHandle, path: String) {
tauri::api::shell::open(&app.shell_scope(), path, None).unwrap();
}