use droidkraft_core::features::flash::RebootTarget;
use droidkraft_core::features::packages::PackageFilter;
use droidkraft_core::AdbCommand;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CommandCategory {
Device,
System,
Packages,
Screen,
Power,
}
impl CommandCategory {
pub fn label(&self) -> &'static str {
match self {
CommandCategory::Device => "Device",
CommandCategory::System => "System",
CommandCategory::Packages => "Packages",
CommandCategory::Screen => "Screen",
CommandCategory::Power => "Power",
}
}
pub fn all() -> &'static [CommandCategory] {
&[
CommandCategory::Device,
CommandCategory::System,
CommandCategory::Packages,
CommandCategory::Screen,
CommandCategory::Power,
]
}
}
#[derive(Debug, Clone)]
pub enum CommandAction {
Adb(AdbCommand),
Shell(String),
Reboot(RebootTarget),
}
#[derive(Debug, Clone)]
pub struct GuiCommand {
pub label: &'static str,
pub category: CommandCategory,
pub action: CommandAction,
pub destructive: bool,
}
impl GuiCommand {
const fn adb(label: &'static str, category: CommandCategory, cmd: AdbCommand) -> Self {
Self {
label,
category,
action: CommandAction::Adb(cmd),
destructive: false,
}
}
fn shell(label: &'static str, category: CommandCategory, cmd: &str) -> Self {
Self {
label,
category,
action: CommandAction::Shell(cmd.to_string()),
destructive: false,
}
}
const fn reboot(label: &'static str, target: RebootTarget) -> Self {
Self {
label,
category: CommandCategory::Power,
action: CommandAction::Reboot(target),
destructive: true,
}
}
}
pub fn catalog() -> Vec<GuiCommand> {
vec![
GuiCommand::adb(
"List Devices",
CommandCategory::Device,
AdbCommand::ListDevices,
),
GuiCommand::adb(
"Device State",
CommandCategory::Device,
AdbCommand::GetDeviceState,
),
GuiCommand::adb(
"ADB Version",
CommandCategory::Device,
AdbCommand::GetAdbVersion,
),
GuiCommand::adb(
"Properties",
CommandCategory::Device,
AdbCommand::GetDeviceProperties,
),
GuiCommand::adb(
"Battery",
CommandCategory::System,
AdbCommand::GetBatteryInfo,
),
GuiCommand::adb("Memory", CommandCategory::System, AdbCommand::GetMemoryInfo),
GuiCommand::adb("CPU", CommandCategory::System, AdbCommand::GetCpuInfo),
GuiCommand::adb(
"Processes",
CommandCategory::System,
AdbCommand::ListProcesses,
),
GuiCommand::adb(
"Network",
CommandCategory::System,
AdbCommand::GetNetworkInfo,
),
GuiCommand::adb("Wi-Fi", CommandCategory::System, AdbCommand::GetWifiStatus),
GuiCommand::adb(
"User Packages",
CommandCategory::Packages,
AdbCommand::ListPackages {
include_path: false,
filter: PackageFilter::User,
},
),
GuiCommand::adb(
"System Packages",
CommandCategory::Packages,
AdbCommand::ListPackages {
include_path: false,
filter: PackageFilter::System,
},
),
GuiCommand::adb(
"Resolution",
CommandCategory::Screen,
AdbCommand::GetScreenResolution,
),
GuiCommand::adb(
"Screenshot",
CommandCategory::Screen,
AdbCommand::TakeScreenshot,
),
GuiCommand::shell(
"Wake",
CommandCategory::Screen,
"input keyevent KEYCODE_WAKEUP",
),
GuiCommand::shell(
"Sleep",
CommandCategory::Screen,
"input keyevent KEYCODE_SLEEP",
),
GuiCommand::reboot("Reboot", RebootTarget::System),
GuiCommand::reboot("Bootloader", RebootTarget::Bootloader),
GuiCommand::reboot("Recovery", RebootTarget::Recovery),
]
}
pub fn by_category(category: CommandCategory) -> Vec<GuiCommand> {
catalog()
.into_iter()
.filter(|c| c.category == category)
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn catalog_is_non_empty() {
assert!(!catalog().is_empty());
}
#[test]
fn every_category_has_commands() {
for cat in CommandCategory::all() {
assert!(
!by_category(*cat).is_empty(),
"category {:?} had no commands",
cat
);
}
}
#[test]
fn power_commands_are_destructive() {
for c in by_category(CommandCategory::Power) {
assert!(c.destructive, "{} should be destructive", c.label);
}
}
#[test]
fn reboot_actions_map_to_targets() {
let power = by_category(CommandCategory::Power);
assert!(power
.iter()
.any(|c| matches!(c.action, CommandAction::Reboot(RebootTarget::Bootloader))));
}
}