refactor: remove remote sequence CLI command
Collapse remote input to `tvctl remote key` so single-key and multi-key usage share one public command while keeping the paced daemon path underneath.
This commit is contained in:
+1
-2
@@ -221,8 +221,7 @@ tvctl
|
|||||||
│ ├── stop
|
│ ├── stop
|
||||||
│ └── refresh
|
│ └── refresh
|
||||||
├── remote
|
├── remote
|
||||||
│ ├── key <key>
|
│ └── key <key> [key...]
|
||||||
│ └── sequence <key> [key...]
|
|
||||||
├── state
|
├── state
|
||||||
├── dev
|
├── dev
|
||||||
│ ├── install <zip>
|
│ ├── install <zip>
|
||||||
|
|||||||
@@ -171,8 +171,7 @@ tvctl app refresh Refresh app cache from TV
|
|||||||
Send input to the TV.
|
Send input to the TV.
|
||||||
|
|
||||||
```
|
```
|
||||||
tvctl remote key <key> Send a single keypress
|
tvctl remote key <key> [key...] Send one or more keypresses
|
||||||
tvctl remote sequence <key> [key...] Send a sequence of keypresses
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Available keys:**
|
**Available keys:**
|
||||||
|
|||||||
+21
-19
@@ -176,14 +176,9 @@ pub enum AppCommand {
|
|||||||
pub enum RemoteCommand {
|
pub enum RemoteCommand {
|
||||||
/// Send a single normalized key.
|
/// Send a single normalized key.
|
||||||
Key {
|
Key {
|
||||||
/// Key name such as `home`, `down`, or `literal:abc`.
|
/// One or more key names such as `home`, `down`, or `literal:abc`.
|
||||||
key: String,
|
|
||||||
},
|
|
||||||
/// Send multiple normalized keys in order.
|
|
||||||
Sequence {
|
|
||||||
/// Key names such as `home down select`.
|
|
||||||
keys: Vec<String>,
|
keys: Vec<String>,
|
||||||
/// Delay between keys in milliseconds.
|
/// Delay between keys in milliseconds when sending more than one key.
|
||||||
#[arg(long, default_value_t = DEFAULT_REMOTE_SEQUENCE_DELAY_MS)]
|
#[arg(long, default_value_t = DEFAULT_REMOTE_SEQUENCE_DELAY_MS)]
|
||||||
delay_ms: u64,
|
delay_ms: u64,
|
||||||
},
|
},
|
||||||
@@ -442,25 +437,25 @@ async fn handle_app_command(cli: &Cli, command: AppCommand) -> Result<(), CliErr
|
|||||||
|
|
||||||
async fn handle_remote_command(cli: &Cli, command: RemoteCommand) -> Result<(), CliError> {
|
async fn handle_remote_command(cli: &Cli, command: RemoteCommand) -> Result<(), CliError> {
|
||||||
match command {
|
match command {
|
||||||
RemoteCommand::Key { key } => {
|
RemoteCommand::Key { keys, delay_ms } => {
|
||||||
|
if keys.is_empty() {
|
||||||
|
return Err(CliError::new(
|
||||||
|
"At least one key is required for `tvctl remote key`.",
|
||||||
|
"Pass one or more keys such as `home` or `home down select`.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if keys.len() == 1 {
|
||||||
let response = send_request(
|
let response = send_request(
|
||||||
load_socket_path().await?,
|
load_socket_path().await?,
|
||||||
&DaemonRequest::SendKey {
|
&DaemonRequest::SendKey {
|
||||||
device: cli.device.clone(),
|
device: cli.device.clone(),
|
||||||
key: parse_tv_key(&key)?,
|
key: parse_tv_key(&keys[0])?,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let result: ActionResult = parse_response_data(response)?;
|
let result: ActionResult = parse_response_data(response)?;
|
||||||
render(cli, &result, || result.detail.clone())
|
render(cli, &result, || result.detail.clone())
|
||||||
}
|
} else {
|
||||||
RemoteCommand::Sequence { keys, delay_ms } => {
|
|
||||||
if keys.is_empty() {
|
|
||||||
return Err(CliError::new(
|
|
||||||
"At least one key is required for `tvctl remote sequence`.",
|
|
||||||
"Pass one or more keys such as `home down select`.",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let parsed = keys
|
let parsed = keys
|
||||||
.iter()
|
.iter()
|
||||||
.map(|key| parse_tv_key(key))
|
.map(|key| parse_tv_key(key))
|
||||||
@@ -479,6 +474,7 @@ async fn handle_remote_command(cli: &Cli, command: RemoteCommand) -> Result<(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_state_command(cli: &Cli) -> Result<(), CliError> {
|
async fn handle_state_command(cli: &Cli) -> Result<(), CliError> {
|
||||||
let response = send_request(
|
let response = send_request(
|
||||||
@@ -674,9 +670,15 @@ async fn daemon_stop(cli: &Cli) -> Result<(), CliError> {
|
|||||||
async fn daemon_status(cli: &Cli) -> Result<(), CliError> {
|
async fn daemon_status(cli: &Cli) -> Result<(), CliError> {
|
||||||
if let Some(status) = daemon_status_payload().await {
|
if let Some(status) = daemon_status_payload().await {
|
||||||
return render(cli, &status, || {
|
return render(cli, &status, || {
|
||||||
|
let http = if status.http_enabled {
|
||||||
|
format!("{}:{}", status.http_host, status.http_port)
|
||||||
|
} else {
|
||||||
|
"disabled".to_string()
|
||||||
|
};
|
||||||
|
let default_device = status.default_device.as_deref().unwrap_or("none");
|
||||||
format!(
|
format!(
|
||||||
"tvctld is running on {} with {} known device(s).",
|
"tvctld is running.\nPID: {}\nSocket: {}\nHTTP: {}\nKnown Devices: {}\nDefault Device: {}",
|
||||||
status.socket, status.device_count
|
status.pid, status.socket, http, status.device_count, default_device
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,8 +169,15 @@ pub struct DaemonStatus {
|
|||||||
pub socket: String,
|
pub socket: String,
|
||||||
/// Whether the HTTP API is enabled.
|
/// Whether the HTTP API is enabled.
|
||||||
pub http_enabled: bool,
|
pub http_enabled: bool,
|
||||||
|
/// The HTTP bind host.
|
||||||
|
pub http_host: String,
|
||||||
|
/// The HTTP bind port.
|
||||||
|
pub http_port: u16,
|
||||||
/// The number of known devices.
|
/// The number of known devices.
|
||||||
pub device_count: usize,
|
pub device_count: usize,
|
||||||
|
/// The current default device, if configured.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub default_device: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Discovery results returned by the daemon.
|
/// Discovery results returned by the daemon.
|
||||||
|
|||||||
@@ -218,7 +218,13 @@ async fn handle_request(
|
|||||||
pid: std::process::id(),
|
pid: std::process::id(),
|
||||||
socket: guard.paths.socket_file.display().to_string(),
|
socket: guard.paths.socket_file.display().to_string(),
|
||||||
http_enabled: guard.config.daemon.http_enabled,
|
http_enabled: guard.config.daemon.http_enabled,
|
||||||
|
http_host: guard.config.daemon.http_host.clone(),
|
||||||
|
http_port: guard.config.daemon.http_port,
|
||||||
device_count: guard.registry.devices.len(),
|
device_count: guard.registry.devices.len(),
|
||||||
|
default_device: guard
|
||||||
|
.registry
|
||||||
|
.default_device()
|
||||||
|
.map(|device| device.name.clone()),
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user