diff --git a/src/bin/scythe-ui.rs b/src/bin/scythe-ui.rs index b273527..49d5e64 100644 --- a/src/bin/scythe-ui.rs +++ b/src/bin/scythe-ui.rs @@ -91,17 +91,15 @@ fn get_ui_cmd() -> std::process::Command { fn check_and_toggle_overlay() -> bool { let pid_path = scythe::ipc::get_overlay_pid_path(); if pid_path.exists() { - if let Ok(metadata) = std::fs::metadata(&pid_path) { - if let Ok(modified) = metadata.modified() { - if let Ok(elapsed) = modified.elapsed() { + if let Ok(metadata) = std::fs::metadata(&pid_path) + && let Ok(modified) = metadata.modified() + && let Ok(elapsed) = modified.elapsed() { // Debounce: if the overlay was spawned less than 400ms ago, this is a // duplicate event from concurrent triggers. Do not kill it; simply exit. if elapsed < std::time::Duration::from_millis(400) { return true; } } - } - } if let Ok(content) = std::fs::read_to_string(&pid_path) { #[cfg(unix)] @@ -273,12 +271,11 @@ fn handle_toggle_cursor() -> Result<(), Box fn handle_save_replay() -> Result<(), Box> { ensure_daemon_running(); - if let Ok(st) = query_status() { - if !st.is_replay_active { + if let Ok(st) = query_status() + && !st.is_replay_active { show_shadowplay_toast("INSTANT REPLAY", "Replay is turned off", ToastIcon::Error); return Ok(()); } - } send_with_notification(Command::SaveReplay, "INSTANT REPLAY", "Saved to Videos", ToastIcon::Replay) } @@ -481,13 +478,12 @@ fn main() -> Result<(), Box> { let mut id_rec = None; let mut id_cur = None; - if !is_on_hyprland { - if let Some(hk) = m_menu { + if !is_on_hyprland + && let Some(hk) = m_menu { id_menu = Some(hk.id()); let _ = mgr.register(hk); reg.push(hk); } - } if let Some(hk) = m_save { id_save = Some(hk.id()); let _ = mgr.register(hk); diff --git a/src/capture/audio.rs b/src/capture/audio.rs index 3fc068d..398fa59 100644 --- a/src/capture/audio.rs +++ b/src/capture/audio.rs @@ -589,13 +589,12 @@ mod tests { let mut got_sys_samples = false; let start = std::time::Instant::now(); while start.elapsed() < std::time::Duration::from_millis(600) { - if let Ok(samples) = rx.try_recv() { - if !samples.is_empty() { + if let Ok(samples) = rx.try_recv() + && !samples.is_empty() { got_sys_samples = true; println!("Received {} system audio samples", samples.len()); break; } - } std::thread::sleep(std::time::Duration::from_millis(20)); } assert!(got_sys_samples, "Did not receive any system audio samples"); @@ -608,13 +607,12 @@ mod tests { let mut got_mic_samples = false; let start = std::time::Instant::now(); while start.elapsed() < std::time::Duration::from_millis(600) { - if let Ok(samples) = rx.try_recv() { - if !samples.is_empty() { + if let Ok(samples) = rx.try_recv() + && !samples.is_empty() { got_mic_samples = true; println!("Received {} mic audio samples", samples.len()); break; } - } std::thread::sleep(std::time::Duration::from_millis(20)); } if !got_mic_samples { @@ -629,13 +627,12 @@ mod tests { let mut got_both_samples = false; let start = std::time::Instant::now(); while start.elapsed() < std::time::Duration::from_millis(600) { - if let Ok(samples) = rx.try_recv() { - if !samples.is_empty() { + if let Ok(samples) = rx.try_recv() + && !samples.is_empty() { got_both_samples = true; println!("Received {} mixed audio samples", samples.len()); break; } - } std::thread::sleep(std::time::Duration::from_millis(20)); } if !got_both_samples { diff --git a/src/config.rs b/src/config.rs index e19baf2..47c6d3f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -244,19 +244,18 @@ X-GNOME-Autostart-enabled=true\n"; // 3. Hyprland execs.lua integration if present let hypr_execs_lua = home.join(".config").join("hypr").join("hyprland").join("execs.lua"); - if hypr_execs_lua.exists() { - if let Ok(mut text) = fs::read_to_string(&hypr_execs_lua) { + if hypr_execs_lua.exists() + && let Ok(mut text) = fs::read_to_string(&hypr_execs_lua) { let mut modified = false; let daemon_cmd_pattern = "scythe-daemon"; let daemon_cmd_line = " hl.exec_cmd(\"scythe-daemon\")\n"; if self.autostart_replay { - if !text.contains(daemon_cmd_pattern) { - if let Some(pos) = text.rfind("end)") { + if !text.contains(daemon_cmd_pattern) + && let Some(pos) = text.rfind("end)") { text.insert_str(pos, daemon_cmd_line); modified = true; } - } } else if text.contains(daemon_cmd_pattern) { text = text.lines() .filter(|l| !l.contains(daemon_cmd_pattern)) @@ -268,12 +267,11 @@ X-GNOME-Autostart-enabled=true\n"; let overlay_cmd_pattern = "scythe-ui --menu"; let overlay_cmd_line = " hl.exec_cmd(\"scythe-ui --menu\")\n"; if self.autostart_overlay { - if !text.contains(overlay_cmd_pattern) { - if let Some(pos) = text.rfind("end)") { + if !text.contains(overlay_cmd_pattern) + && let Some(pos) = text.rfind("end)") { text.insert_str(pos, overlay_cmd_line); modified = true; } - } } else if text.contains(overlay_cmd_pattern) { text = text.lines() .filter(|l| !l.contains(overlay_cmd_pattern)) @@ -286,7 +284,6 @@ X-GNOME-Autostart-enabled=true\n"; let _ = fs::write(&hypr_execs_lua, text); } } - } } } diff --git a/src/overlay.rs b/src/overlay.rs index 26529ab..020f2aa 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -193,7 +193,8 @@ pub fn show_shadowplay_toast(title: &str, subtitle: &str, icon: ToastIcon) { "purple" | "violet" => ("#a855f7", (0.659, 0.333, 0.969)), "amber" | "orange" => ("#f59e0b", (0.961, 0.620, 0.043)), "red" | "crimson" => ("#ef4444", (0.937, 0.267, 0.267)), - "blue" | "sapphire" | _ => ("#38bdf8", (0.220, 0.741, 0.973)), + "blue" | "sapphire" => ("#38bdf8", (0.220, 0.741, 0.973)), + _ => ("#38bdf8", (0.220, 0.741, 0.973)), }; let (active_accent_hex, active_accent) = if icon == ToastIcon::Record { @@ -203,8 +204,8 @@ pub fn show_shadowplay_toast(title: &str, subtitle: &str, icon: ToastIcon) { }; fn get_active_gdk_monitor(display: &gdk::Display) -> Option { - if let Ok(out) = std::process::Command::new("hyprctl").args(["monitors", "-j"]).output() { - if let Ok(v) = serde_json::from_slice::>(&out.stdout) { + if let Ok(out) = std::process::Command::new("hyprctl").args(["monitors", "-j"]).output() + && let Ok(v) = serde_json::from_slice::>(&out.stdout) { let focused = v.iter().find(|m| m["focused"].as_bool().unwrap_or(false)) .or_else(|| v.first()); if let Some(m) = focused { @@ -220,7 +221,6 @@ pub fn show_shadowplay_toast(title: &str, subtitle: &str, icon: ToastIcon) { } } } - } display.primary_monitor().or_else(|| display.monitor(0)) } diff --git a/src/overlay_egui.rs b/src/overlay_egui.rs index c1784e3..ed61b4d 100644 --- a/src/overlay_egui.rs +++ b/src/overlay_egui.rs @@ -367,7 +367,8 @@ pub fn resolve_accent_color(accent: &str) -> Color32 { "purple" | "violet" => Color32::from_rgb(168, 85, 247), "amber" | "orange" => Color32::from_rgb(245, 158, 11), "red" | "crimson" => Color32::from_rgb(239, 68, 68), - "blue" | "sapphire" | _ => Color32::from_rgb(56, 189, 248), // Charming and comforting sky sapphire blue + "blue" | "sapphire" => Color32::from_rgb(56, 189, 248), + _ => Color32::from_rgb(56, 189, 248), } } @@ -996,8 +997,8 @@ impl ScytheOverlayApp { ui.vertical_centered(|ui| { // Voluntary, non-intrusive Update Notification Banner let cur_update = self.update_status.lock().ok().map(|g| g.clone()).unwrap_or_default(); - if let crate::updater::UpdateStatus::Available(ref info) = cur_update { - if !self.update_dismissed { + if let crate::updater::UpdateStatus::Available(ref info) = cur_update + && !self.update_dismissed { egui::Frame::NONE .fill(Color32::from_rgba_unmultiplied(13, 14, 18, 210)) .stroke(Stroke::new(1.0_f32, Color32::from_rgba_unmultiplied(accent.r(), accent.g(), accent.b(), 170))) @@ -1028,7 +1029,6 @@ impl ScytheOverlayApp { }); ui.add_space(8.0); } - } ui.horizontal_top(|ui| { ui.spacing_mut().item_spacing = Vec2::new(card_gap, 0.0); @@ -1342,13 +1342,11 @@ impl ScytheOverlayApp { .desired_width(55.0) .font(FontId::monospace(11.5)) ); - if edit_resp.changed() { - if let Ok(parsed) = self.fps_input_str.trim().parse::() { - if (15..=360).contains(&parsed) { + if edit_resp.changed() + && let Ok(parsed) = self.fps_input_str.trim().parse::() + && (15..=360).contains(&parsed) { self.target_fps = parsed; } - } - } ui.add_space(8.0); for fps in [30, 60, 120, 144, 240] { @@ -1371,13 +1369,11 @@ impl ScytheOverlayApp { .desired_width(55.0) .font(FontId::monospace(11.5)) ); - if edit_resp.changed() { - if let Ok(parsed) = self.bitrate_input_str.trim().parse::() { - if (1..=300).contains(&parsed) { + if edit_resp.changed() + && let Ok(parsed) = self.bitrate_input_str.trim().parse::() + && (1..=300).contains(&parsed) { self.bitrate_mbps = parsed; } - } - } ui.label(egui::RichText::new("Mbps").size(10.5).color(Color32::from_rgb(150, 150, 155))); ui.add_space(8.0); @@ -1407,13 +1403,11 @@ impl ScytheOverlayApp { .desired_width(55.0) .font(FontId::monospace(11.5)) ); - if edit_resp.changed() { - if let Ok(parsed) = self.replay_sec_input_str.trim().parse::() { - if (5..=1800).contains(&parsed) { + if edit_resp.changed() + && let Ok(parsed) = self.replay_sec_input_str.trim().parse::() + && (5..=1800).contains(&parsed) { self.replay_sec = parsed; } - } - } ui.label(egui::RichText::new("sec").size(10.5).color(Color32::from_rgb(150, 150, 155))); ui.add_space(8.0); @@ -1852,8 +1846,8 @@ impl ScytheOverlayApp { ui.add_space(10.0); - if let Some((msg, ts)) = &self.trim_status_msg { - if ts.elapsed() < Duration::from_secs(4) { + if let Some((msg, ts)) = &self.trim_status_msg + && ts.elapsed() < Duration::from_secs(4) { egui::Frame::NONE .fill(Color32::from_rgba_unmultiplied(accent.r(), accent.g(), accent.b(), 25)) .stroke(Stroke::new(1.0_f32, accent)) @@ -1869,7 +1863,6 @@ impl ScytheOverlayApp { }); ui.add_space(8.0); } - } // Main two-column split ui.horizontal(|ui| { @@ -2183,12 +2176,11 @@ impl eframe::App for ScytheOverlayApp { self.frame_count += 1; // Auto-position, DWM transparency, and size to monitor on launch if !self.initial_pos_set && self.frame_count >= 2 { - if let Some(monitor_size) = ctx.input(|i| i.viewport().monitor_size) { - if monitor_size.x > 100.0 && monitor_size.y > 100.0 { + if let Some(monitor_size) = ctx.input(|i| i.viewport().monitor_size) + && monitor_size.x > 100.0 && monitor_size.y > 100.0 { ctx.send_viewport_cmd(egui::ViewportCommand::OuterPosition(egui::pos2(0.0, 0.0))); ctx.send_viewport_cmd(egui::ViewportCommand::InnerSize(monitor_size)); } - } #[cfg(target_os = "windows")] apply_windows_transparency("Scythe"); ctx.send_viewport_cmd(egui::ViewportCommand::Visible(true)); @@ -2279,9 +2271,9 @@ impl eframe::App for ScytheOverlayApp { } // Click outside active panel on darkened background to dismiss - if !self.folder_picking_active.load(Ordering::SeqCst) && ctx.input(|i| i.pointer.primary_clicked()) { - if let Some(pos) = ctx.input(|i| i.pointer.interact_pos()) { - if self.panel_rect.width() > 10.0 && !self.panel_rect.expand(6.0).contains(pos) { + if !self.folder_picking_active.load(Ordering::SeqCst) && ctx.input(|i| i.pointer.primary_clicked()) + && let Some(pos) = ctx.input(|i| i.pointer.interact_pos()) + && self.panel_rect.width() > 10.0 && !self.panel_rect.expand(6.0).contains(pos) { if self.replay_dropdown_open || self.record_dropdown_open { self.replay_dropdown_open = false; self.record_dropdown_open = false; @@ -2291,8 +2283,6 @@ impl eframe::App for ScytheOverlayApp { std::process::exit(0); } } - } - } } let mut visuals = egui::Visuals::dark(); @@ -2412,8 +2402,8 @@ pub fn apply_windows_transparency(title: &str) { #[cfg(not(target_os = "windows"))] pub fn query_focused_monitor_rect() -> (f32, f32, f32, f32) { // 1. hyprctl monitors -j (Hyprland/Wayland) - if let Ok(out) = std::process::Command::new("hyprctl").args(["monitors", "-j"]).output() { - if let Ok(v) = serde_json::from_slice::>(&out.stdout) { + if let Ok(out) = std::process::Command::new("hyprctl").args(["monitors", "-j"]).output() + && let Ok(v) = serde_json::from_slice::>(&out.stdout) { let focused = v.iter().find(|m| m["focused"].as_bool().unwrap_or(false)) .or_else(|| v.first()); if let Some(m) = focused { @@ -2431,10 +2421,9 @@ pub fn query_focused_monitor_rect() -> (f32, f32, f32, f32) { } } } - } // 2. xrandr fallback (X11 / XWayland) - if let Ok(out) = std::process::Command::new("xrandr").output() { - if let Ok(text) = std::str::from_utf8(&out.stdout) { + if let Ok(out) = std::process::Command::new("xrandr").output() + && let Ok(text) = std::str::from_utf8(&out.stdout) { for line in text.lines() { if line.contains(" connected") { for part in line.split_whitespace() { @@ -2442,25 +2431,22 @@ pub fn query_focused_monitor_rect() -> (f32, f32, f32, f32) { let parts: Vec<&str> = part.split('+').collect(); if parts.len() >= 3 { let dims: Vec<&str> = parts[0].split('x').collect(); - if dims.len() == 2 { - if let (Ok(w), Ok(h), Ok(x), Ok(y)) = ( + if dims.len() == 2 + && let (Ok(w), Ok(h), Ok(x), Ok(y)) = ( dims[0].parse::(), dims[1].parse::(), parts[1].parse::(), parts[2].parse::(), - ) { - if w > 320.0 && h > 200.0 { + ) + && w > 320.0 && h > 200.0 { return (x, y, w, h); } - } - } } } } } } } - } (0.0, 0.0, 1920.0, 1080.0) } @@ -2652,8 +2638,8 @@ pub fn run_egui_toast(title: &str, subtitle: &str, icon: crate::overlay::ToastIc let toast_h: f32 = 64.0; let toast_pid_path = crate::ipc::get_toast_pid_path(); - if let Ok(prev_pid_str) = std::fs::read_to_string(&toast_pid_path) { - if let Ok(prev_pid) = prev_pid_str.trim().parse::() { + if let Ok(prev_pid_str) = std::fs::read_to_string(&toast_pid_path) + && let Ok(prev_pid) = prev_pid_str.trim().parse::() { #[cfg(target_os = "windows")] unsafe { use windows::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE}; @@ -2667,7 +2653,6 @@ pub fn run_egui_toast(title: &str, subtitle: &str, icon: crate::overlay::ToastIc let _ = libc::kill(prev_pid as i32, libc::SIGKILL); } } - } let _ = std::fs::create_dir_all(toast_pid_path.parent().unwrap_or(std::path::Path::new("."))); let _ = std::fs::write(&toast_pid_path, std::process::id().to_string()); diff --git a/src/updater.rs b/src/updater.rs index 3c509df..b6625c9 100644 --- a/src/updater.rs +++ b/src/updater.rs @@ -80,7 +80,9 @@ pub fn check_for_updates() -> Option { } #[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Default)] pub enum UpdateStatus { + #[default] Idle, Checking, UpToDate { version: String }, @@ -88,11 +90,6 @@ pub enum UpdateStatus { Failed(String), } -impl Default for UpdateStatus { - fn default() -> Self { - UpdateStatus::Idle - } -} pub fn spawn_update_check(status: Arc>) { if let Ok(mut lock) = status.lock() {