From 4c340f7b709a9aabcc460917f450a1c823a83141 Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Fri, 2 Aug 2024 17:50:15 +0300 Subject: [PATCH] [desktop] Fix all clippy warning. Add clippy to CI. --- .github/workflows/tauri.yml | 19 +++ Earthfile | 36 +++++ desktop/tauri/src-tauri/Cargo.toml | 5 +- desktop/tauri/src-tauri/src/main.rs | 44 +++--- .../tauri/src-tauri/src/portapi/message.rs | 143 +++++++++--------- .../src-tauri/src/portapi/models/config.rs | 6 +- .../src-tauri/src/portmaster/commands.rs | 6 +- desktop/tauri/src-tauri/src/portmaster/mod.rs | 17 +-- .../src-tauri/src/portmaster/notifications.rs | 8 +- .../tauri/src-tauri/src/service/systemd.rs | 6 +- desktop/tauri/src-tauri/src/traymenu.rs | 57 +++---- desktop/tauri/src-tauri/src/window.rs | 9 +- desktop/tauri/src-tauri/src/xdg/mod.rs | 19 +-- 13 files changed, 208 insertions(+), 167 deletions(-) diff --git a/.github/workflows/tauri.yml b/.github/workflows/tauri.yml index 9ae0da99..a84f74e3 100644 --- a/.github/workflows/tauri.yml +++ b/.github/workflows/tauri.yml @@ -34,3 +34,22 @@ jobs: - name: Build tauri project run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +tauri-ci + + lint: + name: Linter + runs-on: ubuntu-latest + steps: + - uses: earthly/actions-setup@v1 + with: + version: v0.8.0 + - uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build tauri project + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +tauri-lint diff --git a/Earthfile b/Earthfile index 4a81900b..a000f855 100644 --- a/Earthfile +++ b/Earthfile @@ -636,6 +636,42 @@ tauri-release: BUILD +tauri-build --target="${arch}" END +tauri-lint: + FROM +tauri-src + + # Clippy (rust linter) will try to build the project before it runs the linter. + # Make sure we have evrything needed to build the project. + ARG target="x86_64-unknown-linux-gnu" + + # if we want tauri to create the installer bundles we also need to provide all external binaries + # we need to do some magic here because tauri expects the binaries to include the rust target tripple. + # We already know that triple because it's a required argument. From that triple, we use +RUST_TO_GO_ARCH_STRING + # function from below to parse the triple and guess wich GOOS and GOARCH we need. + RUN mkdir /tmp/gobuild + RUN mkdir ./binaries + + DO +RUST_TO_GO_ARCH_STRING --rustTarget="${target}" + RUN echo "GOOS=${GOOS} GOARCH=${GOARCH} GOARM=${GOARM} GO_ARCH_STRING=${GO_ARCH_STRING}" + + # Our tauri app has externalBins configured so tauri will try to embed them when it finished compiling + # the app. Make sure we copy portmaster-start and portmaster-core in all architectures supported. + # See documentation for externalBins for more information on how tauri searches for the binaries. + COPY (+go-build/output --CMDS="portmaster-start portmaster-core" --GOOS="${GOOS}" --GOARCH="${GOARCH}" --GOARM="${GOARM}") /tmp/gobuild + + # Place them in the correct folder with the rust target tripple attached. + FOR bin IN $(ls /tmp/gobuild) + # ${bin$.*} does not work in SET commands unfortunately so we use a shell + # snippet here: + RUN set -e ; \ + dest="./binaries/${bin}-${target}" ; \ + if [ -z "${bin##*.exe}" ]; then \ + dest="./binaries/${bin%.*}-${target}.exe" ; \ + fi ; \ + cp "/tmp/gobuild/${bin}" "${dest}" ; + END + DO rust+SET_CACHE_MOUNTS_ENV + RUN cargo clippy --all-targets --all-features -- -D warnings + kext-build: FROM ${rust_builder_image} diff --git a/desktop/tauri/src-tauri/Cargo.toml b/desktop/tauri/src-tauri/Cargo.toml index 3dcfdef5..f89ca02f 100644 --- a/desktop/tauri/src-tauri/Cargo.toml +++ b/desktop/tauri/src-tauri/Cargo.toml @@ -7,7 +7,7 @@ license = "" repository = "" default-run = "portmaster" edition = "2021" -rust-version = "1.60" +rust-version = "1.64" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -80,3 +80,6 @@ ctor = "0.2.6" # If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes. # DO NOT REMOVE!! custom-protocol = [ "tauri/custom-protocol" ] + +[package.metadata.clippy] +allow = ["clippy::collapsible_else_if"] \ No newline at end of file diff --git a/desktop/tauri/src-tauri/src/main.rs b/desktop/tauri/src-tauri/src/main.rs index 77c1d055..c0adcb5c 100644 --- a/desktop/tauri/src-tauri/src/main.rs +++ b/desktop/tauri/src-tauri/src/main.rs @@ -48,7 +48,7 @@ impl portmaster::Handler for WsHandler { "main-handler".to_string() } - fn on_connect(&mut self, cli: portapi::client::PortAPI) -> () { + fn on_connect(&mut self, cli: portapi::client::PortAPI) { info!("connection established, creating main window"); // we successfully connected to Portmaster. Set is_first_connect to false @@ -116,11 +116,11 @@ fn show_webview_not_installed_dialog() -> i32 { } } - return FALLBACK_TO_OLD_UI_EXIT_CODE; + FALLBACK_TO_OLD_UI_EXIT_CODE } fn main() { - if let Err(_) = tauri::webview_version() { + if tauri::webview_version().is_err() { std::process::exit(show_webview_not_installed_dialog()); } @@ -251,8 +251,8 @@ fn main() { .build(tauri::generate_context!()) .expect("error while running tauri application"); - app.run(|handle, e| match e { - RunEvent::WindowEvent { label, event, .. } => { + app.run(|handle, e| { + if let RunEvent::WindowEvent { label, event, .. } = e { if label != "main" { // We only have one window at most so any other label is unexpected return; @@ -266,32 +266,22 @@ fn main() { // // Note: the above javascript does NOT trigger the CloseRequested event so // there's no need to handle that case here. - // - match event { - WindowEvent::CloseRequested { api, .. } => { - debug!( - "window (label={}) close request received, forwarding to user-interface.", - label - ); + if let WindowEvent::CloseRequested { api, .. } = event { + debug!( + "window (label={}) close request received, forwarding to user-interface.", + label + ); - api.prevent_close(); - if let Some(window) = handle.get_webview_window(label.as_str()) { - let result = window.emit("exit-requested", ""); - if let Err(err) = result { - error!("failed to emit event: {}", err.to_string()); - } - } else { - error!("window was None"); + api.prevent_close(); + if let Some(window) = handle.get_webview_window(label.as_str()) { + let result = window.emit("exit-requested", ""); + if let Err(err) = result { + error!("failed to emit event: {}", err.to_string()); } + } else { + error!("window was None"); } - _ => {} } } - - // TODO(vladimir): why was this needed? - // RunEvent::ExitRequested { api, .. } => { - // api.prevent_exit(); - // } - _ => {} }); } diff --git a/desktop/tauri/src-tauri/src/portapi/message.rs b/desktop/tauri/src-tauri/src/portapi/message.rs index 46eb7c77..6230bc55 100644 --- a/desktop/tauri/src-tauri/src/portapi/message.rs +++ b/desktop/tauri/src-tauri/src/portapi/message.rs @@ -26,48 +26,46 @@ pub enum MessageError { InvalidPayload(#[from] serde_json::Error), } - /// Payload defines the payload type and content of a PortAPI message. -/// +/// /// For the time being, only JSON payloads (indicated by a prefixed 'J' of the payload content) /// is directly supported in `Payload::parse()`. -/// +/// /// For other payload types (like CBOR, BSON, ...) it's the user responsibility to figure out /// appropriate decoding from the `Payload::UNKNOWN` variant. #[derive(PartialEq, Debug, Clone)] pub enum Payload { - JSON(String), - UNKNOWN(String), + Json(String), + Unknown(String), } /// ParseError is returned from `Payload::parse()`. #[derive(Debug, Error)] pub enum ParseError { #[error(transparent)] - JSON(#[from] serde_json::Error), + Json(#[from] serde_json::Error), #[error("unknown error while parsing")] - UNKNOWN + Unknown, } - impl Payload { /// Parse the payload into T. - /// + /// /// Only JSON parsing is supported for now. See [Payload] for more information. - pub fn parse<'a, T>(self: &'a Self) -> std::result::Result + pub fn parse<'a, T>(&'a self) -> std::result::Result where - T: serde::de::Deserialize<'a> { - + T: serde::de::Deserialize<'a>, + { match self { - Payload::JSON(blob) => Ok(serde_json::from_str::(blob.as_str())?), - Payload::UNKNOWN(_) => Err(ParseError::UNKNOWN), + Payload::Json(blob) => Ok(serde_json::from_str::(blob.as_str())?), + Payload::Unknown(_) => Err(ParseError::Unknown), } } } /// Supports creating a Payload instance from a String. -/// +/// /// See [Payload] for more information. impl std::convert::From for Payload { fn from(value: String) -> Payload { @@ -77,10 +75,10 @@ impl std::convert::From for Payload { match first { Some(c) => match c { - 'J' => Payload::JSON(rest), - _ => Payload::UNKNOWN(value), + 'J' => Payload::Json(rest), + _ => Payload::Unknown(value), }, - None => Payload::UNKNOWN("".to_string()) + None => Payload::Unknown("".to_string()), } } } @@ -89,10 +87,10 @@ impl std::convert::From for Payload { impl std::fmt::Display for Payload { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Payload::JSON(payload) => { + Payload::Json(payload) => { write!(f, "J{}", payload) - }, - Payload::UNKNOWN(payload) => { + } + Payload::Unknown(payload) => { write!(f, "{}", payload) } } @@ -100,9 +98,9 @@ impl std::fmt::Display for Payload { } /// Message is an internal representation of a PortAPI message. -/// Users should more likely use `portapi::types::Request` and `portapi::types::Response` +/// Users should more likely use `portapi::types::Request` and `portapi::types::Response` /// instead of directly using `Message`. -/// +/// /// The struct is still public since it might be useful for debugging or to implement new /// commands not yet supported by the `portapi::types` crate. #[derive(PartialEq, Debug, Clone)] @@ -115,23 +113,23 @@ pub struct Message { /// Implementation to marshal a PortAPI message into it's wire-format representation /// (which is a string). -/// +/// /// Note that this conversion does not check for invalid messages! impl std::convert::From for String { fn from(value: Message) -> Self { - let mut result = "".to_owned(); + let mut result = String::new(); result.push_str(value.id.to_string().as_str()); - result.push_str("|"); + result.push('|'); result.push_str(&value.cmd); if let Some(key) = value.key { - result.push_str("|"); + result.push('|'); result.push_str(key.as_str()); } if let Some(payload) = value.payload { - result.push_str("|"); + result.push('|'); result.push_str(payload.to_string().as_str()) } @@ -141,15 +139,15 @@ impl std::convert::From for String { /// An implementation for `String::parse()` to convert a wire-format representation /// of a PortAPI message to a Message instance. -/// +/// /// Any errors returned from `String::parse()` will be of type `MessageError` impl std::str::FromStr for Message { type Err = MessageError; fn from_str(line: &str) -> Result { - let parts = line.split("|").collect::>(); + let parts = line.split('|').collect::>(); - let id = match parts.get(0) { + let id = match parts.first() { Some(s) => match (*s).parse::() { Ok(id) => Ok(id), Err(_) => Err(MessageError::InvalidID), @@ -163,18 +161,15 @@ impl std::str::FromStr for Message { }? .to_string(); - let key = parts.get(2) - .and_then(|key| Some(key.to_string())); + let key = parts.get(2).map(|key| key.to_string()); + let payload: Option = parts.get(3).map(|p| p.to_string().into()); - let payload : Option = parts.get(3) - .and_then(|p| Some(p.to_string().into())); - - return Ok(Message { + Ok(Message { id, cmd, key, - payload: payload - }); + payload, + }) } } @@ -191,67 +186,79 @@ mod tests { #[test] fn payload_to_string() { - let p = Payload::JSON("{}".to_string()); + let p = Payload::Json("{}".to_string()); assert_eq!(p.to_string(), "J{}"); - let p = Payload::UNKNOWN("some unknown content".to_string()); + let p = Payload::Unknown("some unknown content".to_string()); assert_eq!(p.to_string(), "some unknown content"); } #[test] fn payload_from_string() { let p: Payload = "J{}".to_string().into(); - assert_eq!(p, Payload::JSON("{}".to_string())); + assert_eq!(p, Payload::Json("{}".to_string())); let p: Payload = "some unknown content".to_string().into(); - assert_eq!(p, Payload::UNKNOWN("some unknown content".to_string())); + assert_eq!(p, Payload::Unknown("some unknown content".to_string())); } #[test] fn payload_parse() { let p: Payload = "J{\"a\": 100, \"s\": \"string\"}".to_string().into(); - let t: Test = p.parse() - .expect("Expected payload parsing to work"); + let t: Test = p.parse().expect("Expected payload parsing to work"); - assert_eq!(t, Test{ - a: 100, - s: "string".to_string(), - }); + assert_eq!( + t, + Test { + a: 100, + s: "string".to_string(), + } + ); } #[test] fn parse_message() { - let m = "10|insert|some:key|J{}".parse::() + let m = "10|insert|some:key|J{}" + .parse::() .expect("Expected message to parse"); - assert_eq!(m, Message{ - id: 10, - cmd: "insert".to_string(), - key: Some("some:key".to_string()), - payload: Some(Payload::JSON("{}".to_string())), - }); + assert_eq!( + m, + Message { + id: 10, + cmd: "insert".to_string(), + key: Some("some:key".to_string()), + payload: Some(Payload::Json("{}".to_string())), + } + ); - let m = "1|done".parse::() + let m = "1|done" + .parse::() .expect("Expected message to parse"); - assert_eq!(m, Message{ - id: 1, - cmd: "done".to_string(), - key: None, - payload: None - }); + assert_eq!( + m, + Message { + id: 1, + cmd: "done".to_string(), + key: None, + payload: None + } + ); - let m = "".parse::() - .expect_err("Expected parsing to fail"); - if let MessageError::InvalidID = m {} else { + let m = "".parse::().expect_err("Expected parsing to fail"); + if let MessageError::InvalidID = m { + } else { panic!("unexpected error value: {}", m) } - let m = "1".parse::() + let m = "1" + .parse::() .expect_err("Expected parsing to fail"); - if let MessageError::MissingCommand = m {} else { + if let MessageError::MissingCommand = m { + } else { panic!("unexpected error value: {}", m) } } diff --git a/desktop/tauri/src-tauri/src/portapi/models/config.rs b/desktop/tauri/src-tauri/src/portapi/models/config.rs index e29474a8..72b8a1d8 100644 --- a/desktop/tauri/src-tauri/src/portapi/models/config.rs +++ b/desktop/tauri/src-tauri/src/portapi/models/config.rs @@ -1,5 +1,5 @@ -use serde::*; use super::super::message::Payload; +use serde::*; #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] pub struct BooleanValue { @@ -13,6 +13,6 @@ impl TryInto for BooleanValue { fn try_into(self) -> Result { let str = serde_json::to_string(&self)?; - Ok(Payload::JSON(str)) + Ok(Payload::Json(str)) } -} \ No newline at end of file +} diff --git a/desktop/tauri/src-tauri/src/portmaster/commands.rs b/desktop/tauri/src-tauri/src/portmaster/commands.rs index d8e9db08..39c05788 100644 --- a/desktop/tauri/src-tauri/src/portmaster/commands.rs +++ b/desktop/tauri/src-tauri/src/portmaster/commands.rs @@ -86,7 +86,7 @@ pub fn get_app_info( matching_path, }; - if id == "" { + if id.is_empty() { id = uuid::Uuid::new_v4().to_string() } let cloned = id.clone(); @@ -137,7 +137,7 @@ pub fn get_app_info( pub fn get_service_manager_status(window: Window, response_id: String) -> Result { let mut id = response_id; - if id == "" { + if id.is_empty() { id = uuid::Uuid::new_v4().to_string(); } let cloned = id.clone(); @@ -161,7 +161,7 @@ pub fn get_service_manager_status(window: Window, response_id: St pub fn start_service(window: Window, response_id: String) -> Result { let mut id = response_id; - if id == "" { + if id.is_empty() { id = uuid::Uuid::new_v4().to_string(); } let cloned = id.clone(); diff --git a/desktop/tauri/src-tauri/src/portmaster/mod.rs b/desktop/tauri/src-tauri/src/portmaster/mod.rs index 80049860..0941f306 100644 --- a/desktop/tauri/src-tauri/src/portmaster/mod.rs +++ b/desktop/tauri/src-tauri/src/portmaster/mod.rs @@ -32,14 +32,13 @@ use std::{ }; use log::{debug, error}; -use serde; use std::sync::Mutex; use tauri::{AppHandle, Emitter, Manager, Runtime}; -const PORTMASTER_BASE_URL: &'static str = "http://127.0.0.1:817/api/v1/"; +const PORTMASTER_BASE_URL: &str = "http://127.0.0.1:817/api/v1/"; pub trait Handler { - fn on_connect(&mut self, cli: PortAPI) -> (); + fn on_connect(&mut self, cli: PortAPI); fn on_disconnect(&mut self); fn name(&self) -> String; } @@ -81,10 +80,7 @@ impl PortmasterInterface { let map = self.state.lock(); if let Ok(map) = map { - match map.get(&key) { - Some(value) => Some(value.clone()), - None => None, - } + map.get(&key).cloned() } else { None } @@ -129,11 +125,8 @@ impl PortmasterInterface { /// Returns the current portapi client. pub fn get_api(&self) -> Option { - if let Ok(mut api) = self.api.lock() { - match &mut *api { - Some(api) => Some(api.clone()), - None => None, - } + if let Ok(api) = self.api.lock() { + (*api).clone() } else { None } diff --git a/desktop/tauri/src-tauri/src/portmaster/notifications.rs b/desktop/tauri/src-tauri/src/portmaster/notifications.rs index bf851230..452db996 100644 --- a/desktop/tauri/src-tauri/src/portmaster/notifications.rs +++ b/desktop/tauri/src-tauri/src/portmaster/notifications.rs @@ -29,13 +29,13 @@ pub async fn notification_handler(cli: PortAPI) { } // Skip if this action has already been acted on - if n.selected_action_id != "" { + if n.selected_action_id.is_empty() { return; } show_notification(&cli, key, n).await; } Err(err) => match err { - ParseError::JSON(err) => { + ParseError::Json(err) => { error!("failed to parse notification: {}", err); } _ => { @@ -81,7 +81,7 @@ pub async fn show_notification(cli: &PortAPI, key: String, n: Notification) { let _ = cli_clone .request(Request::Update( key, - Payload::JSON( + Payload::Json( json!({ "SelectedActionID": value }) @@ -125,7 +125,7 @@ pub async fn show_notification(cli: &PortAPI, key: String, n: Notification) { let _ = cli .request(Request::Update( key, - Payload::JSON( + Payload::Json( json!({ "SelectedActionID": value }) diff --git a/desktop/tauri/src-tauri/src/service/systemd.rs b/desktop/tauri/src-tauri/src/service/systemd.rs index 770a9139..c316f375 100644 --- a/desktop/tauri/src-tauri/src/service/systemd.rs +++ b/desktop/tauri/src-tauri/src/service/systemd.rs @@ -26,7 +26,7 @@ impl From for ServiceManagerError { .ok() .filter(|s| !s.trim().is_empty()) }) - .unwrap_or_else(|| format!("Failed to run `systemctl`")); + .unwrap_or_else(|| "Failed to run `systemctl`".to_string()); ServiceManagerError::Other(output.status, msg) } @@ -231,11 +231,11 @@ fn trim_newline(s: &mut String) { } fn get_sudo_cmd() -> std::result::Result { - if let Ok(_) = fs::metadata("/usr/bin/pkexec") { + if fs::metadata("/usr/bin/pkexec").is_ok() { return Ok(SudoCommand::Pkexec); } - if let Ok(_) = fs::metadata("/usr/bin/gksudo") { + if fs::metadata("/usr/bin/gksudo").is_ok() { return Ok(SudoCommand::Gksu); } diff --git a/desktop/tauri/src-tauri/src/traymenu.rs b/desktop/tauri/src-tauri/src/traymenu.rs index 9d775475..c947bb9e 100644 --- a/desktop/tauri/src-tauri/src/traymenu.rs +++ b/desktop/tauri/src-tauri/src/traymenu.rs @@ -46,13 +46,11 @@ enum IconColor { static CURRENT_ICON_COLOR: RwLock = RwLock::new(IconColor::Red); pub static USER_THEME: RwLock = RwLock::new(dark_light::Mode::Default); -lazy_static! { - static ref SPN_STATUS: Mutex>> = Mutex::new(None); - static ref SPN_BUTTON: Mutex>> = Mutex::new(None); - static ref GLOBAL_STATUS: Mutex>> = Mutex::new(None); -} +static SPN_STATUS: Mutex>> = Mutex::new(None); +static SPN_BUTTON: Mutex>> = Mutex::new(None); +static GLOBAL_STATUS: Mutex>> = Mutex::new(None); -const PM_TRAY_ICON_ID: &'static str = "pm_icon"; +const PM_TRAY_ICON_ID: &str = "pm_icon"; // Icons @@ -64,9 +62,9 @@ fn get_theme_mode() -> dark_light::Mode { } fn get_green_icon() -> &'static [u8] { - const LIGHT_GREEN_ICON: &'static [u8] = + const LIGHT_GREEN_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_light_green_64.png"); - const DARK_GREEN_ICON: &'static [u8] = + const DARK_GREEN_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_dark_green_64.png"); match get_theme_mode() { @@ -76,9 +74,9 @@ fn get_green_icon() -> &'static [u8] { } fn get_blue_icon() -> &'static [u8] { - const LIGHT_BLUE_ICON: &'static [u8] = + const LIGHT_BLUE_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_light_blue_64.png"); - const DARK_BLUE_ICON: &'static [u8] = + const DARK_BLUE_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_dark_blue_64.png"); match get_theme_mode() { dark_light::Mode::Light => DARK_BLUE_ICON, @@ -87,20 +85,27 @@ fn get_blue_icon() -> &'static [u8] { } fn get_red_icon() -> &'static [u8] { - const LIGHT_RED_ICON: &'static [u8] = + const LIGHT_RED_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_light_red_64.png"); const DARK_RED_ICON: &'static [u8] = include_bytes!("../../../../assets/data/icons/pm_dark_red_64.png"); match get_theme_mode() { + const DARK_RED_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_dark_red_64.png"); + let mode = dark_light::detect(); + match mode { + const DARK_RED_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_dark_red_64.png"); + let mode = dark_light::detect(); + match mode { dark_light::Mode::Light => DARK_RED_ICON, _ => LIGHT_RED_ICON, } } fn get_yellow_icon() -> &'static [u8] { - const LIGHT_YELLOW_ICON: &'static [u8] = + const LIGHT_YELLOW_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_light_yellow_64.png"); - const DARK_YELLOW_ICON: &'static [u8] = + const DARK_YELLOW_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_dark_yellow_64.png"); match get_theme_mode() { dark_light::Mode::Light => DARK_YELLOW_ICON, @@ -257,10 +262,8 @@ pub fn setup_tray_menu( button_state, } = event { - if let MouseButton::Left = button { - if let MouseButtonState::Down = button_state { - let _ = open_window(tray.app_handle()); - } + if let (MouseButton::Left, MouseButtonState::Down) = (button, button_state) { + let _ = open_window(tray.app_handle()); } } }) @@ -269,20 +272,20 @@ pub fn setup_tray_menu( } pub fn update_icon(icon: AppIcon, subsystems: HashMap, spn_status: String) { - // iterate over the subsytems and check if there's a module failure - let failure = subsystems - .values() - .into_iter() - .map(|s| &s.module_status) - .fold((subsystem::FAILURE_NONE, "".to_string()), |mut acc, s| { + // iterate over the subsystems and check if there's a module failure + let failure = subsystems.values().map(|s| &s.module_status).fold( + (subsystem::FAILURE_NONE, "".to_string()), + |mut acc, s| { for m in s { if m.failure_status > acc.0 { acc = (m.failure_status, m.failure_msg.clone()) } } acc - }); + }, + ); + #[allow(clippy::collapsible_else_if)] if failure.0 == subsystem::FAILURE_NONE { if let Some(global_status) = &mut *(GLOBAL_STATUS.lock().unwrap()) { _ = global_status.set_text("Status: Secured"); @@ -405,7 +408,7 @@ pub async fn tray_handler(cli: PortAPI, app: tauri::AppHandle) { update_icon(icon.clone(), subsystems.clone(), spn_status.clone()); }, Err(err) => match err { - ParseError::JSON(err) => { + ParseError::Json(err) => { error!("failed to parse subsystem: {}", err); } _ => { @@ -437,7 +440,7 @@ pub async fn tray_handler(cli: PortAPI, app: tauri::AppHandle) { update_icon(icon.clone(), subsystems.clone(), spn_status.clone()); }, Err(err) => match err { - ParseError::JSON(err) => { + ParseError::Json(err) => { error!("failed to parse spn status value: {}", err) }, _ => { @@ -466,7 +469,7 @@ pub async fn tray_handler(cli: PortAPI, app: tauri::AppHandle) { update_spn_ui_state(value.value.unwrap_or(false)); }, Err(err) => match err { - ParseError::JSON(err) => { + ParseError::Json(err) => { error!("failed to parse config value: {}", err) }, _ => { diff --git a/desktop/tauri/src-tauri/src/window.rs b/desktop/tauri/src-tauri/src/window.rs index b5e526a4..6cdcfe08 100644 --- a/desktop/tauri/src-tauri/src/window.rs +++ b/desktop/tauri/src-tauri/src/window.rs @@ -6,9 +6,8 @@ use tauri::{ use crate::{portmaster::PortmasterExt, traymenu}; -const LIGHT_PM_ICON: &'static [u8] = - include_bytes!("../../../../assets/data/icons/pm_light_512.png"); -const DARK_PM_ICON: &'static [u8] = include_bytes!("../../../../assets/data/icons/pm_dark_512.png"); +const LIGHT_PM_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_light_512.png"); +const DARK_PM_ICON: &[u8] = include_bytes!("../../../../assets/data/icons/pm_dark_512.png"); /// Either returns the existing "main" window or creates a new one. /// @@ -54,7 +53,7 @@ pub fn create_main_window(app: &AppHandle) -> Result { set_window_icon(&window); #[cfg(debug_assertions)] - if let Ok(_) = std::env::var("TAURI_SHOW_IMMEDIATELY") { + if std::env::var("TAURI_SHOW_IMMEDIATELY").is_ok() { debug!("[tauri] TAURI_SHOW_IMMEDIATELY is set, opening window"); if let Err(err) = window.show() { @@ -92,7 +91,7 @@ pub fn close_splash_window(app: &AppHandle) -> Result<()> { let _ = window.hide(); return window.destroy(); } - return Err(tauri::Error::WindowNotFound); + Err(tauri::Error::WindowNotFound) } pub fn hide_splash_window(app: &AppHandle) -> Result<()> { diff --git a/desktop/tauri/src-tauri/src/xdg/mod.rs b/desktop/tauri/src-tauri/src/xdg/mod.rs index 8ff6fd11..3db67942 100644 --- a/desktop/tauri/src-tauri/src/xdg/mod.rs +++ b/desktop/tauri/src-tauri/src/xdg/mod.rs @@ -18,7 +18,6 @@ use std::{ }; use thiserror::Error; -use dirs; use ini::{Ini, ParseOption}; static mut GTK_DEFAULT_THEME: Option<*mut GtkIconTheme> = None; @@ -146,7 +145,7 @@ pub fn get_app_info(process_info: ProcessInfo) -> Result { .unwrap() .insert(process_info.exec_path, None); - Err(Error::new(ErrorKind::NotFound, format!("failed to find app info")).into()) + Err(Error::new(ErrorKind::NotFound, "failed to find app info".to_string()).into()) } else { // sort matches by length matches.sort_by(|a, b| a.1.cmp(&b.1)); @@ -178,7 +177,7 @@ pub fn get_app_info(process_info: ProcessInfo) -> Result { }; } - Err(Error::new(ErrorKind::NotFound, format!("failed to find app info")).into()) + Err(Error::new(ErrorKind::NotFound, "failed to find app info".to_string()).into()) } } @@ -336,7 +335,7 @@ fn try_get_app_info( } } - if result.len() > 0 { + if !result.is_empty() { Ok(result) } else { Err(Error::new(ErrorKind::NotFound, "no matching .desktop files found").into()) @@ -393,7 +392,7 @@ fn get_icon_as_png_dataurl(name: &str, size: i8) -> Result<(String, String)> { // - network // name_without_ext - .split("-") + .split('-') .for_each(|part| icons.push(part)); for name in icons { @@ -554,15 +553,7 @@ mod tests { matching_path: bin.clone(), pid: 0, }) - .expect( - format!( - "expected to find app info for {} ({})", - bin, - cmd.to_string() - ) - .as_str(), - ); - + .unwrap_or_else(|_| panic!("expected to find app info for {} ({})", bin, cmd)); let empty_string = String::from(""); // just make sure all fields are populated