Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 86 additions & 13 deletions crates/adapter-ipc-grpc/src/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,27 @@ use std::{path::PathBuf, time::Duration};
use app_services::{
SharedControlPlaneApp, commands as app_commands,
queries::{
ConsoleSnapshot, StatusSnapshot, TransportEventSnapshot, UiDiscoveredPeer, UiPairedPeer,
UiPendingRequest, UiSnapshot,
AntiIdleConfigSnapshot, AntiIdleStatusSnapshot, ConsoleSnapshot, StatusSnapshot,
TransportEventSnapshot, UiDiscoveredPeer, UiPairedPeer, UiPendingRequest, UiSnapshot,
},
};
use tokio::{sync::mpsc, time};
use tokio_stream::wrappers::ReceiverStream;
use tonic::{Request, Response, Status};

use ipc_api::boundless::v1::{
ConsoleSnapshotReply, DiagnosticsDumpReply, DiagnosticsDumpRequest, DiscoveredPeerInfo, Empty,
FeatureListReply, FeatureSetRequest, HotkeySetRequest, HotkeyTriggerRequest,
ImportTrustBundleRequest, InputCaptureTargetReply, InputCaptureTargetRequest, InputOwnerReply,
InputOwnerRequest, LayoutReply, LayoutSetRequest, NearbyJoinStartRequest,
NearbyJoinStatusReply, NearbyJoinStatusRequest, NearbyPairingCompletionReply,
NearbyPairingDecisionRequest, NearbyPairingRequestInfo, NearbyRequestCodeStartReply,
NearbyRequestCodeStartRequest, NearbySubmitCodeRequest, OperationReply, PairCreateCodeReply,
PairCreateCodeRequest, PairJoinReply, PairJoinRequest, PeerInfo, PeerListReply,
RemovePeerRequest, SafeResetRequest, SendClipboardImageRequest, SendClipboardTextRequest,
SendFileRequest, SendInputKeyRequest, SendInputMoveRequest, StatusReply, StatusRequest,
TransportEvent, TransportEventsReply, TrustBundleReply, UiSnapshotReply,
AntiIdleConfigReply, AntiIdleSetRequest, AntiIdleStatusReply, ConsoleSnapshotReply,
DiagnosticsDumpReply, DiagnosticsDumpRequest, DiscoveredPeerInfo, Empty, FeatureListReply,
FeatureSetRequest, HotkeySetRequest, HotkeyTriggerRequest, ImportTrustBundleRequest,
InputCaptureTargetReply, InputCaptureTargetRequest, InputOwnerReply, InputOwnerRequest,
LayoutReply, LayoutSetRequest, NearbyJoinStartRequest, NearbyJoinStatusReply,
NearbyJoinStatusRequest, NearbyPairingCompletionReply, NearbyPairingDecisionRequest,
NearbyPairingRequestInfo, NearbyRequestCodeStartReply, NearbyRequestCodeStartRequest,
NearbySubmitCodeRequest, OperationReply, PairCreateCodeReply, PairCreateCodeRequest,
PairJoinReply, PairJoinRequest, PeerInfo, PeerListReply, RemovePeerRequest, SafeResetRequest,
SendClipboardImageRequest, SendClipboardTextRequest, SendFileRequest, SendInputKeyRequest,
SendInputMoveRequest, StatusReply, StatusRequest, TransportEvent, TransportEventsReply,
TrustBundleReply, UiSnapshotReply,
control_plane_service_server::{ControlPlaneService, ControlPlaneServiceServer},
};

Expand Down Expand Up @@ -240,6 +241,51 @@ impl ControlPlaneService for ControlPlaneApi {
}))
}

async fn get_anti_idle_config(
&self,
_request: Request<Empty>,
) -> Result<Response<AntiIdleConfigReply>, Status> {
let snapshot = self
.app
.anti_idle_config()
.await
.map_err(|error| Status::internal(format!("build anti-idle config: {error:#}")))?;
Ok(Response::new(map_anti_idle_config(snapshot)))
}

async fn get_anti_idle_status(
&self,
_request: Request<Empty>,
) -> Result<Response<AntiIdleStatusReply>, Status> {
let snapshot = self
.app
.anti_idle_status()
.await
.map_err(|error| Status::internal(format!("build anti-idle status: {error:#}")))?;
Ok(Response::new(map_anti_idle_status(snapshot)))
}

async fn set_anti_idle_config(
&self,
request: Request<AntiIdleSetRequest>,
) -> Result<Response<OperationReply>, Status> {
let request = request.into_inner();
let reply = self
.app
.set_anti_idle_config(app_commands::SetAntiIdleConfigCommand {
enabled: request.enabled,
recent_activity_window_secs: request.recent_activity_window_secs,
allow_on_battery: request.allow_on_battery,
keep_display_on: request.keep_display_on,
})
.await
.map_err(|error| Status::invalid_argument(error.to_string()))?;
Ok(Response::new(OperationReply {
ok: reply.ok,
message: reply.message,
}))
}

async fn set_hotkey(
&self,
request: Request<HotkeySetRequest>,
Expand Down Expand Up @@ -790,6 +836,8 @@ fn map_ui_snapshot(snapshot: UiSnapshot) -> UiSnapshotReply {
.into_iter()
.map(map_pending_request)
.collect(),
anti_idle_config: Some(map_anti_idle_config(snapshot.anti_idle_config)),
anti_idle_status: Some(map_anti_idle_status(snapshot.anti_idle_status)),
}
}

Expand All @@ -812,6 +860,8 @@ fn map_console_snapshot(snapshot: ConsoleSnapshot) -> ConsoleSnapshotReply {
input_capture_target_peer_id: snapshot.input_capture_target_peer_id.unwrap_or_default(),
mdns_active: snapshot.mdns_active,
local_display_name: snapshot.local_display_name,
anti_idle_config: Some(map_anti_idle_config(snapshot.anti_idle_config)),
anti_idle_status: Some(map_anti_idle_status(snapshot.anti_idle_status)),
}
}

Expand All @@ -828,6 +878,29 @@ fn map_status_snapshot(snapshot: StatusSnapshot) -> StatusReply {
input_locked: snapshot.input_locked,
input_lock_supported: snapshot.input_lock_supported,
capture_target_peer_id: snapshot.capture_target_peer_id.unwrap_or_default(),
anti_idle_supported: snapshot.anti_idle_supported,
anti_idle_enabled: snapshot.anti_idle_enabled,
anti_idle_active: snapshot.anti_idle_active,
anti_idle_display_required: snapshot.anti_idle_display_required,
}
}

fn map_anti_idle_config(snapshot: AntiIdleConfigSnapshot) -> AntiIdleConfigReply {
AntiIdleConfigReply {
enabled: snapshot.enabled,
recent_activity_window_secs: snapshot.recent_activity_window_secs,
allow_on_battery: snapshot.allow_on_battery,
keep_display_on: snapshot.keep_display_on,
}
}

fn map_anti_idle_status(snapshot: AntiIdleStatusSnapshot) -> AntiIdleStatusReply {
AntiIdleStatusReply {
supported: snapshot.supported,
enabled: snapshot.enabled,
active: snapshot.active,
display_required: snapshot.display_required,
reason: snapshot.reason,
}
}

Expand Down
14 changes: 10 additions & 4 deletions crates/app-services/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ use crate::{
NearbyRequestCodeCommand, NearbySubmitCodeCommand, OperationReply, PairJoinCommand,
PairJoinReply, PairingCodeReply, PairingCodeRequest, RemovePeerCommand, SafeResetCommand,
SendClipboardImageCommand, SendClipboardTextCommand, SendFileCommand, SendInputKeyCommand,
SendInputMoveCommand,
SendInputMoveCommand, SetAntiIdleConfigCommand,
},
queries::{
ConsoleSnapshot, NearbyJoinStatusSnapshot, NearbyPairingCompletionSnapshot,
NearbyRequestCodeStartSnapshot, StatusSnapshot, TransportEventSnapshot,
TrustBundleSnapshot, UiSnapshot,
AntiIdleConfigSnapshot, AntiIdleStatusSnapshot, ConsoleSnapshot, NearbyJoinStatusSnapshot,
NearbyPairingCompletionSnapshot, NearbyRequestCodeStartSnapshot, StatusSnapshot,
TransportEventSnapshot, TrustBundleSnapshot, UiSnapshot,
},
};

Expand All @@ -34,6 +34,12 @@ pub trait ControlPlaneApp: Send + Sync {
async fn layout(&self) -> Result<LayoutReply>;
async fn features(&self) -> Result<std::collections::BTreeMap<String, bool>>;
async fn set_feature(&self, command: FeatureSetCommand) -> Result<OperationReply>;
async fn anti_idle_config(&self) -> Result<AntiIdleConfigSnapshot>;
async fn anti_idle_status(&self) -> Result<AntiIdleStatusSnapshot>;
async fn set_anti_idle_config(
&self,
command: SetAntiIdleConfigCommand,
) -> Result<OperationReply>;
async fn set_hotkey(&self, command: HotkeySetCommand) -> Result<OperationReply>;
async fn trigger_hotkey_action(&self, command: HotkeyTriggerCommand) -> Result<OperationReply>;
async fn export_trust_bundle(&self) -> Result<TrustBundleSnapshot>;
Expand Down
8 changes: 8 additions & 0 deletions crates/app-services/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ pub struct FeatureSetCommand {
pub enabled: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SetAntiIdleConfigCommand {
pub enabled: bool,
pub recent_activity_window_secs: u32,
pub allow_on_battery: bool,
pub keep_display_on: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HotkeySetCommand {
pub action: String,
Expand Down
25 changes: 25 additions & 0 deletions crates/app-services/src/queries.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AntiIdleConfigSnapshot {
pub enabled: bool,
pub recent_activity_window_secs: u32,
pub allow_on_battery: bool,
pub keep_display_on: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AntiIdleStatusSnapshot {
pub supported: bool,
pub enabled: bool,
pub active: bool,
pub display_required: bool,
pub reason: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusSnapshot {
pub daemon_version: String,
Expand All @@ -13,6 +30,10 @@ pub struct StatusSnapshot {
pub input_locked: bool,
pub input_lock_supported: bool,
pub capture_target_peer_id: Option<String>,
pub anti_idle_supported: bool,
pub anti_idle_enabled: bool,
pub anti_idle_active: bool,
pub anti_idle_display_required: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -50,6 +71,8 @@ pub struct UiSnapshot {
pub discovered_peers: Vec<UiDiscoveredPeer>,
pub paired_peers: Vec<UiPairedPeer>,
pub pending_requests: Vec<UiPendingRequest>,
pub anti_idle_config: AntiIdleConfigSnapshot,
pub anti_idle_status: AntiIdleStatusSnapshot,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand All @@ -65,6 +88,8 @@ pub struct ConsoleSnapshot {
pub input_capture_target_peer_id: Option<String>,
pub mdns_active: bool,
pub local_display_name: String,
pub anti_idle_config: AntiIdleConfigSnapshot,
pub anti_idle_status: AntiIdleStatusSnapshot,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
99 changes: 97 additions & 2 deletions crates/cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub(super) async fn daemon_status(endpoint: &str) -> Result<()> {
let mut client = ControlPlaneServiceClient::new(channel(endpoint).await?);
let status = client.get_status(StatusRequest {}).await?.into_inner();
println!(
"running={} machine_id={} peers={} protocol={} api_transport={} api_bind={} api_pipe_name={} input_locked={} input_lock_supported={} active_capture_target={}",
"running={} machine_id={} peers={} protocol={} api_transport={} api_bind={} api_pipe_name={} input_locked={} input_lock_supported={} active_capture_target={} anti_idle_supported={} anti_idle_enabled={} anti_idle_active={} anti_idle_display_required={}",
status.running,
status.machine_id,
status.peer_count,
Expand All @@ -56,7 +56,11 @@ pub(super) async fn daemon_status(endpoint: &str) -> Result<()> {
"none"
} else {
status.capture_target_peer_id.as_str()
}
},
status.anti_idle_supported,
status.anti_idle_enabled,
status.anti_idle_active,
status.anti_idle_display_required
);
Ok(())
}
Expand Down Expand Up @@ -879,6 +883,48 @@ pub(super) async fn feature_set(endpoint: &str, name: String, value: ToggleValue
Ok(())
}

pub(super) async fn anti_idle_show(endpoint: &str) -> Result<()> {
let mut client = ControlPlaneServiceClient::new(channel(endpoint).await?);
let config = client.get_anti_idle_config(Empty {}).await?.into_inner();
let status = client.get_anti_idle_status(Empty {}).await?.into_inner();

println!(
"enabled={} recent_activity_window_secs={} allow_on_battery={} keep_display_on={} supported={} active={} display_required={} reason={}",
config.enabled,
config.recent_activity_window_secs,
config.allow_on_battery,
config.keep_display_on,
status.supported,
status.active,
status.display_required,
status.reason
);
Ok(())
}

pub(super) async fn anti_idle_set(
endpoint: &str,
enabled: bool,
window_minutes: u32,
allow_on_battery: bool,
keep_display_on: bool,
) -> Result<()> {
let recent_activity_window_secs = window_minutes.saturating_mul(60);
let mut client = ControlPlaneServiceClient::new(channel(endpoint).await?);
let response = client
.set_anti_idle_config(AntiIdleSetRequest {
enabled,
recent_activity_window_secs,
allow_on_battery,
keep_display_on,
})
.await?
.into_inner();

println!("ok={} message={}", response.ok, response.message);
Ok(())
}

pub(super) async fn hotkey_set(endpoint: &str, action: String, combo: String) -> Result<()> {
let mut client = ControlPlaneServiceClient::new(channel(endpoint).await?);
let response = client
Expand Down Expand Up @@ -1168,6 +1214,8 @@ struct UiSnapshot {
discovered_peers: Vec<UiDiscoveredPeer>,
paired_peers: Vec<UiPairedPeer>,
pending_requests: Vec<UiPendingRequest>,
anti_idle_config: UiAntiIdleConfig,
anti_idle_status: UiAntiIdleStatus,
}

#[derive(Debug, Clone, Serialize)]
Expand Down Expand Up @@ -1196,6 +1244,23 @@ struct UiPendingRequest {
requires_verification_code: bool,
}

#[derive(Debug, Clone, Serialize)]
struct UiAntiIdleConfig {
enabled: bool,
recent_activity_window_secs: u32,
allow_on_battery: bool,
keep_display_on: bool,
}

#[derive(Debug, Clone, Serialize)]
struct UiAntiIdleStatus {
supported: bool,
enabled: bool,
active: bool,
display_required: bool,
reason: String,
}

pub(super) async fn ui_snapshot(endpoint: &str, start_daemon: bool) -> Result<()> {
if start_daemon {
ensure_daemon_available(endpoint, true).await?;
Expand Down Expand Up @@ -1240,6 +1305,36 @@ pub(super) async fn ui_snapshot(endpoint: &str, start_daemon: bool) -> Result<()
requires_verification_code: request.requires_verification_code,
})
.collect(),
anti_idle_config: snapshot
.anti_idle_config
.map(|config| UiAntiIdleConfig {
enabled: config.enabled,
recent_activity_window_secs: config.recent_activity_window_secs,
allow_on_battery: config.allow_on_battery,
keep_display_on: config.keep_display_on,
})
.unwrap_or(UiAntiIdleConfig {
enabled: false,
recent_activity_window_secs: 0,
allow_on_battery: false,
keep_display_on: false,
}),
anti_idle_status: snapshot
.anti_idle_status
.map(|status| UiAntiIdleStatus {
supported: status.supported,
enabled: status.enabled,
active: status.active,
display_required: status.display_required,
reason: status.reason,
})
.unwrap_or(UiAntiIdleStatus {
supported: false,
enabled: false,
active: false,
display_required: false,
reason: "none".to_string(),
}),
};

println!(
Expand Down
Loading
Loading