This commit is contained in:
HorizonCode committed 2026-05-22 08:18:54 +02:00
commit e84feb292b
19 files changed
+790 -520

No files matched your search

+562 -170
View File
File diff suppressed because it is too large. Load diff
+12 -12
View File
@@ -25,29 +25,29 @@ name = "ezpplauncher_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.5.6", features = [] }
tauri-build = { version = "2.6.2", features = [] }
[dependencies]
tauri = { version = "2.10.3", features = ["protocol-asset"] }
tauri = { version = "2.11.2", features = ["protocol-asset"] }
tauri-plugin-shell = "2.3.5"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
serde_json = "1.0.150"
serde_repr = "0.1.20"
tauri-plugin-dialog = "2.7.0"
tauri-plugin-fs = "2.5.0"
tauri-plugin-dialog = "2.7.1"
tauri-plugin-fs = "2.5.1"
hardware-id = "0.3.0"
tauri-plugin-cors-fetch = "5.0.0"
sysinfo = "0.38.4"
reqwest = { version = "0.13.2", features = ["json", "stream", "query"] }
sysinfo = "0.39.2"
reqwest = { version = "0.13.3", features = ["json", "stream", "query"] }
md5 = "0.8.0"
tokio = { version = "1.52.1", features = ["full"] }
open = "5.3.4"
discord-rich-presence = "1.1.0"
tokio = { version = "1.52.2", features = ["full"] }
open = "5.3.5"
presenceforge = { version = "0.2.1", features = ["tokio-runtime"] }
once_cell = "1.21.4"
futures-util = "0.3.32"
byteorder = "1.5.0"
anyhow = "1.0.102"
url = "2"
url = "2.5.8"
[target.'cfg(windows)'.dependencies]
winreg = "0.56.0"
@@ -57,5 +57,5 @@ widestring = "1.2.1"
windows-sys = "0.61.2"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-single-instance = "2.4.1"
tauri-plugin-single-instance = "2.4.2"
+1 -1
View File
@@ -881,7 +881,7 @@ pub struct PresenceButton {
pub async fn presence_update_button(button: PresenceButton) {
match (button.text.as_deref(), button.url.as_deref()) {
(Some(text), Some(url)) => presence::set_button(text, url),
_ => presence::clear_button(),
_ =>presence::clear_button()
}
}
+4 -8
View File
@@ -15,7 +15,7 @@ use crate::commands::{
get_osu_skin, get_osu_version, get_platform, get_skins, get_skins_count, has_net8,
has_osuwinello, has_wmctrl, install_ezpp_launcher_update, is_osu_running, open_url_in_browser,
opened_urls, presence_connect, presence_disconnect, presence_is_connected,
presence_update_status, presence_update_user, replace_ui_files, run_osu, run_osu_updater,
presence_update_status, presence_update_user, presence_update_button, replace_ui_files, run_osu, run_osu_updater,
set_osu_config_values, set_osu_user_config_values, valid_osu_folder,
};
@@ -108,6 +108,7 @@ pub fn run() {
presence_disconnect,
presence_update_status,
presence_update_user,
presence_update_button,
presence_is_connected,
has_osuwinello,
has_wmctrl,
@@ -123,12 +124,7 @@ pub fn run() {
.build(tauri::generate_context!())
.expect("error while building tauri application");
app.run(|_app_handle, event| {
if let tauri::RunEvent::ExitRequested { api, .. } = event {
api.prevent_exit();
tauri::async_runtime::block_on(presence::disconnect());
std::process::exit(0);
}
app.run(|app, event| {
presence::handle_run_event(app, &event);
});
}
+67 -50
View File
@@ -1,10 +1,8 @@
use discord_rich_presence::{
DiscordIpc, DiscordIpcClient,
activity::{Activity, Assets, Button, Timestamps},
};
use once_cell::sync::Lazy;
use presenceforge::{ActivityBuilder, AsyncDiscordIpcClient};
use std::sync::Mutex as StdMutex;
use std::time::{SystemTime, UNIX_EPOCH};
use tauri::{AppHandle, RunEvent};
use tokio::sync::{mpsc, oneshot};
use tokio::time::{Duration, interval};
@@ -48,7 +46,7 @@ enum PresenceCommand {
}
enum ReconnectResult {
Connected(DiscordIpcClient),
Connected(AsyncDiscordIpcClient),
Failed,
}
@@ -56,7 +54,7 @@ struct PresenceActor {
receiver: mpsc::Receiver<PresenceCommand>,
reconnect_rx: mpsc::Receiver<ReconnectResult>,
reconnect_tx: mpsc::Sender<ReconnectResult>,
client: Option<DiscordIpcClient>,
client: Option<AsyncDiscordIpcClient>,
data: PresenceData,
start_timestamp: i64,
reconnecting: bool,
@@ -129,7 +127,7 @@ impl PresenceActor {
return;
}
match try_connect_once() {
match try_connect_once().await {
Some(client) => {
self.client = Some(client);
self.reconnecting = false;
@@ -146,8 +144,7 @@ impl PresenceActor {
async fn cmd_disconnect(&mut self, resp: oneshot::Sender<()>) {
if let Some(mut client) = self.client.take() {
let _ = client.clear_activity();
let _ = client.close();
let _ = client.clear_activity().await;
println!("Presence: disconnected.");
}
let _ = resp.send(());
@@ -159,37 +156,34 @@ impl PresenceActor {
None => return,
};
let mut assets = Assets::new()
let mut builder = ActivityBuilder::new()
.state(&self.data.state)
.details(&self.data.details)
.start_timestamp(self.start_timestamp as u64)
.large_image(&self.data.large_image_key)
.large_text(&self.data.large_image_text);
if let Some(key) = &self.data.small_image_key {
assets = assets.small_image(key);
builder = builder.small_image(key);
}
if let Some(text) = &self.data.small_image_text {
assets = assets.small_text(text);
builder = builder.small_text(text);
}
let buttons = if let Some(btn) = &self.data.dynamic_button {
vec![
Button::new(&btn.label, &btn.url),
Button::new("Join EZPPFarm", "https://ez-pp.farm/discord"),
]
if let Some(btn) = &self.data.dynamic_button {
builder = builder.button(&btn.label, &btn.url);
} else {
vec![
Button::new("Download the Launcher", "https://git.ez-pp.farm/EZPPFarm/EZPPLauncher/releases/latest"),
Button::new("Join EZPPFarm", "https://ez-pp.farm/discord"),
]
};
builder = builder.button(
"Download the Launcher",
"https://git.ez-pp.farm/EZPPFarm/EZPPLauncher/releases/latest",
);
}
builder = builder.button("Join EZPPFarm", "https://ez-pp.farm/discord");
let activity = Activity::new()
.state(&self.data.state)
.details(&self.data.details)
.timestamps(Timestamps::new().start(self.start_timestamp))
.assets(assets)
.buttons(buttons);
let activity = builder.build();
if let Err(e) = client.set_activity(activity) {
/* println!("Presence: updating activity: {:?}", activity); */
if let Err(e) = client.set_activity(&activity).await {
eprintln!("Presence: set_activity failed ({:?}); will reconnect.", e);
self.client = None;
self.spawn_reconnect_task();
@@ -213,7 +207,7 @@ impl PresenceActor {
);
tokio::time::sleep(delay).await;
if let Some(client) = try_connect_once() {
if let Some(client) = try_connect_once().await {
let _ = tx.send(ReconnectResult::Connected(client)).await;
return;
}
@@ -223,15 +217,20 @@ impl PresenceActor {
}
}
fn try_connect_once() -> Option<DiscordIpcClient> {
let mut client = DiscordIpcClient::new("1032772293220384808");
match client.connect() {
Ok(()) => {
println!("Presence: IPC connected.");
Some(client)
}
async fn try_connect_once() -> Option<AsyncDiscordIpcClient> {
match AsyncDiscordIpcClient::new("1032772293220384808").await {
Ok(mut client) => match client.connect().await {
Ok(_) => {
println!("Presence: IPC connected.");
Some(client)
}
Err(e) => {
eprintln!("Presence: IPC connect error: {:?}", e);
None
}
},
Err(e) => {
eprintln!("Presence: IPC connect error: {:?}", e);
eprintln!("Presence: failed to create client: {:?}", e);
None
}
}
@@ -295,6 +294,20 @@ pub fn update_status(state: Option<&str>, details: Option<&str>, large_image_key
});
}
pub fn update_user(username: Option<&str>, id: Option<&str>) {
let data = {
let mut guard = PRESENCE_DATA.lock().unwrap();
guard.small_image_key = id.map(|s| format!("https://a.ez-pp.farm/{}", s));
guard.small_image_text = username.map(str::to_string);
guard.clone()
};
let tx = PRESENCE_TX.clone();
tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
});
}
pub fn set_button(label: &str, url: &str) {
let data = {
let mut guard = PRESENCE_DATA.lock().unwrap();
@@ -324,16 +337,20 @@ pub fn clear_button() {
});
}
pub fn update_user(username: Option<&str>, id: Option<&str>) {
let data = {
let mut guard = PRESENCE_DATA.lock().unwrap();
guard.small_image_key = id.map(|s| format!("https://a.ez-pp.farm/{}", s));
guard.small_image_text = username.map(str::to_string);
guard.clone()
};
let tx = PRESENCE_TX.clone();
tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await;
});
/// Register a Tauri event handler that cleanly disconnects presence when the
/// application exits. Call this once in your main.rs `tauri::Builder` run callback:
///
/// ```rust
/// .build(tauri::generate_context!())
/// .expect("error building app")
/// .run(|app, event| {
/// presence::handle_run_event(app, &event);
/// });
/// ```
pub fn handle_run_event(_app: &AppHandle, event: &RunEvent) {
if let RunEvent::ExitRequested { .. } | RunEvent::Exit = event {
tauri::async_runtime::block_on(async {
disconnect().await;
});
}
}