fix: update laptop detection logic to be more reliable (#348)
This commit is contained in:
parent
c359e3ff17
commit
97f3018be0
3 changed files with 29 additions and 36 deletions
|
|
@ -26,31 +26,23 @@ pub fn is_clamshell() -> Result<bool, String> {
|
||||||
Ok(stdout.contains("\"AppleClamshellState\" = Yes"))
|
Ok(stdout.contains("\"AppleClamshellState\" = Yes"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the Mac has a built-in display (i.e., is a laptop)
|
/// Checks if the Mac is a laptop by detecting battery presence
|
||||||
///
|
///
|
||||||
/// This queries the macOS IORegistry for built-in displays.
|
/// This uses pmset to check for battery information.
|
||||||
/// Returns true if a built-in display is found (MacBook), false otherwise (Mac Mini, Mac Studio, etc.)
|
/// Returns true if a battery is detected (laptop), false otherwise (desktop)
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn has_builtin_display() -> Result<bool, String> {
|
pub fn is_laptop() -> Result<bool, String> {
|
||||||
let output = Command::new("ioreg")
|
let output = Command::new("pmset")
|
||||||
.args(["-l", "-w", "0", "-r", "-c", "IODisplayConnect"])
|
.arg("-g")
|
||||||
|
.arg("batt")
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("Failed to execute ioreg: {}", e))?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
return Err(format!(
|
|
||||||
"ioreg command failed with status: {}",
|
|
||||||
output.status
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
// Look for built-in display indicators
|
// Check if InternalBattery is present (laptops have batteries, desktops typically don't)
|
||||||
// Built-in displays typically have AppleDisplay or AppleBacklightDisplay
|
Ok(stdout.contains("InternalBattery"))
|
||||||
Ok(stdout.contains("AppleBacklightDisplay")
|
|
||||||
|| (stdout.contains("built-in") && stdout.contains("IODisplayConnect")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stub implementation for non-macOS platforms
|
/// Stub implementation for non-macOS platforms
|
||||||
|
|
@ -62,10 +54,10 @@ pub fn is_clamshell() -> Result<bool, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stub implementation for non-macOS platforms
|
/// Stub implementation for non-macOS platforms
|
||||||
/// Always returns false since built-in display detection is macOS-specific
|
/// Always returns false since laptop detection is macOS-specific
|
||||||
#[cfg(not(target_os = "macos"))]
|
#[cfg(not(target_os = "macos"))]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn has_builtin_display() -> Result<bool, String> {
|
pub fn is_laptop() -> Result<bool, String> {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,9 +76,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
fn test_has_builtin_display() {
|
fn test_is_laptop() {
|
||||||
let result = has_builtin_display();
|
let result = is_laptop();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let _ = result.unwrap();
|
if let Ok(is_laptop) = result {
|
||||||
|
println!("Is laptop: {}", is_laptop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ pub fn run() {
|
||||||
commands::audio::set_clamshell_microphone,
|
commands::audio::set_clamshell_microphone,
|
||||||
commands::audio::get_clamshell_microphone,
|
commands::audio::get_clamshell_microphone,
|
||||||
helpers::clamshell::is_clamshell,
|
helpers::clamshell::is_clamshell,
|
||||||
helpers::clamshell::has_builtin_display,
|
helpers::clamshell::is_laptop,
|
||||||
commands::transcription::set_model_unload_timeout,
|
commands::transcription::set_model_unload_timeout,
|
||||||
commands::transcription::get_model_load_status,
|
commands::transcription::get_model_load_status,
|
||||||
commands::transcription::unload_model_manually,
|
commands::transcription::unload_model_manually,
|
||||||
|
|
|
||||||
|
|
@ -22,25 +22,24 @@ export const ClamshellMicrophoneSelector: React.FC<ClamshellMicrophoneSelectorPr
|
||||||
refreshAudioDevices,
|
refreshAudioDevices,
|
||||||
} = useSettings();
|
} = useSettings();
|
||||||
|
|
||||||
const [hasBuiltinDisplay, setHasBuiltinDisplay] = useState<boolean>(false);
|
const [isLaptop, setIsLaptop] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check if the device has a built-in display (i.e., is a laptop)
|
const checkIsLaptop = async () => {
|
||||||
const checkBuiltinDisplay = async () => {
|
|
||||||
try {
|
try {
|
||||||
const result = await invoke<boolean>("has_builtin_display");
|
const result = await invoke<boolean>("is_laptop");
|
||||||
setHasBuiltinDisplay(result);
|
setIsLaptop(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to check for built-in display:", error);
|
console.error("Failed to check if device is laptop:", error);
|
||||||
setHasBuiltinDisplay(false);
|
setIsLaptop(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
checkBuiltinDisplay();
|
checkIsLaptop();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Only render on devices with built-in displays (laptops)
|
// Only render on laptops
|
||||||
if (!hasBuiltinDisplay) {
|
if (!isLaptop) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue