use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Manager, Runtime};
use crate::models::*;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(target_os = "linux")]
mod linux;
pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
_api: PluginApi<R, C>,
) -> crate::Result<DeviceInfo<R>> {
Ok(DeviceInfo(app.clone()))
}
pub struct DeviceInfo<R: Runtime>(AppHandle<R>);
impl<R: Runtime> DeviceInfo<R> {
pub fn get_device_info(&self) -> crate::Result<DeviceInfoResponse> {
#[cfg(target_os = "windows")]
return windows::get_device_info();
#[cfg(target_os = "macos")]
return macos::get_device_info();
#[cfg(target_os = "linux")]
return linux::get_device_info();
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
return Err(crate::Error::DeviceInfo("Unsupported platform".to_string()));
}
pub fn get_battery_info(&self) -> crate::Result<BatteryInfo> {
#[cfg(target_os = "macos")]
return macos::get_battery_info();
#[cfg(not(target_os = "macos"))]
{
let manager =
battery::Manager::new().map_err(|e| crate::Error::DeviceInfo(e.to_string()))?;
if let Some(Ok(battery)) = manager
.batteries()
.map_err(|e| crate::Error::DeviceInfo(e.to_string()))?
.next()
{
let level = (battery.state_of_charge().value * 100.0).round();
let is_charging = battery.state() == battery::State::Charging;
let health = format!("{:?}", battery.state_of_health().value * 100.0);
Ok(BatteryInfo {
level: Some(level),
is_charging: Some(is_charging),
health: Some(health),
})
} else {
Ok(BatteryInfo::default())
}
}
}
pub fn get_default_mac_address() -> String {
use default_net::get_default_interface;
match get_default_interface() {
Ok(interface) => match interface.mac_addr {
Some(mac) => mac.to_string(),
None => "00:00:00:00:00:00".to_string(),
},
Err(_) => "00:00:00:00:00:00".to_string(),
}
}
pub fn get_network_info(&self) -> crate::Result<NetworkInfo> {
use local_ip_address::local_ip;
let ip_addr = local_ip().ok();
let ip_str = ip_addr.map(|ip| ip.to_string());
let mac_address = Some(Self::get_default_mac_address());
let mut network_type = Some("unknown".to_string());
if let Some(target_ip) = ip_addr {
let networks = sysinfo::Networks::new_with_refreshed_list();
if let Some((name, _)) = networks.iter().find(|(_, network)| {
network
.ip_networks()
.iter()
.any(|net| net.addr == target_ip)
}) {
let name_lower = name.to_lowercase();
if name_lower.contains("wifi") || name_lower.contains("wl") {
network_type = Some("wifi".to_string());
} else if name_lower.contains("eth") || name_lower.contains("ethernet") {
network_type = Some("ethernet".to_string());
} else if cfg!(target_os = "macos") && name_lower.starts_with("en") {
if name == "en0" {
network_type = Some("wifi".to_string());
} else {
network_type = Some("ethernet".to_string());
}
} else {
network_type = Some(name.to_string());
}
}
}
Ok(NetworkInfo {
ip_address: ip_str,
network_type,
mac_address,
})
}
pub fn get_storage_info(&self) -> crate::Result<StorageInfo> {
let disks = sysinfo::Disks::new_with_refreshed_list();
let system_disk = disks.iter().find(|d| {
let mount = d.mount_point();
mount == std::path::Path::new("/") || mount == std::path::Path::new("C:\\")
});
let targeted_disk = system_disk.or_else(|| disks.iter().max_by_key(|d| d.total_space()));
if let Some(disk) = targeted_disk {
Ok(StorageInfo {
total_space: disk.total_space(),
free_space: disk.available_space(),
storage_type: Some(format!("{:?}", disk.kind())),
})
} else {
Ok(StorageInfo::default())
}
}
pub fn get_display_info(&self) -> crate::Result<DisplayInfo> {
let windows = self.0.webview_windows();
if let Some(window) = windows.values().next() {
if let Ok(Some(monitor)) = window.primary_monitor() {
let size = monitor.size();
let refresh_rate = {
#[cfg(target_os = "macos")]
{
macos::get_display_refresh_rate()
}
#[cfg(target_os = "windows")]
{
windows::get_display_refresh_rate()
}
#[cfg(target_os = "linux")]
{
linux::get_display_refresh_rate()
}
#[cfg(not(any(
target_os = "macos",
target_os = "windows",
target_os = "linux"
)))]
{
None
}
};
return Ok(DisplayInfo {
width: size.width,
height: size.height,
scale_factor: monitor.scale_factor(),
refresh_rate,
});
}
}
Ok(DisplayInfo::default())
}
}