use anyhow::Result; use dialoguer::{Input, Select, theme::ColorfulTheme}; use iroh_tickets::endpoint::EndpointTicket; use std::str::FromStr; use crate::cli::Cli; use crate::{host, viewer}; pub async fn run(cli: Cli) -> Result<()> { print_welcome(); let theme = ColorfulTheme::default(); let choice = Select::with_theme(&theme) .with_prompt("What do you want to do?") .items(&[ "Host (share my screen)", "View (watch someone else's screen)", ]) .default(0) .interact()?; match choice { 0 => host::run(cli.into_host_opts(true)).await, _ => { let ticket = prompt_ticket(&theme)?; viewer::run(ticket, cli.into_viewer_opts(true)).await } } } fn print_welcome() { eprintln!(); eprintln!("Welcome to PixelPass."); eprintln!(); } fn prompt_ticket(theme: &ColorfulTheme) -> Result { loop { let raw: String = Input::with_theme(theme) .with_prompt("Paste the share code you received") .interact_text()?; match EndpointTicket::from_str(raw.trim()) { Ok(t) => return Ok(t), Err(_) => eprintln!("That doesn't look like a share code. Try again."), } } } /// Player options the interactive viewer can launch. #[derive(Clone, Copy)] pub enum Player { Mpv, Vlc, } impl Player { pub fn spawn(self, url: &str) -> std::io::Result<()> { match self { Player::Mpv => crate::common::process::spawn_detached( "mpv", &[ "--profile=low-latency", "--untimed", "--hwdec=auto", "--audio-buffer=0.2", "--demuxer-max-bytes=2M", "--demuxer-readahead-secs=0.5", url, ], ), Player::Vlc => crate::common::process::spawn_detached( "vlc", &["--network-caching=200", "--live-caching=200", url], ), } } } pub fn prompt_player() -> Result { let theme = ColorfulTheme::default(); let choice = Select::with_theme(&theme) .with_prompt("Connected. Pick a player to launch") .items(&["mpv", "VLC"]) .default(0) .interact()?; Ok(if choice == 0 { Player::Mpv } else { Player::Vlc }) }