oino/modes/
interactive.rs1use std::sync::Arc;
4
5use futures::StreamExt;
6use oino_client::{InProcessBackend, SessionBackend};
7use oino_core::events::{ClientEvent, OinoEvent};
8use oino_tui::TuiOptions;
9use oino_tui::host::LocalHost;
10
11use crate::modes::signals;
12use crate::startup::{Environment, Started};
13
14pub async fn run(started: Started, env: &Environment, options: TuiOptions) -> i32 {
18 let backend = Arc::new(InProcessBackend::new(started.runtime));
19 let host = Arc::new(
22 LocalHost::new(
23 &env.cwd,
24 &env.agent_dir,
25 Some(started.sessions_root),
26 started.project_trusted,
27 )
28 .with_render(Arc::clone(&backend) as Arc<dyn SessionBackend>),
29 );
30 let ui = oino_tui::run(
31 Arc::clone(&backend) as Arc<dyn SessionBackend>,
32 host,
33 options,
34 );
35 let shutdown = backend.shutdown_requested();
36 let takeover_notice = Box::pin(async {
40 let mut events = backend.events();
41 loop {
42 match events.next().await {
43 Some(ClientEvent::Oino(OinoEvent::SessionTakenOver { by })) => {
44 return format!("Session moved to another window (by {})", by.client);
45 }
46 Some(_) => {}
47 None => std::future::pending().await,
48 }
49 }
50 });
51 let mut notice = None;
52 let code = tokio::select! {
53 () = shutdown => 0,
54 result = ui => match result {
55 Ok(()) => 0,
56 Err(error) => {
57 crate::eprintln_line(&format!("Error: {error}"));
58 1
59 }
60 },
61 taken = takeover_notice => {
62 notice = Some(taken);
63 0
64 }
65 signal = signals::next() => signal.exit_code(),
66 };
67 backend.shutdown().await;
68 if let Some(notice) = notice {
69 crate::eprintln_line(¬ice);
70 }
71 code
72}