diff --git a/.gitignore b/.gitignore index a896b5c..4183e73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # custom .env +app/data.json # ---> Rust # Generated by Cargo diff --git a/app/Cargo.toml b/app/Cargo.toml index ec091d5..54f413a 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -1,11 +1,15 @@ [package] name = "DiscordRPC-HDRezcord-APP" -version = "0.1.0" +version = "0.1.2" edition = "2021" [dependencies] actix-web = "4" +image = "0.25.5" +open = "5.3.2" rust-discord-rpc = { git = "https://git.amok.dev/AmokDev/rust-discord-rpc", version = "0.3.3" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } +tray-icon = "0.20.0" +winit = "0.30.9" diff --git a/app/data.json b/app/data.json index e4c916b..40c9bc5 100644 --- a/app/data.json +++ b/app/data.json @@ -1 +1 @@ -{"episode":0,"season":0,"timestamps":[0, 0],"name":"name","image_url":"image_url"} \ No newline at end of file +{"episode":0,"season":0,"timestamps":[1,1],"name":"Полетта","image_url":"https://statichdrezka.ac/i/2014/1/25/ze3dffce6f572bx77h96o.jpg"} \ No newline at end of file diff --git a/app/src/icons/32.ico b/app/src/icons/32.ico new file mode 100644 index 0000000..a188638 Binary files /dev/null and b/app/src/icons/32.ico differ diff --git a/app/src/main.rs b/app/src/main.rs index 1c1dbd6..dc1d315 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -1,12 +1,18 @@ +#![windows_subsystem = "windows"] + mod network; mod discord; mod utils; use network::api::start_api; use discord::rpc::start_presence; +use utils::tray::init_tray; #[actix_web::main] async fn main() -> std::io::Result<()> { + std::thread::spawn(|| { + init_tray(); + }); let _ = tokio::join!(start_api(), start_presence()); Ok(()) } diff --git a/app/src/network/api.rs b/app/src/network/api.rs index 4eed9c1..cfde47c 100644 --- a/app/src/network/api.rs +++ b/app/src/network/api.rs @@ -3,7 +3,7 @@ use crate::utils::json_database::{save_to_json, PostData}; #[post("/set_presence")] async fn set_presence(data: web::Json) -> HttpResponse { - // println!("{:?}", data); + println!("{:?}", data); let _ = save_to_json(&data); HttpResponse::Ok().finish() } diff --git a/app/src/utils/mod.rs b/app/src/utils/mod.rs index 00db1b7..c259277 100644 --- a/app/src/utils/mod.rs +++ b/app/src/utils/mod.rs @@ -1 +1,2 @@ -pub mod json_database; \ No newline at end of file +pub mod json_database; +pub mod tray; \ No newline at end of file diff --git a/app/src/utils/tray.rs b/app/src/utils/tray.rs new file mode 100644 index 0000000..5fcf634 --- /dev/null +++ b/app/src/utils/tray.rs @@ -0,0 +1,112 @@ +use tray_icon::{ + menu::{Menu, MenuEvent, MenuId, MenuItem}, + TrayIcon, TrayIconBuilder, TrayIconEvent, +}; +use winit::{ + application::ApplicationHandler, + event_loop::EventLoop, platform::windows::EventLoopBuilderExtWindows, +}; +use std::process; + +#[derive(Debug)] +enum UserEvent { + MenuEvent(tray_icon::menu::MenuEvent), +} + +struct Application { + tray_icon: Option, +} + +impl Application { + fn new() -> Application { + Application { tray_icon: None } + } + + fn new_tray_icon() -> TrayIcon { + let path = concat!(env!("CARGO_MANIFEST_DIR"), "/src/icons/32.ico"); + let icon = load_icon(std::path::Path::new(path)); + + TrayIconBuilder::new() + .with_menu(Box::new(Self::new_tray_menu())) + .with_tooltip("HDRezcord") + .with_icon(icon) + .build() + .unwrap() + } + + fn new_tray_menu() -> Menu { + let menu = Menu::new(); + let _ = menu.append(&MenuItem::new("GitHub", true, None)); + let _ = menu.append(&MenuItem::new("Exit", true, None)); + menu + } +} + +impl ApplicationHandler for Application { + fn resumed(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {} + + fn window_event( + &mut self, + _event_loop: &winit::event_loop::ActiveEventLoop, + _window_id: winit::window::WindowId, + _event: winit::event::WindowEvent, + ) { + } + + fn new_events( + &mut self, + _event_loop: &winit::event_loop::ActiveEventLoop, + cause: winit::event::StartCause, + ) { + if winit::event::StartCause::Init == cause { + #[cfg(not(target_os = "linux"))] + { + self.tray_icon = Some(Self::new_tray_icon()); + } + } + } + + fn user_event(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) { + // println!("{event:?}"); + match event { + UserEvent::MenuEvent(menu_event) => { + // println!("{:?}", menu_event.id); + if menu_event.id == MenuId("1001".to_string()) { + let _ = open::that("https://git.amok.dev/AmokDev/HDRezcord"); + } else if menu_event.id == MenuId("1002".to_string()) { + process::exit(0); + } + } + } + } +} + +pub fn init_tray() { + let event_loop = EventLoop::::with_user_event().with_any_thread(true).build().unwrap(); + + let proxy = event_loop.create_proxy(); + MenuEvent::set_event_handler(Some(move |event| { + let _ = proxy.send_event(UserEvent::MenuEvent(event)); + })); + + let mut app = Application::new(); + + let _menu_channel = MenuEvent::receiver(); + let _tray_channel = TrayIconEvent::receiver(); + + if let Err(err) = event_loop.run_app(&mut app) { + println!("Error: {:?}", err); + } +} + +fn load_icon(path: &std::path::Path) -> tray_icon::Icon { + let (icon_rgba, icon_width, icon_height) = { + 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) + }; + tray_icon::Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon") +} \ No newline at end of file