chore(rust): resolve all clippy warnings across codebase

This commit is contained in:
HorizonCode committed 2026-11-01 12:14:23 +01:00
1 parent 45962242aa
commit a75e723416
6 files changed
+75 -105

No files matched your search

+18 -27
View File
@@ -90,7 +90,6 @@ pub fn file_size(path: String) -> Option<u64> {
pub fn get_hwid() -> String { pub fn get_hwid() -> String {
get_id() get_id()
.unwrap_or("recorderinsandybridge".to_string()) .unwrap_or("recorderinsandybridge".to_string())
.into()
} }
/// Show the native macOS picker, which can select `osu!.app` bundles as files. /// Show the native macOS picker, which can select `osu!.app` bundles as files.
@@ -374,8 +373,8 @@ pub async fn get_skins_count(folder: String) -> Option<u64> {
let mut count = 0; let mut count = 0;
if let Ok(mut entries) = fs::read_dir(skins_folder).await { if let Ok(mut entries) = fs::read_dir(skins_folder).await {
while let Ok(Some(entry)) = entries.next_entry().await { while let Ok(Some(entry)) = entries.next_entry().await {
if let Ok(ft) = entry.file_type().await { if let Ok(ft) = entry.file_type().await
if ft.is_dir() { && ft.is_dir() {
let dir_path = entry.path(); let dir_path = entry.path();
let has_ini = tokio::fs::try_exists(dir_path.join("skin.ini")) let has_ini = tokio::fs::try_exists(dir_path.join("skin.ini"))
.await .await
@@ -389,7 +388,6 @@ pub async fn get_skins_count(folder: String) -> Option<u64> {
} }
} }
} }
}
Some(count) Some(count)
} }
@@ -1596,8 +1594,8 @@ pub(crate) fn theme_root() -> Result<PathBuf, String> {
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
fn loopback_theme_asset_base() -> String { fn loopback_theme_asset_base() -> String {
if crate::theme_server::base_url().is_none() { if crate::theme_server::base_url().is_none()
if let Ok(root) = theme_root() { && let Ok(root) = theme_root() {
match crate::theme_server::media_root() { match crate::theme_server::media_root() {
Ok(media) => { Ok(media) => {
if let Err(error) = crate::theme_server::start(root, media) { if let Err(error) = crate::theme_server::start(root, media) {
@@ -1609,7 +1607,6 @@ fn loopback_theme_asset_base() -> String {
} }
} }
} }
}
crate::theme_server::base_url().unwrap_or_default() crate::theme_server::base_url().unwrap_or_default()
} }
@@ -1617,7 +1614,7 @@ fn loopback_theme_asset_base() -> String {
pub fn theme_asset_base() -> String { pub fn theme_asset_base() -> String {
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
{ {
return loopback_theme_asset_base(); loopback_theme_asset_base()
} }
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
@@ -1631,7 +1628,7 @@ pub fn theme_preview_url(path: String) -> Result<String, String> {
#[cfg(any(target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "linux", target_os = "macos"))]
{ {
let _ = loopback_theme_asset_base(); let _ = loopback_theme_asset_base();
return crate::theme_server::preview_url(Path::new(&path)); crate::theme_server::preview_url(Path::new(&path))
} }
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
@@ -1915,9 +1912,8 @@ async fn download_ffmpeg(app: &AppHandle) -> Result<PathBuf, String> {
.await .await
.map_err(|error| format!("Could not write the FFmpeg archive: {error}"))?; .map_err(|error| format!("Could not write the FFmpeg archive: {error}"))?;
if total > 0 { if let Some(percent) = (received.min(total) * 100).checked_div(total).map(|v| v as u8)
let percent = ((received.min(total) * 100) / total) as u8; && percent != last_percent {
if percent != last_percent {
last_percent = percent; last_percent = percent;
let _ = app.emit( let _ = app.emit(
"theme-media-progress", "theme-media-progress",
@@ -1928,7 +1924,6 @@ async fn download_ffmpeg(app: &AppHandle) -> Result<PathBuf, String> {
); );
} }
} }
}
file.flush() file.flush()
.await .await
@@ -2035,7 +2030,7 @@ fn optimize_theme_media_blocking(
let codec = probe_text.lines().find_map(|line| { let codec = probe_text.lines().find_map(|line| {
let index = line.find("Video: ")?; let index = line.find("Video: ")?;
line[index + 7..] line[index + 7..]
.split(|character: char| character == ',' || character == ' ') .split([',', ' '])
.next() .next()
.map(str::to_ascii_lowercase) .map(str::to_ascii_lowercase)
}); });
@@ -2518,7 +2513,7 @@ pub async fn list_theme_backups(theme_folder: String) -> Result<Vec<ThemeBackupI
.map_err(|error| format!("Failed to read theme backups: {error}"))? .map_err(|error| format!("Failed to read theme backups: {error}"))?
.filter_map(|entry| entry.ok()) .filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().map(|kind| kind.is_dir()).unwrap_or(false)) .filter(|entry| entry.file_type().map(|kind| kind.is_dir()).unwrap_or(false))
.filter_map(|entry| { .map(|entry| {
let path = entry.path(); let path = entry.path();
let created_at = entry let created_at = entry
.metadata() .metadata()
@@ -2527,16 +2522,16 @@ pub async fn list_theme_backups(theme_folder: String) -> Result<Vec<ThemeBackupI
.and_then(|time| time.duration_since(std::time::UNIX_EPOCH).ok()) .and_then(|time| time.duration_since(std::time::UNIX_EPOCH).ok())
.map(|duration| duration.as_millis() as u64) .map(|duration| duration.as_millis() as u64)
.unwrap_or(0); .unwrap_or(0);
Some(ThemeBackupInfo { ThemeBackupInfo {
label: entry.file_name().to_string_lossy().into_owned(), label: entry.file_name().to_string_lossy().into_owned(),
path: path.to_string_lossy().into_owned(), path: path.to_string_lossy().into_owned(),
created_at, created_at,
size: directory_size(&path), size: directory_size(&path),
}) }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
backups.sort_by(|a, b| b.created_at.cmp(&a.created_at)); backups.sort_by_key(|b| std::cmp::Reverse(b.created_at));
Ok(backups) Ok(backups)
}) })
.await .await
@@ -2699,13 +2694,11 @@ fn collect_theme_asset_refs(value: &Value, assets: &mut HashSet<String>) {
match value { match value {
Value::Object(object) => { Value::Object(object) => {
for (key, value) in object { for (key, value) in object {
if key == "src" || key == "preview" { if (key == "src" || key == "preview")
if let Some(src) = value.as_str() { && let Some(src) = value.as_str()
if let Some(path) = theme_asset_reference(src) { && let Some(path) = theme_asset_reference(src) {
assets.insert(path); assets.insert(path);
} }
}
}
collect_theme_asset_refs(value, assets); collect_theme_asset_refs(value, assets);
} }
} }
@@ -2816,14 +2809,13 @@ fn add_theme_folder_to_zip(
continue; continue;
} }
if let Some(filter) = asset_filter { if let Some(filter) = asset_filter
if let Ok(asset_path) = entry_path.strip_prefix(&assets_root) { && let Ok(asset_path) = entry_path.strip_prefix(&assets_root) {
let key = asset_path.to_string_lossy().replace('\\', "/"); let key = asset_path.to_string_lossy().replace('\\', "/");
if !filter.contains(&key) { if !filter.contains(&key) {
continue; continue;
} }
} }
}
let relative = entry_path let relative = entry_path
.strip_prefix(root) .strip_prefix(root)
@@ -2938,7 +2930,6 @@ pub async fn reveal_window(window: tauri::WebviewWindow) -> Result<(), String> {
{ {
let res = crate::macos::activate_and_focus_window(&win); let res = crate::macos::activate_and_focus_window(&win);
let _ = tx.send(res); let _ = tx.send(res);
return;
} }
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
+2 -3
View File
@@ -227,8 +227,8 @@ pub fn run() {
// The content view can be replaced again while the webview is being // The content view can be replaced again while the webview is being
// built, so re-apply the corner mask once the app is ready. // built, so re-apply the corner mask once the app is ready.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
if let tauri::RunEvent::Ready = &event { if let tauri::RunEvent::Ready = &event
if let Some(window) = app.get_webview_window("main") { && let Some(window) = app.get_webview_window("main") {
if let Err(error) = macos::round_window(&window, 12.0) { if let Err(error) = macos::round_window(&window, 12.0) {
log::warn!(target: "launcher", "Could not round the launcher window: {error}"); log::warn!(target: "launcher", "Could not round the launcher window: {error}");
} }
@@ -236,7 +236,6 @@ pub fn run() {
log::warn!(target: "launcher", "{error}"); log::warn!(target: "launcher", "{error}");
} }
} }
}
presence::handle_run_event(app, &event); presence::handle_run_event(app, &event);
}); });
+1 -1
View File
@@ -426,7 +426,7 @@ pub fn list_log_bundles() -> Result<Vec<LogBundleInfo>, String> {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
bundles.sort_by(|a, b| b.modified.cmp(&a.modified)); bundles.sort_by_key(|b| std::cmp::Reverse(b.modified));
Ok(bundles) Ok(bundles)
} }
+27 -43
View File
@@ -291,17 +291,15 @@ impl WineRuntime {
if let Ok(rel) = canon_path.strip_prefix(&canon_drive_c) { if let Ok(rel) = canon_path.strip_prefix(&canon_drive_c) {
return format!("C:\\{}", rel.display()).replace('/', "\\"); return format!("C:\\{}", rel.display()).replace('/', "\\");
} }
if let Ok(rel) = path.strip_prefix(&self.prefix.join("drive_c")) { if let Ok(rel) = path.strip_prefix(self.prefix.join("drive_c")) {
return format!("C:\\{}", rel.display()).replace('/', "\\"); return format!("C:\\{}", rel.display()).replace('/', "\\");
} }
if let Some(drive_c_ancestor) = canon_path if let Some(drive_c_ancestor) = canon_path
.ancestors() .ancestors()
.find(|a| a.file_name() == Some(OsStr::new("drive_c"))) .find(|a| a.file_name() == Some(OsStr::new("drive_c")))
{ && let Ok(rel) = canon_path.strip_prefix(drive_c_ancestor) {
if let Ok(rel) = canon_path.strip_prefix(drive_c_ancestor) {
return format!("C:\\{}", rel.display()).replace('/', "\\"); return format!("C:\\{}", rel.display()).replace('/', "\\");
} }
}
// If outside drive_c, Wine maps the Unix root filesystem to Z:\ // If outside drive_c, Wine maps the Unix root filesystem to Z:\
let path_display = canon_path.display().to_string(); let path_display = canon_path.display().to_string();
@@ -521,9 +519,9 @@ pub async fn prepare_osu_environment(folder: &Path, runtime: &WineRuntime) {
// 3. Reset update fail count in osu!.cfg // 3. Reset update fail count in osu!.cfg
let cfg_path = folder.join("osu!.cfg"); let cfg_path = folder.join("osu!.cfg");
if cfg_path.is_file() { if cfg_path.is_file()
if let Ok(content) = fs::read_to_string(&cfg_path) { && let Ok(content) = fs::read_to_string(&cfg_path)
if content.contains("_UpdateFailCount") { && content.contains("_UpdateFailCount") {
let updated = content let updated = content
.lines() .lines()
.map(|line| { .map(|line| {
@@ -537,42 +535,36 @@ pub async fn prepare_osu_environment(folder: &Path, runtime: &WineRuntime) {
.join("\n"); .join("\n");
let _ = fs::write(&cfg_path, updated); let _ = fs::write(&cfg_path, updated);
} }
}
}
// 4. Update execute.bat if present to use ez-pp.farm // 4. Update execute.bat if present to use ez-pp.farm
let bat_path = folder.join("execute.bat"); let bat_path = folder.join("execute.bat");
if bat_path.is_file() { if bat_path.is_file()
if let Ok(content) = fs::read_to_string(&bat_path) { && let Ok(content) = fs::read_to_string(&bat_path)
if content.contains("lucoa.best") { && content.contains("lucoa.best") {
let updated = content.replace("lucoa.best", "ez-pp.farm"); let updated = content.replace("lucoa.best", "ez-pp.farm");
let _ = fs::write(&bat_path, updated); let _ = fs::write(&bat_path, updated);
} }
} }
}
}
async fn clean_wine_font_registry(runtime: &WineRuntime) { async fn clean_wine_font_registry(runtime: &WineRuntime) {
let mut needs_clean = false; let mut needs_clean = false;
for reg_name in &["user.reg", "system.reg"] { for reg_name in &["user.reg", "system.reg"] {
let reg_path = runtime.prefix.join(reg_name); let reg_path = runtime.prefix.join(reg_name);
if reg_path.is_file() { if reg_path.is_file()
if let Ok(content) = fs::read_to_string(&reg_path) { && let Ok(content) = fs::read_to_string(&reg_path)
if content.contains("Apple Braille") { && content.contains("Apple Braille") {
needs_clean = true; needs_clean = true;
break; break;
} }
} }
}
}
if needs_clean { if needs_clean {
runtime.kill_prefix().await; runtime.kill_prefix().await;
for reg_name in &["user.reg", "system.reg"] { for reg_name in &["user.reg", "system.reg"] {
let reg_path = runtime.prefix.join(reg_name); let reg_path = runtime.prefix.join(reg_name);
if reg_path.is_file() { if reg_path.is_file()
if let Ok(content) = fs::read_to_string(&reg_path) { && let Ok(content) = fs::read_to_string(&reg_path)
if content.contains("Apple Braille") { && content.contains("Apple Braille") {
let cleaned: String = content let cleaned: String = content
.lines() .lines()
.filter(|line| !line.contains("Apple Braille")) .filter(|line| !line.contains("Apple Braille"))
@@ -588,8 +580,6 @@ async fn clean_wine_font_registry(runtime: &WineRuntime) {
} }
} }
} }
}
}
/// Run osu! (`-devserver ez-pp.farm`) and wait until the game exits. /// Run osu! (`-devserver ez-pp.farm`) and wait until the game exits.
pub async fn run_osu(osu_folder: &str, patch: bool) -> Result<(), String> { pub async fn run_osu(osu_folder: &str, patch: bool) -> Result<(), String> {
@@ -660,8 +650,8 @@ pub async fn run_osu(osu_folder: &str, patch: bool) -> Result<(), String> {
let start_time = Instant::now(); let start_time = Instant::now();
let mut wait_result = game.wait().await; let mut wait_result = game.wait().await;
if let Ok(status) = &wait_result { if let Ok(status) = &wait_result
if status.code() == Some(5) && start_time.elapsed() < StdDuration::from_secs(6) { && status.code() == Some(5) && start_time.elapsed() < StdDuration::from_secs(6) {
log::warn!( log::warn!(
target: "osu", target: "osu",
"osu! exited early with status 5 during Wine cold start; retrying now that Wine runtime is initialized..." "osu! exited early with status 5 during Wine cold start; retrying now that Wine runtime is initialized..."
@@ -683,7 +673,6 @@ pub async fn run_osu(osu_folder: &str, patch: bool) -> Result<(), String> {
wait_result = retry_game.wait().await; wait_result = retry_game.wait().await;
} }
}
match &wait_result { match &wait_result {
Ok(status) => log::info!(target: "osu", "osu! loader exited with {status}"), Ok(status) => log::info!(target: "osu", "osu! loader exited with {status}"),
@@ -836,7 +825,7 @@ async fn wait_for_osu_game() -> bool {
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true); sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
for (_pid, process) in sys.processes() { for process in sys.processes().values() {
if crate::utils::is_osu_process(process) || process.name() == "osu!.exe" { if crate::utils::is_osu_process(process) || process.name() == "osu!.exe" {
let pid = process.pid(); let pid = process.pid();
let title = crate::utils::get_window_title_by_pid(pid); let title = crate::utils::get_window_title_by_pid(pid);
@@ -932,17 +921,15 @@ pub fn resolve_osu_folder(folder: &Path) -> Option<PathBuf> {
let mut prefixes = Vec::new(); let mut prefixes = Vec::new();
if folder.file_name() == Some(OsStr::new("drive_c")) { if folder.file_name() == Some(OsStr::new("drive_c"))
if let Some(parent) = canonical_prefix(folder) { && let Some(parent) = canonical_prefix(folder) {
prefixes.push(parent); prefixes.push(parent);
} }
}
if folder.join("drive_c").is_dir() { if folder.join("drive_c").is_dir()
if let Some(parent) = canonical_prefix(&folder.join("drive_c")) { && let Some(parent) = canonical_prefix(&folder.join("drive_c")) {
prefixes.push(parent); prefixes.push(parent);
} }
}
if folder.extension() == Some(OsStr::new("app")) || folder.join("Contents").is_dir() { if folder.extension() == Some(OsStr::new("app")) || folder.join("Contents").is_dir() {
for drive_c in [ for drive_c in [
@@ -950,12 +937,11 @@ pub fn resolve_osu_folder(folder: &Path) -> Option<PathBuf> {
folder.join("Contents/SharedSupport/drive_c"), folder.join("Contents/SharedSupport/drive_c"),
folder.join("Contents/SharedSupport/prefix/drive_c"), folder.join("Contents/SharedSupport/prefix/drive_c"),
] { ] {
if drive_c.is_dir() { if drive_c.is_dir()
if let Some(parent) = canonical_prefix(&drive_c) { && let Some(parent) = canonical_prefix(&drive_c) {
prefixes.push(parent); prefixes.push(parent);
} }
} }
}
let mut drive_dirs = Vec::new(); let mut drive_dirs = Vec::new();
find_drive_c_dirs(folder, 5, &mut drive_dirs); find_drive_c_dirs(folder, 5, &mut drive_dirs);
@@ -1093,11 +1079,10 @@ fn find_drive_c_dirs(dir: &Path, depth: usize, out: &mut Vec<PathBuf>) {
// Wineskin wrappers often add a convenience drive_c symlink at // Wineskin wrappers often add a convenience drive_c symlink at
// the app root. Resolve it to the real prefix so WINEPREFIX points // the app root. Resolve it to the real prefix so WINEPREFIX points
// at Contents/Resources instead of the bundle itself. // at Contents/Resources instead of the bundle itself.
if path.file_name() == Some(OsStr::new("drive_c")) { if path.file_name() == Some(OsStr::new("drive_c"))
if let Ok(canonical) = fs::canonicalize(&path) { && let Ok(canonical) = fs::canonicalize(&path) {
out.push(canonical); out.push(canonical);
} }
}
continue; continue;
} }
@@ -1246,13 +1231,12 @@ fn find_wine_bin(prefix: &Path, app: Option<&Path>) -> Option<(PathBuf, Option<P
} }
for binary in ["wine64", "wine32on64", "wine"] { for binary in ["wine64", "wine32on64", "wine"] {
if let Some(path) = find_in_path(binary) { if let Some(path) = find_in_path(binary)
if let Some(bin) = path.parent() { && let Some(bin) = path.parent() {
candidates.push((bin.to_path_buf(), None)); candidates.push((bin.to_path_buf(), None));
break; break;
} }
} }
}
candidates.into_iter().find(|(bin, _)| has_wine_loader(bin)) candidates.into_iter().find(|(bin, _)| has_wine_loader(bin))
} }
+15 -16
View File
@@ -53,12 +53,12 @@ impl Default for PresenceData {
enum PresenceCommand { enum PresenceCommand {
Connect(oneshot::Sender<bool>), Connect(oneshot::Sender<bool>),
Disconnect(oneshot::Sender<()>), Disconnect(oneshot::Sender<()>),
UpdateData(PresenceData), UpdateData(Box<PresenceData>),
IsConnected(oneshot::Sender<bool>), IsConnected(oneshot::Sender<bool>),
} }
enum ReconnectResult { enum ReconnectResult {
Connected(AsyncDiscordIpcClient), Connected(Box<AsyncDiscordIpcClient>),
Failed, Failed,
} }
@@ -103,7 +103,7 @@ impl PresenceActor {
PresenceCommand::Connect(resp) => self.cmd_connect(resp).await, PresenceCommand::Connect(resp) => self.cmd_connect(resp).await,
PresenceCommand::Disconnect(resp) => self.cmd_disconnect(resp).await, PresenceCommand::Disconnect(resp) => self.cmd_disconnect(resp).await,
PresenceCommand::UpdateData(data) => { PresenceCommand::UpdateData(data) => {
self.data = data; self.data = *data;
self.push_presence().await; self.push_presence().await;
} }
PresenceCommand::IsConnected(resp) => { PresenceCommand::IsConnected(resp) => {
@@ -117,7 +117,7 @@ impl PresenceActor {
match result { match result {
ReconnectResult::Connected(client) => { ReconnectResult::Connected(client) => {
log::info!(target: "launcher", "Presence: reconnect succeeded"); log::info!(target: "launcher", "Presence: reconnect succeeded");
self.client = Some(client); self.client = Some(*client);
self.push_presence().await; self.push_presence().await;
} }
ReconnectResult::Failed => { ReconnectResult::Failed => {
@@ -188,16 +188,14 @@ impl PresenceActor {
builder = builder.small_text(text); builder = builder.small_text(text);
} }
if let Some(btn) = &self.data.dynamic_button { if let Some(btn) = &self.data.dynamic_button
if !btn.label.trim().is_empty() && !btn.url.trim().is_empty() { && !btn.label.trim().is_empty() && !btn.url.trim().is_empty() {
builder = builder.button(&btn.label, &btn.url); builder = builder.button(&btn.label, &btn.url);
} }
} if let Some(btn2) = &self.data.secondary_button
if let Some(btn2) = &self.data.secondary_button { && !btn2.label.trim().is_empty() && !btn2.url.trim().is_empty() {
if !btn2.label.trim().is_empty() && !btn2.url.trim().is_empty() {
builder = builder.button(&btn2.label, &btn2.url); builder = builder.button(&btn2.label, &btn2.url);
} }
}
let activity = builder.build(); let activity = builder.build();
@@ -233,7 +231,7 @@ impl PresenceActor {
tokio::time::sleep(delay).await; tokio::time::sleep(delay).await;
if let Some(client) = try_connect_once().await { if let Some(client) = try_connect_once().await {
let _ = tx.send(ReconnectResult::Connected(client)).await; let _ = tx.send(ReconnectResult::Connected(Box::new(client))).await;
return; return;
} }
} }
@@ -302,6 +300,7 @@ pub async fn has_presence() -> bool {
false false
} }
#[allow(clippy::too_many_arguments)]
pub fn update_activity( pub fn update_activity(
state: Option<&str>, state: Option<&str>,
details: Option<&str>, details: Option<&str>,
@@ -347,7 +346,7 @@ pub fn update_activity(
let tx = PRESENCE_TX.clone(); let tx = PRESENCE_TX.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await; let _ = tx.send(PresenceCommand::UpdateData(Box::new(data))).await;
}); });
} }
@@ -368,7 +367,7 @@ pub fn update_status(state: Option<&str>, details: Option<&str>, large_image_key
let tx = PRESENCE_TX.clone(); let tx = PRESENCE_TX.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await; let _ = tx.send(PresenceCommand::UpdateData(Box::new(data))).await;
}); });
} }
@@ -382,7 +381,7 @@ pub fn update_user(username: Option<&str>, id: Option<&str>) {
let tx = PRESENCE_TX.clone(); let tx = PRESENCE_TX.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await; let _ = tx.send(PresenceCommand::UpdateData(Box::new(data))).await;
}); });
} }
@@ -398,7 +397,7 @@ pub fn set_button(label: &str, url: &str) {
let tx = PRESENCE_TX.clone(); let tx = PRESENCE_TX.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await; let _ = tx.send(PresenceCommand::UpdateData(Box::new(data))).await;
}); });
} }
@@ -411,7 +410,7 @@ pub fn clear_button() {
let tx = PRESENCE_TX.clone(); let tx = PRESENCE_TX.clone();
tokio::spawn(async move { tokio::spawn(async move {
let _ = tx.send(PresenceCommand::UpdateData(data)).await; let _ = tx.send(PresenceCommand::UpdateData(Box::new(data))).await;
}); });
} }
+12 -15
View File
@@ -40,15 +40,14 @@ pub fn is_osu_process(process: &sysinfo::Process) -> bool {
return true; return true;
} }
if let Some(exe) = process.exe() { if let Some(exe) = process.exe()
if exe && exe
.file_name() .file_name()
.map(|file_name| file_name.to_string_lossy().to_ascii_lowercase() == "osu!.exe") .map(|file_name| file_name.to_string_lossy().to_ascii_lowercase() == "osu!.exe")
.unwrap_or(false) .unwrap_or(false)
{ {
return true; return true;
} }
}
process.cmd().iter().any(|arg| { process.cmd().iter().any(|arg| {
arg.to_string_lossy() arg.to_string_lossy()
@@ -103,7 +102,7 @@ fn find_osu_user_config_path<P: AsRef<Path>>(folder_path: P) -> Option<PathBuf>
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
candidates.sort_by(|a, b| b.0.cmp(&a.0)); candidates.sort_by_key(|b| std::cmp::Reverse(b.0));
candidates.into_iter().next().map(|(_, path)| path) candidates.into_iter().next().map(|(_, path)| path)
} }
@@ -261,7 +260,7 @@ pub fn get_osu_config<P: AsRef<Path>>(
} }
} }
return Some(config_map); Some(config_map)
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@@ -469,7 +468,7 @@ pub fn get_window_title_by_pid(target_pid: Pid) -> String {
} else { } else {
0 0
}; };
if layer < 0 || layer > 50 { if !(0..=50).contains(&layer) {
continue; continue;
} }
@@ -477,8 +476,8 @@ pub fn get_window_title_by_pid(target_pid: Pid) -> String {
let name_str: *mut AnyObject = msg_send![dict, objectForKey: name_key]; let name_str: *mut AnyObject = msg_send![dict, objectForKey: name_key];
if !name_str.is_null() { if !name_str.is_null() {
let utf8: *const std::ffi::c_char = msg_send![name_str, UTF8String]; let utf8: *const std::ffi::c_char = msg_send![name_str, UTF8String];
if !utf8.is_null() { if !utf8.is_null()
if let Ok(s) = CStr::from_ptr(utf8).to_str() { && let Ok(s) = CStr::from_ptr(utf8).to_str() {
let trimmed = s.trim(); let trimmed = s.trim();
if !trimmed.is_empty() { if !trimmed.is_empty() {
if trimmed.to_lowercase().contains("updater") { if trimmed.to_lowercase().contains("updater") {
@@ -490,7 +489,6 @@ pub fn get_window_title_by_pid(target_pid: Pid) -> String {
} }
} }
} }
}
// 2. Check window bounds // 2. Check window bounds
let bounds_dict: *mut AnyObject = msg_send![dict, objectForKey: bounds_key]; let bounds_dict: *mut AnyObject = msg_send![dict, objectForKey: bounds_key];
@@ -723,6 +721,7 @@ pub fn is_compatible_patcher(data: &[u8]) -> bool {
/// 2. `GetOsuPid()` checks for `" -devserver "` via PEB reading, which fails or is unreliable under Wine. /// 2. `GetOsuPid()` checks for `" -devserver "` via PEB reading, which fails or is unreliable under Wine.
/// 3. Costura embeds `ManagedInjector.Lib` which also calls generic `Marshal.SizeOf<Native.ModuleEntry32>()` /// 3. Costura embeds `ManagedInjector.Lib` which also calls generic `Marshal.SizeOf<Native.ModuleEntry32>()`
/// and parses remote PE export tables through generic marshal APIs. /// and parses remote PE export tables through generic marshal APIs.
///
/// This function patches the binary in-place so it runs reliably under Wine. /// This function patches the binary in-place so it runs reliably under Wine.
pub fn ensure_patcher_compatibility(patcher_exe: &Path) -> Result<bool, String> { pub fn ensure_patcher_compatibility(patcher_exe: &Path) -> Result<bool, String> {
if !patcher_exe.is_file() { if !patcher_exe.is_file() {
@@ -828,9 +827,9 @@ pub fn ensure_patcher_compatibility(patcher_exe: &Path) -> Result<bool, String>
if inner_modified { if inner_modified {
let mut encoder = DeflateEncoder::new(Vec::new(), Compression::best()); let mut encoder = DeflateEncoder::new(Vec::new(), Compression::best());
if encoder.write_all(&decomp).is_ok() { if encoder.write_all(&decomp).is_ok()
if let Ok(mut compressed) = encoder.finish() { && let Ok(mut compressed) = encoder.finish()
if compressed.len() <= 10020 - 5 { && compressed.len() <= 10020 - 5 {
let remaining = 10020 - compressed.len(); let remaining = 10020 - compressed.len();
let length = (remaining - 5) as u16; let length = (remaining - 5) as u16;
let nlen = !length; let nlen = !length;
@@ -839,7 +838,7 @@ pub fn ensure_patcher_compatibility(patcher_exe: &Path) -> Result<bool, String>
compressed.push((length >> 8) as u8); compressed.push((length >> 8) as u8);
compressed.push((nlen & 0xff) as u8); compressed.push((nlen & 0xff) as u8);
compressed.push((nlen >> 8) as u8); compressed.push((nlen >> 8) as u8);
compressed.extend(std::iter::repeat(0x00).take(length as usize)); compressed.extend(std::iter::repeat_n(0x00, length as usize));
if compressed.len() == 10020 { if compressed.len() == 10020 {
data[0x1f00..0x1f00 + 10020].copy_from_slice(&compressed); data[0x1f00..0x1f00 + 10020].copy_from_slice(&compressed);
modified = true; modified = true;
@@ -848,8 +847,6 @@ pub fn ensure_patcher_compatibility(patcher_exe: &Path) -> Result<bool, String>
} }
} }
} }
}
}
if modified { if modified {
fs::write(patcher_exe, &data) fs::write(patcher_exe, &data)