diff --git a/dist/about_pake.html b/dist/about_pake.html new file mode 100644 index 0000000..e1655dd --- /dev/null +++ b/dist/about_pake.html @@ -0,0 +1,16 @@ + + + + + + Document + + +
Welcome from Pake!
+

version: 1.0.1

+ Project link
+ Discussions
+ Issues
+

LICENSE: MIT

+ + \ No newline at end of file diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a02d382..fa36a96 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -48,9 +48,9 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-window-state", "tauri-utils", - "webbrowser", - "wry", + "webkit2gtk", ] [[package]] @@ -89,6 +89,15 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bit_field" version = "0.10.1" @@ -1345,12 +1354,46 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +[[package]] +name = "libappindicator" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2d3cb96d092b4824cb306c9e544c856a4cb6210c1081945187f7f1924b47e8" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b6681973cea8cc3bce7391e6d7d5502720b80a581c9a95c9cbaf592826aa" +dependencies = [ + "gtk-sys", + "libloading", + "once_cell", +] + [[package]] name = "libc" version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "line-wrap" version = "0.1.1" @@ -2482,6 +2525,7 @@ dependencies = [ "core-foundation", "core-graphics", "crossbeam-channel", + "dirs-next", "dispatch", "gdk", "gdk-pixbuf", @@ -2495,6 +2539,7 @@ dependencies = [ "instant", "jni", "lazy_static", + "libappindicator", "libc", "log", "ndk", @@ -2626,6 +2671,17 @@ dependencies = [ "tauri-utils", ] +[[package]] +name = "tauri-plugin-window-state" +version = "0.1.0" +source = "git+https://github.com/tauri-apps/tauri-plugin-window-state?branch=dev#17f468062904e64bb3ebf5f1b7486883aaafa1cf" +dependencies = [ + "bincode", + "serde", + "tauri", + "thiserror", +] + [[package]] name = "tauri-runtime" version = "0.12.1" @@ -3083,32 +3139,6 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0cc7962b5aaa0dfcebaeef0161eec6edf5f4606c12e6777fd7d392f52033a5" -dependencies = [ - "jni", - "ndk-context", - "objc", - "raw-window-handle", - "url", - "web-sys", - "widestring", - "winapi", -] - [[package]] name = "webkit2gtk" version = "0.18.2" @@ -3200,12 +3230,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" -[[package]] -name = "widestring" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" - [[package]] name = "winapi" version = "0.3.9" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ccc7e9f..d829449 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,12 +17,14 @@ tauri-build = { version = "1.2.1", features = [] } [dependencies] serde_json = "1.0.89" serde = { version = "1.0.150", features = ["derive"] } -tauri = { version = "1.2.2", features = [] } +tauri = { version = "1.2.2", features = ["system-tray"] } image = "0.24.5" home = "0.5" tauri-utils = "1.2.1" -webbrowser = "0.8.2" -wry = "0.23.4" +tauri-plugin-window-state = { git = "https://github.com/tauri-apps/tauri-plugin-window-state", branch = "dev"} +webkit2gtk = "0.18.0" +# webbrowser = "0.8.2" +# wry = "0.23.4" [features] # by default Tauri runs in production mode diff --git a/src-tauri/pake.json b/src-tauri/pake.json new file mode 100644 index 0000000..32b5543 --- /dev/null +++ b/src-tauri/pake.json @@ -0,0 +1,18 @@ +{ + "windows": [ + { + "url": "https://weread.qq.com/", + "transparent": true, + "fullscreen": false, + "width": 1200, + "height": 780, + "resizable": true, + "url_type": "web" + } + ], + "user_agent": { + "macos": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", + "linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", + "windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" + } +} \ No newline at end of file diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs new file mode 100644 index 0000000..6bd2441 --- /dev/null +++ b/src-tauri/src/lib.rs @@ -0,0 +1,263 @@ +#[cfg(target_os = "macos")] +use tauri::MenuItem; + +use tauri::{ + window::PlatformWebview, App, Config, CustomMenuItem, Manager, Menu, Submenu, SystemTray, + SystemTrayEvent, SystemTrayMenu, Window, WindowBuilder, WindowMenuEvent, WindowUrl, +}; + +pub fn get_menu() -> Menu { + // first menu + let hide = CustomMenuItem::new("hide", "Hide"); + let close = CustomMenuItem::new("close", "Close"); + let quit = CustomMenuItem::new("quit", "Quit"); + #[cfg(target_os = "macos")] + let first_menu = Menu::new() + .add_native_item(MenuItem::EnterFullScreen) + .add_native_item(MenuItem::Minimize) + .add_native_item(MenuItem::Separator) + .add_native_item(MenuItem::Copy) + .add_native_item(MenuItem::Cut) + .add_native_item(MenuItem::Paste) + .add_native_item(MenuItem::Undo) + .add_native_item(MenuItem::Redo) + .add_native_item(MenuItem::SelectAll) + .add_native_item(MenuItem::Separator) + .add_item(hide) + .add_item(close) + .add_item(quit); + #[cfg(any(target_os = "linux", target_os = "windows"))] + let first_menu = Menu::new().add_item(hide).add_item(close).add_item(quit); + let first_menu = Submenu::new("File", first_menu); + // Hot Key + // let top = CustomMenuItem::new("top", "Top (↑)"); + // let buttom = CustomMenuItem::new("buttom", "Bottom (↓)"); + // let previous = CustomMenuItem::new("previous", "Previous (←)"); + // let next = CustomMenuItem::new("next", "next (→)"); + // let refresh = CustomMenuItem::new("refresh", "Refresh"); + let zoom_out = CustomMenuItem::new("zoom_out", "Zoom Out (125%)"); + let zoom_in = CustomMenuItem::new("zoom_in", "Zoom In (75%)"); + let zoom_reset = CustomMenuItem::new("reset", "Zoom Reset"); + let hot_key = Menu::new() + // .add_item(top) + // .add_item(buttom) + // .add_item(previous) + // .add_item(next) + // .add_item(refresh) + .add_item(zoom_in) + .add_item(zoom_out) + .add_item(zoom_reset); + let hot_key_menu = Submenu::new("Hot Key", hot_key); + + // Help + // let instructions = CustomMenuItem::new("instruction", "Instruction"); + // let about = CustomMenuItem::new("about", "About"); + // let help = Menu::new() + // .add_item(instructions) + // .add_item(about); + // let help_menu = Submenu::new("Help", help); + let menu = Menu::new() + .add_submenu(first_menu) + .add_submenu(hot_key_menu); + menu +} + +pub fn set_zoom(webview: PlatformWebview, zoom_value: f64) { + #[cfg(target_os = "linux")] + { + // see https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/struct.WebView.html + // and https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/trait.WebViewExt.html + use webkit2gtk::traits::WebViewExt; + webview.inner().set_zoom_level(zoom_value); + } + + #[cfg(windows)] + unsafe { + // see https://docs.rs/webview2-com/0.19.1/webview2_com/Microsoft/Web/WebView2/Win32/struct.ICoreWebView2Controller.html + webview.controller().SetZoomFactor(zoom_value).unwrap(); + } + + #[cfg(target_os = "macos")] + unsafe { + let () = msg_send![webview.inner(), setPageZoom: zoom_value]; + let () = msg_send![webview.controller(), removeAllUserScripts]; + let bg_color: cocoa::base::id = + msg_send![class!(NSColor), colorWithDeviceRed:0.5 green:0.2 blue:0.4 alpha:1.]; + let () = msg_send![webview.ns_window(), setBackgroundColor: bg_color]; + } +} + +pub fn set_zoom_out(webview: PlatformWebview) { + set_zoom(webview, 1.25); +} + +pub fn set_zoom_in(webview: PlatformWebview) { + set_zoom(webview, 0.75); +} + +pub fn zoom_reset(webview: PlatformWebview) { + set_zoom(webview, 1.0); +} + +pub fn menu_event_handle(event: WindowMenuEvent) { + match event.menu_item_id() { + "hide" => event.window().hide().expect("can't hide window"), + "close" => event.window().close().expect("can't close window"), + "quit" => std::process::exit(0), + "zoom_out" => { + event + .window() + .with_webview(set_zoom_out) + .expect("can't set zoom out"); + } + "zoom_in" => { + event + .window() + .with_webview(set_zoom_in) + .expect("can't set zoom in"); + } + "reset" => { + event + .window() + .with_webview(zoom_reset) + .expect("can't reset zoom"); + } + _ => {} + } +} + +pub mod pake { + use serde::Deserialize; + + #[derive(Debug, Deserialize)] + pub struct WindowConfig { + pub url: String, + pub transparent: bool, + pub fullscreen: bool, + pub width: f64, + pub height: f64, + pub resizable: bool, + pub url_type: String, + } + + #[derive(Debug, Deserialize)] + pub struct UserAgent { + pub macos: String, + pub linux: String, + pub windows: String, + } + + #[derive(Debug, Deserialize)] + pub struct PakeConfig { + pub windows: Vec, + pub user_agent: UserAgent, + } +} + +use pake::PakeConfig; + +pub fn get_pake_config() -> (PakeConfig, Config) { + let pake_config_path = include_str!("../pake.json"); + let pake_config: PakeConfig = + serde_json::from_str(pake_config_path).expect("failed to parse pake config"); + // println!("{:#?}", config); + let tauri_config_path = include_str!("../tauri.conf.json"); + let tauri_config: Config = + serde_json::from_str(tauri_config_path).expect("failed to parse tauri config"); + (pake_config, tauri_config) +} + +pub fn get_system_tray() -> SystemTray { + let hide = CustomMenuItem::new("hide".to_string(), "Hide"); + let show = CustomMenuItem::new("show".to_string(), "Show"); + let quit = CustomMenuItem::new("quit".to_string(), "Quit"); + let about = CustomMenuItem::new("about".to_string(), "About"); + let tray_menu = SystemTrayMenu::new() + .add_item(hide) + .add_item(show) + .add_item(quit) + .add_item(about); + SystemTray::new().with_menu(tray_menu) +} + +pub fn system_tray_handle(app: &tauri::AppHandle, event: tauri::SystemTrayEvent) { + if let SystemTrayEvent::MenuItemClick { tray_id: _, id, .. } = event { + match id.as_str() { + "hide" => { + app.get_window("pake").unwrap().hide().unwrap(); + } + "show" => { + app.get_window("pake").unwrap().show().unwrap(); + } + "quit" => { + std::process::exit(0); + } + "about" => { + let _about_window = WindowBuilder::new( + app, + "about", + WindowUrl::App(std::path::PathBuf::from("about_pake.html")), + ) + .resizable(true) + .title("About") + .inner_size(100.0, 100.0) + .build() + .expect("can't open about!"); + } + _ => {} + } + }; +} + +pub fn get_data_dir(tauri_config: Config) -> std::path::PathBuf { + let package_name = tauri_config.package.product_name.unwrap(); + let home_dir = match home::home_dir() { + Some(path1) => path1, + None => panic!("Error, can't found you home dir!!"), + }; + #[cfg(target_os = "windows")] + let data_dir = home_dir.join("AppData").join("Roaming").join(package_name); + #[cfg(target_os = "linux")] + let data_dir = home_dir.join(".config").join(package_name); + if !data_dir.exists() { + std::fs::create_dir(&data_dir) + .unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display())); + } + data_dir +} + +pub fn get_window(app: &mut App, config: PakeConfig, data_dir: std::path::PathBuf) -> Window { + let window_config = config.windows.first().unwrap(); + let user_agent = config.user_agent; + let url = match window_config.url_type.as_str() { + "web" => WindowUrl::External(window_config.url.parse().unwrap()), + "local" => WindowUrl::App(std::path::PathBuf::from(&window_config.url)), + _ => panic!("url type only can be web or local"), + }; + #[cfg(target_os = "macos")] + let window = WindowBuilder::new(app, "pake", url) + .title("") + .user_agent(user_agent.macos.as_str()) + .resizable(window_config.resizable) + .fullscreen(window_config.fullscreen) + .transparent(window_config.transparent) + .inner_size(window_config.width, window_config.height) + .initialization_script(include_str!("pake.js")); + + #[cfg(any(target_os = "linux", target_os = "windows"))] + let window = { + #[cfg(target_os = "linux")] + let user_agent = user_agent.linux.as_str(); + #[cfg(target_os = "windows")] + let user_agent = user_agent.windows.as_str(); + WindowBuilder::new(app, "pake", url) + .title("") + .data_directory(data_dir) + .resizable(window_config.resizable) + .fullscreen(window_config.fullscreen) + .user_agent(user_agent) + .inner_size(window_config.width, window_config.height) + .initialization_script(include_str!("pake.js")) + }; + window.build().unwrap() +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index fe8714b..0ac2093 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,230 +1,61 @@ -// at the top of main.rs - that will prevent the console from showing -#![windows_subsystem = "windows"] -extern crate image; -use tauri_utils::config::{Config, WindowConfig}; -use wry::{ - application::{ - event::{Event, StartCause, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, - menu::MenuType, - window::{Fullscreen, Window, WindowBuilder}, - }, - webview::WebViewBuilder, -}; +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] +use app::{get_data_dir, get_pake_config, get_system_tray, get_window, system_tray_handle}; #[cfg(target_os = "macos")] -use wry::application::{ - accelerator::{Accelerator, SysMods}, - keyboard::KeyCode, - menu::{MenuBar as Menu, MenuItem, MenuItemAttributes}, - platform::macos::WindowBuilderExtMacOS, -}; +use app::{get_menu, menu_event_handle}; -#[cfg(target_os = "windows")] -use wry::application::window::Icon; - -#[cfg(any(target_os = "linux", target_os = "windows"))] -use wry::webview::WebContext; - -fn main() -> wry::Result<()> { +pub fn run_app() { + let system_tray = get_system_tray(); #[cfg(target_os = "macos")] - let (menu_bar_menu, close_item) = { - let mut menu_bar_menu = Menu::new(); - let mut first_menu = Menu::new(); - first_menu.add_native_item(MenuItem::Hide); - first_menu.add_native_item(MenuItem::EnterFullScreen); - first_menu.add_native_item(MenuItem::Minimize); - first_menu.add_native_item(MenuItem::Separator); - first_menu.add_native_item(MenuItem::Copy); - first_menu.add_native_item(MenuItem::Cut); - first_menu.add_native_item(MenuItem::Paste); - first_menu.add_native_item(MenuItem::Undo); - first_menu.add_native_item(MenuItem::Redo); - first_menu.add_native_item(MenuItem::SelectAll); - first_menu.add_native_item(MenuItem::Separator); - let close_item = first_menu.add_item( - MenuItemAttributes::new("CloseWindow") - .with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyW)), - ); - first_menu.add_native_item(MenuItem::Quit); - menu_bar_menu.add_submenu("App", true, first_menu); - (menu_bar_menu, close_item) - }; - - #[cfg(any(target_os = "linux", target_os = "windows"))] - let ( - package_name, - WindowConfig { - url, - width, - height, - resizable, - fullscreen, - .. - }, - ) = { - let (package_name, windows_config) = get_windows_config(); - ( - package_name - .expect("can't get package name in config file") - .to_lowercase(), - windows_config.unwrap_or_default(), - ) - }; - - #[cfg(target_os = "macos")] - let WindowConfig { - url, - width, - height, - resizable, - transparent, - fullscreen, - .. - } = get_windows_config().1.unwrap_or_default(); - let event_loop = EventLoop::new(); - - let common_window = WindowBuilder::new() - .with_title("") - .with_resizable(resizable) - .with_fullscreen(if fullscreen { - Some(Fullscreen::Borderless(None)) - } else { - None - }) - .with_inner_size(wry::application::dpi::LogicalSize::new(width, height)); - #[cfg(target_os = "windows")] - let window = { - let icon_path = format!("png/{}_32.ico", package_name); - let icon = load_icon(std::path::Path::new(&icon_path)); - common_window - .with_decorations(true) - .with_window_icon(Some(icon)) - .build(&event_loop) - .unwrap() - }; - - #[cfg(target_os = "linux")] - let window = common_window.build(&event_loop).unwrap(); - - #[cfg(target_os = "macos")] - let window = common_window - .with_fullsize_content_view(true) - .with_titlebar_buttons_hidden(false) - .with_titlebar_transparent(transparent) - .with_title_hidden(true) - .with_menu(menu_bar_menu) - .build(&event_loop) - .unwrap(); - - let handler = move |window: &Window, req: String| { - if req == "drag_window" { - let _ = window.drag_window(); - } else if req == "fullscreen" { - if window.fullscreen().is_some() { - window.set_fullscreen(None); - } else { - window.set_fullscreen(Some(Fullscreen::Borderless(None))); - } - } else if req.starts_with("open_browser") { - let href = req.replace("open_browser:", ""); - webbrowser::open(&href).expect("no browser"); - } - }; - - // 用于欺骗部分页面对于浏览器的强检测 - - #[cfg(target_os = "macos")] - let webview = { - let user_agent_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15"; - WebViewBuilder::new(window)? - .with_user_agent(user_agent_string) - .with_url(&url.to_string())? - .with_devtools(cfg!(feature = "devtools")) - .with_initialization_script(include_str!("pake.js")) - .with_ipc_handler(handler) - .with_back_forward_navigation_gestures(true) - .build()? - }; - - #[cfg(any(target_os = "linux", target_os = "windows"))] - let webview = { - let home_dir = match home::home_dir() { - Some(path1) => path1, - None => panic!("Error, can't found you home dir!!"), - }; - #[cfg(target_os = "windows")] - let data_dir = home_dir.join("AppData").join("Roaming").join(package_name); - #[cfg(target_os = "linux")] - let data_dir = home_dir.join(".config").join(package_name); - if !data_dir.exists() { - std::fs::create_dir(&data_dir) - .unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display())); - } - let mut web_content = WebContext::new(Some(data_dir)); - #[cfg(target_os = "windows")] - let user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"; - #[cfg(target_os = "linux")] - let user_agent_string = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"; - WebViewBuilder::new(window)? - .with_user_agent(user_agent_string) - .with_url(&url.to_string())? - .with_devtools(cfg!(feature = "devtools")) - .with_initialization_script(include_str!("pake.js")) - .with_ipc_handler(handler) - .with_web_context(&mut web_content) - .build()? - }; - #[cfg(feature = "devtools")] { - webview.open_devtools(); - } - - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Wait; - - match event { - Event::NewEvents(StartCause::Init) => println!("Wry has started!"), - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => *control_flow = ControlFlow::Exit, - Event::MenuEvent { - menu_id, - origin: MenuType::MenuBar, - .. - } => { - #[cfg(target_os = "macos")] - if menu_id == close_item.clone().id() { - webview.window().set_minimized(true); + let (pake_config, _) = get_pake_config(); + let menu = get_menu(); + tauri::Builder::default() + .menu(menu) + .on_menu_event(menu_event_handle) + .system_tray(system_tray) + .on_system_tray_event(system_tray_handle) + .plugin(tauri_plugin_window_state::Builder::default().build()) + .invoke_handler(tauri::generate_handler![]) + .setup(|app| { + let _window = get_window(app, pake_config, std::path::PathBuf::new()); + #[cfg(feature = "devtools")] + { + app.get_window("pake").unwrap().open_devtools(); } - println!("Clicked on {:?}", menu_id); - println!("Clicked on {:?}", webview.window().is_visible()); - } - _ => (), - } - }); + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } + #[cfg(any(target_os = "linux", target_os = "windows"))] + { + let (pake_config, tauri_config) = get_pake_config(); + let data_dir = get_data_dir(tauri_config); + // let menu = get_menu(); + tauri::Builder::default() + // .menu(menu) + // .on_menu_event(menu_event_handle) + .system_tray(system_tray) + .on_system_tray_event(system_tray_handle) + .plugin(tauri_plugin_window_state::Builder::default().build()) + .invoke_handler(tauri::generate_handler![]) + .setup(|app| { + let _window = get_window(app, pake_config, data_dir); + #[cfg(feature = "devtools")] + { + app.get_window("pake").unwrap().open_devtools(); + } + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); + } } -fn get_windows_config() -> (Option, Option) { - let config_file = include_str!("../tauri.conf.json"); - let config: Config = serde_json::from_str(config_file).expect("failed to parse windows config"); - ( - config.package.product_name.clone(), - config.tauri.windows.first().cloned(), - ) -} - -#[cfg(target_os = "windows")] -fn load_icon(path: &std::path::Path) -> Icon { - let (icon_rgba, icon_width, icon_height) = { - // alternatively, you can embed the icon in the binary through `include_bytes!` macro and use `image::load_from_memory` - let image = image::open(path) - .expect("Failed to open icon path") - .into_rgba8(); - let (width, height) = image.dimensions(); - let rgba = image.into_raw(); - (rgba, width, height) - }; - Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon") +fn main() { + run_app() } diff --git a/src-tauri/src/main.rs.bak b/src-tauri/src/main.rs.bak new file mode 100644 index 0000000..5763754 --- /dev/null +++ b/src-tauri/src/main.rs.bak @@ -0,0 +1,229 @@ +// at the top of main.rs - that will prevent the console from showing +#![windows_subsystem = "windows"] +extern crate image; +use tauri_utils::config::{Config, WindowConfig}; +use wry::{ + application::{ + event::{Event, StartCause, WindowEvent}, + event_loop::{ControlFlow, EventLoop}, + menu::MenuType, + window::{Fullscreen, Window, WindowBuilder}, + }, + webview::WebViewBuilder, +}; + +#[cfg(target_os = "macos")] +use wry::application::{ + accelerator::{Accelerator, SysMods}, + keyboard::KeyCode, + menu::{MenuBar as Menu, MenuItem, MenuItemAttributes}, + platform::macos::WindowBuilderExtMacOS, +}; + +#[cfg(target_os = "windows")] +use wry::application::window::Icon; + +#[cfg(any(target_os = "linux", target_os = "windows"))] +use wry::webview::WebContext; + +fn main() -> wry::Result<()> { + #[cfg(target_os = "macos")] + let (menu_bar_menu, close_item) = { + let mut menu_bar_menu = Menu::new(); + let mut first_menu = Menu::new(); + first_menu.add_native_item(MenuItem::Hide); + first_menu.add_native_item(MenuItem::EnterFullScreen); + first_menu.add_native_item(MenuItem::Minimize); + first_menu.add_native_item(MenuItem::Separator); + first_menu.add_native_item(MenuItem::Copy); + first_menu.add_native_item(MenuItem::Cut); + first_menu.add_native_item(MenuItem::Paste); + first_menu.add_native_item(MenuItem::Undo); + first_menu.add_native_item(MenuItem::Redo); + first_menu.add_native_item(MenuItem::SelectAll); + first_menu.add_native_item(MenuItem::Separator); + let close_item = first_menu.add_item( + MenuItemAttributes::new("CloseWindow") + .with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyW)), + ); + first_menu.add_native_item(MenuItem::Quit); + menu_bar_menu.add_submenu("App", true, first_menu); + (menu_bar_menu, close_item) + }; + + #[cfg(any(target_os = "linux", target_os = "windows"))] + let ( + package_name, + WindowConfig { + url, + width, + height, + resizable, + fullscreen, + .. + }, + ) = { + let (package_name, windows_config) = get_windows_config(); + ( + package_name + .expect("can't get package name in config file") + .to_lowercase(), + windows_config.unwrap_or_default(), + ) + }; + + #[cfg(target_os = "macos")] + let WindowConfig { + url, + width, + height, + resizable, + transparent, + fullscreen, + .. + } = get_windows_config().1.unwrap_or_default(); + let event_loop = EventLoop::new(); + + let common_window = WindowBuilder::new() + .with_title("") + .with_resizable(resizable) + .with_fullscreen(if fullscreen { + Some(Fullscreen::Borderless(None)) + } else { + None + }) + .with_inner_size(wry::application::dpi::LogicalSize::new(width, height)); + #[cfg(target_os = "windows")] + let window = { + let icon_path = format!("png/{}_32.ico", package_name); + let icon = load_icon(std::path::Path::new(&icon_path)); + common_window + .with_decorations(true) + .with_window_icon(Some(icon)) + .build(&event_loop) + .unwrap() + }; + + #[cfg(target_os = "linux")] + let window = common_window.build(&event_loop).unwrap(); + + #[cfg(target_os = "macos")] + let window = common_window + .with_fullsize_content_view(true) + .with_titlebar_buttons_hidden(false) + .with_titlebar_transparent(transparent) + .with_title_hidden(true) + .with_menu(menu_bar_menu) + .build(&event_loop) + .unwrap(); + + let handler = move |window: &Window, req: String| { + if req == "drag_window" { + let _ = window.drag_window(); + } else if req == "fullscreen" { + if window.fullscreen().is_some() { + window.set_fullscreen(None); + } else { + window.set_fullscreen(Some(Fullscreen::Borderless(None))); + } + } else if req.starts_with("open_browser") { + let href = req.replace("open_browser:", ""); + webbrowser::open(&href).expect("no browser"); + } + }; + + // 用于欺骗部分页面对于浏览器的强检测 + + #[cfg(target_os = "macos")] + let webview = { + let user_agent_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15"; + WebViewBuilder::new(window)? + .with_user_agent(user_agent_string) + .with_url(&url.to_string())? + .with_devtools(cfg!(feature = "devtools")) + .with_initialization_script(include_str!("pake.js")) + .with_ipc_handler(handler) + .with_back_forward_navigation_gestures(true) + .build()? + }; + + #[cfg(any(target_os = "linux", target_os = "windows"))] + let webview = { + let home_dir = match home::home_dir() { + Some(path1) => path1, + None => panic!("Error, can't found you home dir!!"), + }; + #[cfg(target_os = "windows")] + let data_dir = home_dir.join("AppData").join("Roaming").join(package_name); + #[cfg(target_os = "linux")] + let data_dir = home_dir.join(".config").join(package_name); + if !data_dir.exists() { + std::fs::create_dir(&data_dir) + .unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display())); + } + let mut web_content = WebContext::new(Some(data_dir)); + #[cfg(target_os = "windows")] + let user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"; + #[cfg(target_os = "linux")] + let user_agent_string = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"; + WebViewBuilder::new(window)? + .with_user_agent(user_agent_string) + .with_url(&url.to_string())? + .with_devtools(cfg!(feature = "devtools")) + .with_initialization_script(include_str!("pake.js")) + .with_ipc_handler(handler) + .with_web_context(&mut web_content) + .build()? + }; + #[cfg(feature = "devtools")] + { + webview.open_devtools(); + } + + event_loop.run(move |event, _, control_flow| { + *control_flow = ControlFlow::Wait; + match event { + Event::NewEvents(StartCause::Init) => println!("Wry has started!"), + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => *control_flow = ControlFlow::Exit, + Event::MenuEvent { + menu_id, + origin: MenuType::MenuBar, + .. + } => { + #[cfg(target_os = "macos")] + if menu_id == close_item.clone().id() { + webview.window().set_minimized(true); + } + println!("Clicked on {:?}", menu_id); + println!("Clicked on {:?}", webview.window().is_visible()); + } + _ => (), + } + }); +} + +fn get_windows_config() -> (Option, Option) { + let config_file = include_str!("../tauri.conf.json"); + let config: Config = serde_json::from_str(config_file).expect("failed to parse windows config"); + ( + config.package.product_name.clone(), + config.tauri.windows.first().cloned(), + ) +} + +#[cfg(target_os = "windows")] +fn load_icon(path: &std::path::Path) -> Icon { + let (icon_rgba, icon_width, icon_height) = { + // alternatively, you can embed the icon in the binary through `include_bytes!` macro and use `image::load_from_memory` + let image = image::open(path) + .expect("Failed to open icon path") + .into_rgba8(); + let (width, height) = image.dimensions(); + let rgba = image.into_raw(); + (rgba, width, height) + }; + Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon") +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index bd260ec..35ed045 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -4,21 +4,15 @@ "version": "1.0.0" }, "tauri": { - "windows": [ - { - "url": "https://weread.qq.com/", - "transparent": true, - "fullscreen": false, - "width": 1200, - "height": 780, - "resizable": true - } - ], "security": { "csp": null }, "updater": { "active": false + }, + "systemTray": { + "iconPath": "png/weread_512.png", + "iconAsTemplate": true } }, "build": {