chore(rust): resolve all clippy warnings across codebase
This commit is contained in:
1 parent
45962242aa
commit
a75e723416
6 files changed
+75
-105
No files matched your search
+18
-27
@@ -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"))]
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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
@@ -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(®_path) {
|
&& let Ok(content) = fs::read_to_string(®_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(®_path) {
|
&& let Ok(content) = fs::read_to_string(®_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"))
|
||||||
@@ -587,8 +579,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.
|
||||||
@@ -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
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in new issue
Block a user