interactive: Host/View entry menu, clipboard copy, player picker

Bare `pixelpass` now opens a dialoguer-driven Host/View menu instead of
going straight to host mode. Host path copies the ticket to the system
clipboard via arboard with silent print-only fallback. View path
prompts for the ticket, then after the local listener binds prompts
mpv-vs-VLC and spawns it detached (setsid + null stdio) so the player
survives pixelpass exiting.

Headless invocations (`pixelpass <ticket>`, `pixelpass --repair`)
unchanged. Per spec at ~/Documents/pixelpass-interactive-mode-spec.md.
This commit is contained in:
2026-05-18 15:46:57 -04:00
parent 4cab9f6b20
commit bb437a73cf
9 changed files with 410 additions and 15 deletions
+8 -5
View File
@@ -5,8 +5,8 @@ use clap::{Parser, ValueEnum};
name = "pixelpass",
version,
about = "P2P screen sharing over iroh + ffmpeg",
long_about = "Run with no arguments to host (prints a ticket to share). \
Pass a ticket to view."
long_about = "Run with no arguments for an interactive Host/View menu. \
Pass a ticket positionally to skip the menu and view headlessly."
)]
pub struct Cli {
/// iroh ticket. If present, runs as viewer. If absent, runs as host.
@@ -76,15 +76,17 @@ pub struct HostOpts {
pub framerate: u32,
pub no_hwencode: bool,
pub low_latency: bool,
pub interactive: bool,
}
#[derive(Debug, Clone)]
pub struct ViewerOpts {
pub port: u16,
pub interactive: bool,
}
impl Cli {
pub fn into_host_opts(self) -> HostOpts {
pub fn into_host_opts(self, interactive: bool) -> HostOpts {
HostOpts {
window: self.window,
app: self.app,
@@ -94,10 +96,11 @@ impl Cli {
framerate: self.framerate,
no_hwencode: self.no_hwencode,
low_latency: self.low_latency,
interactive,
}
}
pub fn into_viewer_opts(self) -> ViewerOpts {
ViewerOpts { port: self.port }
pub fn into_viewer_opts(self, interactive: bool) -> ViewerOpts {
ViewerOpts { port: self.port, interactive }
}
}